diff --git a/docs/source/integration.rst b/docs/source/integration.rst index 51feba2..efe4196 100644 --- a/docs/source/integration.rst +++ b/docs/source/integration.rst @@ -24,6 +24,9 @@ We'll look at integration of CEL into another application from four perspectives 5. Finally, `External API`_ will review some elements of the API that are part of the integration interface. +The CEL compile and evaluation is designed to work inside a single thread. +In an application where multiple, concurrent threads will be performing CEL evaluations, each thread requires a distinct copy of a stateful :py:class:`celpy.Environment` instance. + Integration Essentials ====================== diff --git a/features/Makefile b/features/Makefile index e30b308..3028201 100644 --- a/features/Makefile +++ b/features/Makefile @@ -30,7 +30,8 @@ CEL_SPEC_PATH ?= $(HERE)../../../google/cel-spec CEL_SIMPLE_TESTDATA ?= $(CEL_SPEC_PATH)/tests/simple/testdata # This is most -- but not all -- the feature files. -# Some are built manually. These are built from textproto files. +# These are built from textproto files to assure conformance with CEL-SPEC. +# Others in this directory are built manually. FEATURES = \ basic.feature \ bindings_ext.feature \ diff --git a/features/README.rst b/features/README.rst index 57015a8..1c1a724 100644 --- a/features/README.rst +++ b/features/README.rst @@ -17,20 +17,51 @@ for the ``TestAllTypes`` protobuf definition that some tests expect to be presen Running the Conformance Tests ============================= -Run behave. +This can be done using **make** at the top level of the project. + +:: + + make test + +To test work-in-progress (WIP):: + + make test-wip + +As an alternative, this can be done by running **behave** manually, using the ``src`` directory directly (without an install of the package.) :: PYTHONPATH=src uv run behave features -To run a subset, pick a feature file. +To run a subset of the features, pick a specific file. :: PYTHONPATH=src uv run behave features/basic.feature +To run the ``@wip`` tests, include ``--tags=wip``. + +To skip the ``@wip`` tests, include ``tags=~wip``. + Building the Conformance Test Features ====================================== The ``tools`` directory has a ``gherkinize.py`` application that builds the test suite. -See the ``tools/README.rst`` for more information. +See the ``tools/README.rst`` for more information on running this application. + +Here's the bigger picture workflow: + +1. Create a ``google/cel-spec`` project parallel to this project's directory. + This should be based on https://github.com/google/cel-spec + + (Or, create it anywhere and set ``CEL_SPEC_PATH`` to refer to this directory.) + +2. Find the tag for the most recent release (e.g. ``v0.24.0``) + +3. Do ``git pull tag v0.24.0`` to get the released version. + +4. Update this ``README.rst`` to reflect the version tag actually used. + +5. Run ``make`` to copy the ``.textproto`` files to this directory and create ``feature`` files from them. + + diff --git a/pyproject.toml b/pyproject.toml index 9c88f25..9f95e98 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -85,10 +85,11 @@ dev = [ "types-protobuf>=6.32.1", "types-pyyaml>=6.0.12", "types-toml>=0.10.8", + "ipykernel>=7.2.0", ] [tool.tox] -envlist = ["py310", "py311", "py312", "py313", "lint", "tools"] +envlist = ["py310", "py311", "py312", "py313", "py314", "lint", "tools"] minversion = "4.24.0" [tool.tox.env_run_base] diff --git a/src/celpy/__init__.py b/src/celpy/__init__.py index df0c202..3d5b40e 100644 --- a/src/celpy/__init__.py +++ b/src/celpy/__init__.py @@ -269,6 +269,10 @@ class Environment: At this time, external functions are bound to the CEL expression. The :py:class:`celpy.Runnable` can be evaluated repeatedly with multiple inputs, avoiding the overheads of compiling for each input value. + .. note:: This cannot be shared by multiple threads. + + Each thread must have an ``Environment`` instance. + .. todo:: For a better fit with Go language expectations - A type adapters registry makes other native types available for CEL. diff --git a/tests/test_adapter.py b/tests/test_adapter.py index f63ba54..2a39a63 100644 --- a/tests/test_adapter.py +++ b/tests/test_adapter.py @@ -16,6 +16,7 @@ """ C7N Type Adapter Test Cases. """ + import datetime import celpy.adapter @@ -28,7 +29,9 @@ 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( [ @@ -36,7 +39,9 @@ def test_json_to_cel(): 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!"), @@ -44,14 +49,12 @@ def test_json_to_cel(): ) 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") diff --git a/tests/test_c7n_to_cel.py b/tests/test_c7n_to_cel.py index 85b68c2..1590adf 100644 --- a/tests/test_c7n_to_cel.py +++ b/tests/test_c7n_to_cel.py @@ -16,6 +16,7 @@ """ C7N Integration Translation Test Cases. """ + from unittest.mock import Mock, call, sentinel from pytest import * @@ -32,92 +33,102 @@ def test_q(): def test_age_to_duration(): assert C7N_Rewriter.age_to_duration(1) == '"1d"' - assert C7N_Rewriter.age_to_duration(.5) == '"12h"' - assert C7N_Rewriter.age_to_duration(.084) == '"2h57s"' - assert C7N_Rewriter.age_to_duration(.011) == '"15m50s"' + assert C7N_Rewriter.age_to_duration(0.5) == '"12h"' + assert C7N_Rewriter.age_to_duration(0.084) == '"2h57s"' + assert C7N_Rewriter.age_to_duration(0.011) == '"15m50s"' @fixture def mock_logical_connector(monkeypatch): - logical_connector = Mock( - return_value=sentinel.rewritten - ) - monkeypatch.setattr(C7N_Rewriter, 'logical_connector', logical_connector) + logical_connector = Mock(return_value=sentinel.rewritten) + monkeypatch.setattr(C7N_Rewriter, "logical_connector", logical_connector) return logical_connector def test_c7n_rewrite(mock_logical_connector): - assert C7N_Rewriter.c7n_rewrite('name: policy\nfilters: "text"\n') == sentinel.rewritten + assert ( + C7N_Rewriter.c7n_rewrite('name: policy\nfilters: "text"\n') + == sentinel.rewritten + ) assert mock_logical_connector.mock_calls == [call(None, "text")] @fixture def mock_type_value_rewrite(monkeypatch): - type_value_rewrite = Mock( - return_value=str(sentinel.rewritten) - ) - monkeypatch.setattr(C7N_Rewriter, 'type_value_rewrite', type_value_rewrite) + type_value_rewrite = Mock(return_value=str(sentinel.rewritten)) + monkeypatch.setattr(C7N_Rewriter, "type_value_rewrite", type_value_rewrite) return type_value_rewrite @fixture def mock_type_marked_for_op_rewrite(monkeypatch): - type_marked_for_op_rewrite = Mock( - return_value=str(sentinel.rewritten) + type_marked_for_op_rewrite = Mock(return_value=str(sentinel.rewritten)) + monkeypatch.setattr( + C7N_Rewriter, "type_marked_for_op_rewrite", type_marked_for_op_rewrite ) - monkeypatch.setattr(C7N_Rewriter, 'type_marked_for_op_rewrite', type_marked_for_op_rewrite) return type_marked_for_op_rewrite + @fixture def mock_type_image_age_rewrite(monkeypatch): - type_image_age_rewrite = Mock( - return_value=str(sentinel.rewritten) - ) - monkeypatch.setattr(C7N_Rewriter, 'type_image_age_rewrite', type_image_age_rewrite) + type_image_age_rewrite = Mock(return_value=str(sentinel.rewritten)) + monkeypatch.setattr(C7N_Rewriter, "type_image_age_rewrite", type_image_age_rewrite) return type_image_age_rewrite + @fixture def mock_type_event_rewrite(monkeypatch): - type_event_rewrite = Mock( - return_value=str(sentinel.rewritten) - ) - monkeypatch.setattr(C7N_Rewriter, 'type_event_rewrite', type_event_rewrite) + type_event_rewrite = Mock(return_value=str(sentinel.rewritten)) + monkeypatch.setattr(C7N_Rewriter, "type_event_rewrite", type_event_rewrite) return type_event_rewrite def test_logical_connector_list(mock_type_value_rewrite): - assert C7N_Rewriter.logical_connector(sentinel.resource, [{"type": "value"}]) == str(sentinel.rewritten) - assert mock_type_value_rewrite.mock_calls == [call(sentinel.resource, {'type': 'value'})] + assert C7N_Rewriter.logical_connector( + sentinel.resource, [{"type": "value"}] + ) == str(sentinel.rewritten) + assert mock_type_value_rewrite.mock_calls == [ + call(sentinel.resource, {"type": "value"}) + ] def test_logical_connector_and(mock_type_value_rewrite): - assert C7N_Rewriter.logical_connector(sentinel.resource, {"and": [{"type": "value"}]}) == str(sentinel.rewritten) - assert mock_type_value_rewrite.mock_calls == [call(sentinel.resource, {'type': 'value'})] + assert C7N_Rewriter.logical_connector( + sentinel.resource, {"and": [{"type": "value"}]} + ) == str(sentinel.rewritten) + assert mock_type_value_rewrite.mock_calls == [ + call(sentinel.resource, {"type": "value"}) + ] def test_logical_connector_or(mock_type_value_rewrite): # Note the singleton or; this is common. - assert C7N_Rewriter.logical_connector(sentinel.resource, {"or": [{"type": "value"}]}) == str(sentinel.rewritten) - assert mock_type_value_rewrite.mock_calls == [call(sentinel.resource, {'type': 'value'})] + assert C7N_Rewriter.logical_connector( + sentinel.resource, {"or": [{"type": "value"}]} + ) == str(sentinel.rewritten) + assert mock_type_value_rewrite.mock_calls == [ + call(sentinel.resource, {"type": "value"}) + ] def test_logical_connector_not_1(mock_type_value_rewrite): not_1 = {"not": [{"type": "value"}]} assert ( - C7N_Rewriter.logical_connector(sentinel.resource, not_1) == f"! ({str(sentinel.rewritten)})" + C7N_Rewriter.logical_connector(sentinel.resource, not_1) + == f"! ({str(sentinel.rewritten)})" ) - assert mock_type_value_rewrite.mock_calls == [call(sentinel.resource, {'type': 'value'})] + assert mock_type_value_rewrite.mock_calls == [ + call(sentinel.resource, {"type": "value"}) + ] def test_logical_connector_not_2(mock_type_value_rewrite): not_2 = {"not": [{"type": "value", "value": 1}, {"type": "value", "value": 2}]} expected_2 = f"! ({str(sentinel.rewritten)} && {str(sentinel.rewritten)})" - assert ( - C7N_Rewriter.logical_connector(sentinel.resource, not_2) == expected_2 - ) + assert C7N_Rewriter.logical_connector(sentinel.resource, not_2) == expected_2 assert mock_type_value_rewrite.mock_calls == [ - call(sentinel.resource, {'type': 'value', 'value': 1}), - call(sentinel.resource, {'type': 'value', 'value': 2}) + call(sentinel.resource, {"type": "value", "value": 1}), + call(sentinel.resource, {"type": "value", "value": 2}), ] @@ -130,76 +141,98 @@ def test_logical_connector_errors(mock_type_value_rewrite): @fixture def mock_key_to_cel(monkeypatch): - key_to_cel = Mock( - return_value=str(sentinel.rewritten) - ) - monkeypatch.setattr(C7N_Rewriter, 'key_to_cel', key_to_cel) + key_to_cel = Mock(return_value=str(sentinel.rewritten)) + monkeypatch.setattr(C7N_Rewriter, "key_to_cel", key_to_cel) return key_to_cel @fixture def mock_value_to_cel(monkeypatch): - value_to_cel = Mock( - return_value=str(sentinel.rewritten) - ) - monkeypatch.setattr(C7N_Rewriter, 'value_to_cel', value_to_cel) + value_to_cel = Mock(return_value=str(sentinel.rewritten)) + monkeypatch.setattr(C7N_Rewriter, "value_to_cel", value_to_cel) return value_to_cel @fixture def mock_value_from_to_cel(monkeypatch): - value_from_to_cel = Mock( - return_value=str(sentinel.rewritten) - ) - monkeypatch.setattr(C7N_Rewriter, 'value_from_to_cel', value_from_to_cel) + value_from_to_cel = Mock(return_value=str(sentinel.rewritten)) + monkeypatch.setattr(C7N_Rewriter, "value_from_to_cel", value_from_to_cel) return value_from_to_cel def test_type_value_rewrite(mock_key_to_cel, mock_value_to_cel): clause = {"key": "key", "op": "eq", "value": 42} - assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str(sentinel.rewritten) + assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str( + sentinel.rewritten + ) assert mock_key_to_cel.mock_calls == [call("key")] - assert mock_value_to_cel.mock_calls == [call(str(sentinel.rewritten), "eq", 42, None)] + assert mock_value_to_cel.mock_calls == [ + call(str(sentinel.rewritten), "eq", 42, None) + ] def test_type_value_rewrite_present(mock_key_to_cel, mock_value_to_cel): clause = {"key": "key", "value": "present"} - assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str(sentinel.rewritten) + assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str( + sentinel.rewritten + ) assert mock_key_to_cel.mock_calls == [call("key")] - assert mock_value_to_cel.mock_calls == [call(str(sentinel.rewritten), "__present__", None)] + assert mock_value_to_cel.mock_calls == [ + call(str(sentinel.rewritten), "__present__", None) + ] def test_type_value_rewrite_not_null(mock_key_to_cel, mock_value_to_cel): clause = {"key": "key", "value": "not-null"} - assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str(sentinel.rewritten) + assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str( + sentinel.rewritten + ) assert mock_key_to_cel.mock_calls == [call("key")] - assert mock_value_to_cel.mock_calls == [call(str(sentinel.rewritten), "__present__", None)] + assert mock_value_to_cel.mock_calls == [ + call(str(sentinel.rewritten), "__present__", None) + ] def test_type_value_rewrite_absent(mock_key_to_cel, mock_value_to_cel): clause = {"key": "key", "value": "absent"} - assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str(sentinel.rewritten) + assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str( + sentinel.rewritten + ) assert mock_key_to_cel.mock_calls == [call("key")] - assert mock_value_to_cel.mock_calls == [call(str(sentinel.rewritten), "__absent__", None)] + assert mock_value_to_cel.mock_calls == [ + call(str(sentinel.rewritten), "__absent__", None) + ] def test_type_value_rewrite_emptu(mock_key_to_cel, mock_value_to_cel): clause = {"key": "key", "value": "empty"} - assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str(sentinel.rewritten) + assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str( + sentinel.rewritten + ) assert mock_key_to_cel.mock_calls == [call("key")] - assert mock_value_to_cel.mock_calls == [call(str(sentinel.rewritten), "__absent__", None)] + assert mock_value_to_cel.mock_calls == [ + call(str(sentinel.rewritten), "__absent__", None) + ] def test_tag_absent(mock_key_to_cel, mock_value_to_cel): clause = {"tag:aws:autoscaling:groupName": "absent"} - assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str(sentinel.rewritten) + assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str( + sentinel.rewritten + ) assert mock_key_to_cel.mock_calls == [call("tag:aws:autoscaling:groupName")] - assert mock_value_to_cel.mock_calls == [call(str(sentinel.rewritten), "__absent__", None)] + assert mock_value_to_cel.mock_calls == [ + call(str(sentinel.rewritten), "__absent__", None) + ] def test_primitive_value(mock_type_value_rewrite): - assert C7N_Rewriter.primitive(sentinel.resource, {"type": "value"}) == str(sentinel.rewritten) - assert mock_type_value_rewrite.mock_calls == [call(sentinel.resource, {'type': 'value'})] + assert C7N_Rewriter.primitive(sentinel.resource, {"type": "value"}) == str( + sentinel.rewritten + ) + assert mock_type_value_rewrite.mock_calls == [ + call(sentinel.resource, {"type": "value"}) + ] def test_primitive_absent(mock_type_value_rewrite): @@ -210,7 +243,9 @@ def test_primitive_absent(mock_type_value_rewrite): def test_type_value_from_rewrite(mock_key_to_cel, mock_value_from_to_cel): clause = {"key": "key", "op": "in", "value_from": {"url": "url"}} - assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str(sentinel.rewritten) + assert C7N_Rewriter.type_value_rewrite(sentinel.resource, clause) == str( + sentinel.rewritten + ) assert mock_key_to_cel.mock_calls == [call("key")] assert mock_value_from_to_cel.mock_calls == [ call(str(sentinel.rewritten), "in", {"url": "url"}) @@ -236,11 +271,11 @@ def test_value_from_to_cel(): assert C7N_Rewriter.value_from_to_cel("key", "in", value_from_2) == expected_2 value_from_3 = {"url": "url://path", "expr": "jmespath"} - expected_3 = 'value_from("url://path").jmes_path(\'jmespath\').contains(key)' + expected_3 = "value_from(\"url://path\").jmes_path('jmespath').contains(key)" assert C7N_Rewriter.value_from_to_cel("key", "in", value_from_3) == expected_3 value_from_4 = {"url": "url://path", "expr": "jmespath{account-id}"} - expected_4 = 'value_from("url://path").jmes_path(subst(\'jmespath{account-id}\')).contains(key)' + expected_4 = "value_from(\"url://path\").jmes_path(subst('jmespath{account-id}')).contains(key)" assert C7N_Rewriter.value_from_to_cel("key", None, value_from_4) == expected_4 @@ -259,48 +294,48 @@ def test_value_to_cel_boolean(): def test_value_to_cel_non_bool(): assert ( - C7N_Rewriter.value_to_cel("key", "eq", "some_string") == 'key == "some_string"' + C7N_Rewriter.value_to_cel("key", "eq", "some_string") == 'key == "some_string"' ) + assert C7N_Rewriter.value_to_cel("key", "gt", 42) == "key > 42" assert ( - C7N_Rewriter.value_to_cel("key", "gt", 42) == 'key > 42' + C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="age") + == 'now - duration("42d") > timestamp(key)' ) assert ( - C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="age") - == 'now - duration("42d") > timestamp(key)' + C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="integer") + == "int(key) > 42" ) assert ( - C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="integer") == 'int(key) > 42' + C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="expiration") + == 'timestamp(key) > now + duration("42d")' ) assert ( - C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="expiration") - == 'timestamp(key) > now + duration("42d")' + C7N_Rewriter.value_to_cel("key", "eq", "some_string", value_type="normalize") + == 'normalize(key) == "some_string"' ) assert ( - C7N_Rewriter.value_to_cel("key", "eq", "some_string", value_type="normalize") - == 'normalize(key) == "some_string"' + C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="size") + == "size(key) > 42" ) assert ( - C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="size") == 'size(key) > 42' + C7N_Rewriter.value_to_cel("key", "ne", "127.0.0.1/22", value_type="cidr") + == 'parse_cidr(key) != parse_cidr("127.0.0.1/22")' ) assert ( - C7N_Rewriter.value_to_cel("key", "ne", "127.0.0.1/22", value_type="cidr") - == 'parse_cidr(key) != parse_cidr("127.0.0.1/22")' + C7N_Rewriter.value_to_cel("key", "gt", "127.0.0.1/22", value_type="cidr_size") + == 'size_parse_cidr(key) > "127.0.0.1/22"' ) assert ( - C7N_Rewriter.value_to_cel("key", "gt", "127.0.0.1/22", value_type="cidr_size") - == 'size_parse_cidr(key) > "127.0.0.1/22"' + C7N_Rewriter.value_to_cel("key", "eq", "some_string", value_type="swap") + == '"some_string" == key' ) assert ( - C7N_Rewriter.value_to_cel("key", "eq", "some_string", value_type="swap") - == '"some_string" == key' + C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="unique_size") + == "unique_size(key) > 42" ) assert ( - C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="unique_size") - == 'unique_size(key) > 42' - ) - assert ( - C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="date") - == 'timestamp(key) > timestamp(42)' + C7N_Rewriter.value_to_cel("key", "gt", 42, value_type="date") + == "timestamp(key) > timestamp(42)" ) assert ( C7N_Rewriter.value_to_cel("key", "gt", "3.8.5", value_type="version") @@ -309,71 +344,80 @@ def test_value_to_cel_non_bool(): def test_key_to_cel(): + assert C7N_Rewriter.key_to_cel("length(key)") == 'size(resource["key"])' + assert C7N_Rewriter.key_to_cel("Key.Subkey") == 'resource["Key"]["Subkey"]' assert ( - C7N_Rewriter.key_to_cel("length(key)") == 'size(resource["key"])' - ) - assert ( - C7N_Rewriter.key_to_cel("Key.Subkey") == 'resource["Key"]["Subkey"]' - ) - assert ( - C7N_Rewriter.key_to_cel("tag:TagName") - == 'resource["Tags"].filter(x, x["Key"] == "TagName")[0]["Value"]' - ) - assert ( - C7N_Rewriter.key_to_cel("key") == 'resource["key"]' + C7N_Rewriter.key_to_cel("tag:TagName") + == 'resource["Tags"].filter(x, x["Key"] == "TagName")[0]["Value"]' ) + assert C7N_Rewriter.key_to_cel("key") == 'resource["key"]' def test_marked_for_op_rewrite(mock_key_to_cel): - clause = {"op": "terminate", "skew": 4, "tag": "c7n-tag-compliance", "type": "marked-for-op"} + clause = { + "op": "terminate", + "skew": 4, + "tag": "c7n-tag-compliance", + "type": "marked-for-op", + } expected = ( - 'resource["Tags"].marked_key("c7n-tag-compliance").action == "terminate" ' - '&& now >= resource["Tags"].marked_key("c7n-tag-compliance").action_date ' - '- duration("4d0h")' + 'resource["Tags"].marked_key("c7n-tag-compliance").action == "terminate" ' + '&& now >= resource["Tags"].marked_key("c7n-tag-compliance").action_date ' + '- duration("4d0h")' + ) + assert ( + C7N_Rewriter.type_marked_for_op_rewrite(sentinel.resource, clause) == expected ) - assert C7N_Rewriter.type_marked_for_op_rewrite(sentinel.resource, clause) == expected def test_primitive_mark_for_op(mock_type_marked_for_op_rewrite): - assert C7N_Rewriter.primitive(sentinel.resource, {"type": "marked-for-op"}) == str(sentinel.rewritten) - assert mock_type_marked_for_op_rewrite.mock_calls == [call(sentinel.resource, {'type': 'marked-for-op'})] + assert C7N_Rewriter.primitive(sentinel.resource, {"type": "marked-for-op"}) == str( + sentinel.rewritten + ) + assert mock_type_marked_for_op_rewrite.mock_calls == [ + call(sentinel.resource, {"type": "marked-for-op"}) + ] def test_image_age_rewrite(): clause = {"days": 60, "op": "gt", "type": "image-age"} - expected = ( - 'now - resource.image().CreationDate > duration("60d")' - ) + expected = 'now - resource.image().CreationDate > duration("60d")' assert C7N_Rewriter.type_image_age_rewrite(sentinel.resource, clause) == expected def test_image_rewrite(): clause = {"key": "Name", "op": "regex", "type": "image", "value": "(?!WIN.*)"} - expected = ( - 'resource.image().Name.matches("(?!WIN.*)")' - ) + expected = 'resource.image().Name.matches("(?!WIN.*)")' assert C7N_Rewriter.type_image_rewrite(sentinel.resource, clause) == expected def test_primitive_image_age(mock_type_image_age_rewrite): - assert C7N_Rewriter.primitive(sentinel.resource, {"type": "image-age"}) == str(sentinel.rewritten) - assert mock_type_image_age_rewrite.mock_calls == [call(sentinel.resource, {'type': 'image-age'})] + assert C7N_Rewriter.primitive(sentinel.resource, {"type": "image-age"}) == str( + sentinel.rewritten + ) + assert mock_type_image_age_rewrite.mock_calls == [ + call(sentinel.resource, {"type": "image-age"}) + ] def test_event_rewrite(): clause = { - "key": "detail.responseElements.functionName", "op": "regex", "type": "event", - "value": "^(custodian-.*)" + "key": "detail.responseElements.functionName", + "op": "regex", + "type": "event", + "value": "^(custodian-.*)", } - expected = ( - 'event.detail.responseElements.functionName.matches("^(custodian-.*)")' - ) + expected = 'event.detail.responseElements.functionName.matches("^(custodian-.*)")' assert C7N_Rewriter.type_event_rewrite(sentinel.resource, clause) == expected def test_primitive_event(mock_type_event_rewrite): - assert C7N_Rewriter.primitive(sentinel.resource, {"type": "event"}) == str(sentinel.rewritten) - assert mock_type_event_rewrite.mock_calls == [call(sentinel.resource, {'type': 'event'})] + assert C7N_Rewriter.primitive(sentinel.resource, {"type": "event"}) == str( + sentinel.rewritten + ) + assert mock_type_event_rewrite.mock_calls == [ + call(sentinel.resource, {"type": "event"}) + ] def test_metrics_rewrite_simple(): @@ -386,10 +430,10 @@ def test_metrics_rewrite_simple(): "op": "less-than", } expected = ( - 'resource.get_metrics(' + "resource.get_metrics(" '{"MetricName": "CPUUtilization", "Statistic": "Average", ' '"StartTime": now - duration("4d"), "EndTime": now, "Period": duration("1d")})' - '.exists(m, m < 30)' + ".exists(m, m < 30)" ) assert C7N_Rewriter.type_metrics_rewrite(sentinel.resource, clause) == expected @@ -405,43 +449,55 @@ def test_metrics_rewrite_missing_value(): "missing-value": 0, } expected = ( - 'resource.get_metrics(' + "resource.get_metrics(" '{"MetricName": "RequestCount", "Statistic": "Sum", ' '"StartTime": now - duration("7d"), "EndTime": now, "Period": duration("7d")})' - '.map(m, m == null ? 0 : m)' - '.exists(m, m < 7)' + ".map(m, m == null ? 0 : m)" + ".exists(m, m < 7)" ) assert C7N_Rewriter.type_metrics_rewrite(sentinel.resource, clause) == expected + def test_age_rewrite(): clause = {"days": 21, "op": "gt", "type": "age"} - expected = ( - 'now - timestamp(resource.StartTime) > duration("21d")' - ) + expected = 'now - timestamp(resource.StartTime) > duration("21d")' assert C7N_Rewriter.type_age_rewrite("ebs-snapshot", clause) == expected + def test_security_group_rewrite(): clause_0 = { - "key": "GroupId", "op": "in", "type": "security-group", - "value": ["sg-12345678", "sg-23456789", "sg-34567890"] + "key": "GroupId", + "op": "in", + "type": "security-group", + "value": ["sg-12345678", "sg-23456789", "sg-34567890"], } - expected = 'resource.SecurityGroups.map(sg, sg.GroupId.security_group()).exists(sg, [\'sg-12345678\', \'sg-23456789\', \'sg-34567890\'].contains(sg["GroupId"]))' + expected = "resource.SecurityGroups.map(sg, sg.GroupId.security_group()).exists(sg, ['sg-12345678', 'sg-23456789', 'sg-34567890'].contains(sg[\"GroupId\"]))" assert C7N_Rewriter.type_security_group_rewrite("ec2", clause_0) == expected clause_1 = { - "key": "GroupName", "op": "regex", "type": "security-group", - "value": "^Enterprise-AllInstances-SG.*$"} - expected = 'resource.SecurityGroups.map(sg, sg.GroupId.security_group()).exists(sg, sg["GroupName"].matches(\'^Enterprise-AllInstances-SG.*$\'))' + "key": "GroupName", + "op": "regex", + "type": "security-group", + "value": "^Enterprise-AllInstances-SG.*$", + } + expected = "resource.SecurityGroups.map(sg, sg.GroupId.security_group()).exists(sg, sg[\"GroupName\"].matches('^Enterprise-AllInstances-SG.*$'))" assert C7N_Rewriter.type_security_group_rewrite("ec2", clause_1) == expected - clause_2 = {"key": "tag:ASSET", "op": "eq", "type": "security-group", "value": "SPECIALASSETNAME"} + clause_2 = { + "key": "tag:ASSET", + "op": "eq", + "type": "security-group", + "value": "SPECIALASSETNAME", + } expected = 'resource.SecurityGroups.map(sg, sg.GroupId.security_group()).exists(sg, sg["Tags"].filter(x, x["Key"] == "ASSET")[0]["Value"] == \'SPECIALASSETNAME\')' assert C7N_Rewriter.type_security_group_rewrite("ec2", clause_2) == expected def test_subnet_rewrite(): clause_0 = { - "key": "SubnetId", "op": "in", "type": "subnet-group", + "key": "SubnetId", + "op": "in", + "type": "subnet-group", "value_from": {"format": "txt", "url": "s3://path-to-resource/subnets.txt"}, "value_type": "normalize", } @@ -451,57 +507,74 @@ def test_subnet_rewrite(): def test_flow_logs_rewrite(): clause_0 = { - "enabled": False, "type": "flow-logs", + "enabled": False, + "type": "flow-logs", } - expected = 'size(resource.flow_logs()) == 0' + expected = "size(resource.flow_logs()) == 0" assert C7N_Rewriter.type_flow_log_rewrite("vpc", clause_0) == expected clause_1 = { - "enabled": "true", "type": "flow-logs", "destination-type": "s3", + "enabled": "true", + "type": "flow-logs", + "destination-type": "s3", } expected = 'size(resource.flow_logs()) != 0 && (resource.flow_logs().exists(x, x.LogDestinationType == "s3"))' assert C7N_Rewriter.type_flow_log_rewrite("vpc", clause_1) == expected - clause_2 = {'type': 'flow-logs', 'enabled': True, - 'set-op': 'or', 'op': 'equal', 'traffic-type': 'all', 'status': 'active', - 'log-group': 'vpc-logs'} + clause_2 = { + "type": "flow-logs", + "enabled": True, + "set-op": "or", + "op": "equal", + "traffic-type": "all", + "status": "active", + "log-group": "vpc-logs", + } expected = 'size(resource.flow_logs()) != 0 && (resource.flow_logs().exists(x, x.LogGroupName == "vpc-logs") || resource.flow_logs().exists(x, x.TrafficType == "ALL") || resource.flow_logs().exists(x, x.FlowLogStatus == "active"))' assert C7N_Rewriter.type_flow_log_rewrite("vpc", clause_2) == expected - clause_3 = {'type': 'flow-logs', 'enabled': True, - "log-format": "this", "destination": "that", "deliver-status": "the-other-thing"} + clause_3 = { + "type": "flow-logs", + "enabled": True, + "log-format": "this", + "destination": "that", + "deliver-status": "the-other-thing", + } expected = 'size(resource.flow_logs()) != 0 && (resource.flow_logs().exists(x, x.LogFormat == "this") || resource.flow_logs().exists(x, x.LogDestination == "that") || resource.flow_logs().exists(x, x.DeliverLogsStatus == "the-other-thing"))' assert C7N_Rewriter.type_flow_log_rewrite("vpc", clause_3) == expected def test_tag_count_rewrite(): - clause_0 = { - "type": "tag-count", "op": "gte", "count": 8 - } + clause_0 = {"type": "tag-count", "op": "gte", "count": 8} expected = 'size(resource["Tags"].filter(x, ! matches(x.Key, "^aws:.*"))) >= 8' assert C7N_Rewriter.type_tag_count_rewrite("elb", clause_0) == expected - clause_1 = { - "type": "tag-count", "op": "gte", "count": 8 - } + clause_1 = {"type": "tag-count", "op": "gte", "count": 8} expected = 'size(resource["Tags"].filter(x, ! matches(x.Key, "^aws:.*"))) >= 8' assert C7N_Rewriter.type_tag_count_rewrite("elb", clause_1) == expected def test_type_vpc_rewrite(): clause_0 = { - "key": "VpcId", "op": "not-in", "type": "vpc", + "key": "VpcId", + "op": "not-in", + "type": "vpc", "value_from": { "url": "s3://c7n-resources/some_list.json", "format": "json", - "expr": 'not_null(offhours_exceptions."{account_id}".account, "[]")'.format(account_id="123456789012") - } + "expr": 'not_null(offhours_exceptions."{account_id}".account, "[]")'.format( + account_id="123456789012" + ), + }, } - expected = '! value_from("s3://c7n-resources/some_list.json", "json").jmes_path(\'not_null(offhours_exceptions."123456789012".account, \"[]\")\').contains(resource.VPCId)' + expected = '! value_from("s3://c7n-resources/some_list.json", "json").jmes_path(\'not_null(offhours_exceptions."123456789012".account, "[]")\').contains(resource.VPCId)' assert C7N_Rewriter.type_vpc_rewrite("elb", clause_0) == expected clause_1 = { - "key": "VpcId", "op": "not-equal", "type": "vpc", "value": "vpc-12ab34de" + "key": "VpcId", + "op": "not-equal", + "type": "vpc", + "value": "vpc-12ab34de", } expected = 'resource.VPCId != "vpc-12ab34de"' assert C7N_Rewriter.type_vpc_rewrite("elb", clause_1) == expected @@ -513,7 +586,7 @@ def test_type_credential_rewrite(): "op": "gte", "type": "credential", "value": 55, - "value_type": "age" + "value_type": "age", } expected = 'now - duration("55d") >= timestamp(resource.credentials().access_keys.last_rotated)' assert C7N_Rewriter.type_credential_rewrite("elb", clause_0) == expected @@ -521,7 +594,10 @@ def test_type_credential_rewrite(): def test_type_kms_alias_rewrite(): clause_0 = { - "key": "AliasName", "op": "regex", "type": "kms-alias", "value": "^(alias/aws/)" + "key": "AliasName", + "op": "regex", + "type": "kms-alias", + "value": "^(alias/aws/)", } expected = 'resource.kms_alias().AliasName.matches("^(alias/aws/)")' assert C7N_Rewriter.type_kms_alias_rewrite("elb", clause_0) == expected @@ -529,35 +605,34 @@ def test_type_kms_alias_rewrite(): def test_type_kms_key_rewrite(): clause_0 = { - "key": "c7n:AliasName", "op": "regex", "type": "kms-key", - "value": "^(alias/enterprise/sns/encrypted)" + "key": "c7n:AliasName", + "op": "regex", + "type": "kms-key", + "value": "^(alias/enterprise/sns/encrypted)", } expected = 'resource.KmsKeyId.kms_key()["Aliases"][0]["AliasName"].matches("^(alias/enterprise/sns/encrypted)")' assert C7N_Rewriter.type_kms_key_rewrite("efs", clause_0) == expected clause_1 = { - "key": "AliasName", "op": "regex", "type": "kms-key", "value": "^(alias/aws/)" + "key": "AliasName", + "op": "regex", + "type": "kms-key", + "value": "^(alias/aws/)", } expected = 'resource.KmsKeyId.kms_key()["AliasName"].matches("^(alias/aws/)")' assert C7N_Rewriter.type_kms_key_rewrite("efs", clause_1) == expected def test_onhour_rewrite(): - clause_0 = { - "default_tz": "et", - "onhour": 7, - "opt-out": True, - "type": "onhour" - - } + clause_0 = {"default_tz": "et", "onhour": 7, "opt-out": True, "type": "onhour"} expected_0 = 'resource.Tags.exists(x, x.key=="maid_offhours") ? false : (now.getDayOfWeek("et") in [0, 1, 2, 3, 4] && now.getHours("et") == 7)' assert C7N_Rewriter.onhour_rewrite("efs", clause_0) == expected_0 clause_1 = { "default_tz": "et", "onhour": 7, - "skip-days": ['2019-11-11', '2019-11-28', '2019-12-25', '2020-01-01'], + "skip-days": ["2019-11-11", "2019-11-28", "2019-12-25", "2020-01-01"], "tag": "custodian_downtime", - "type": "onhour" + "type": "onhour", } expected_1 = '! getDate(now) in ["2019-11-11", "2019-11-28", "2019-12-25", "2020-01-01"].map(d, getDate(timestamp(d))) && resource.Tags.exists(x, x.key=="custodian_downtime") ? resource.Tags.key("custodian_downtime").resource_schedule().on.exists(s, now.getDayOfWeek(s.tz) in s.days && now.getHours(s.tz) == s.hour) || (now.getDayOfWeek("et") in [0, 1, 2, 3, 4] && now.getHours("et") == 7) : false' assert C7N_Rewriter.onhour_rewrite("efs", clause_1) == expected_1 @@ -565,8 +640,12 @@ def test_onhour_rewrite(): def test_offhour_rewrite(): clause_2 = { - "type": "offhour", "weekends": False, "default_tz": "pt", - "tag": "datetime", "opt-out": True, "offhour": 20 + "type": "offhour", + "weekends": False, + "default_tz": "pt", + "tag": "datetime", + "opt-out": True, + "offhour": 20, } expected_2 = 'resource.Tags.exists(x, x.key=="datetime") ? false : (now.getDayOfWeek("pt") in [0, 1, 2, 3, 4, 5, 6] && now.getHours("pt") == 20)' assert C7N_Rewriter.offhour_rewrite("efs", clause_2) == expected_2 @@ -581,7 +660,7 @@ def test_cross_account_rewrite(): clause_1 = { "type": "cross-account", - "whitelist": ["permitted-account-01", "permitted-account-02"] + "whitelist": ["permitted-account-01", "permitted-account-02"], } expected_1 = 'size(resource.map(r, r["VaultName"])["policy"]["Policy"]).filter(acct, ! acct in ["permitted-account-01", "permitted-account-02"])) > 0' assert C7N_Rewriter.cross_account_rewrite("glacier", clause_1) == expected_1 @@ -590,8 +669,8 @@ def test_cross_account_rewrite(): "type": "cross-account", "whitelist_from": { "expr": "accounts.*.accountNumber", - "url": "http://server/path/to/data.json" - } + "url": "http://server/path/to/data.json", + }, } expected_2 = 'size(resource.map(r, r["VaultName"])["policy"]["Policy"]).filter(acct, ! acct in json_from("http://server/path/to/data.json", "json").jmes_path("accounts.*.accountNumber"))) > 0' assert C7N_Rewriter.cross_account_rewrite("glacier", clause_2) == expected_2 @@ -600,9 +679,9 @@ def test_cross_account_rewrite(): "type": "cross-account", "whitelist_from": { "expr": "accounts.*.account", - "url": "http://server/path/to/data.json" + "url": "http://server/path/to/data.json", }, - "whitelist_orgids": ["o-rhymjmbbe"] + "whitelist_orgids": ["o-rhymjmbbe"], } expected_3 = 'size(resource.map(r, r["VaultName"])["policy"]["Policy"]).filter(acct, ! acct in json_from("http://server/path/to/data.json", "json").jmes_path("accounts.*.account")).filter(p, ! p.attr in ["o-rhymjmbbe"])) > 0' assert C7N_Rewriter.cross_account_rewrite("glacier", clause_3) == expected_3 @@ -610,7 +689,9 @@ def test_cross_account_rewrite(): def test_used_rewrite(): clause_0 = {"type": "used"} - expected_0 = 'resource["LaunchConfigurationName"] in all_launch_configuration_names()' + expected_0 = ( + 'resource["LaunchConfigurationName"] in all_launch_configuration_names()' + ) assert C7N_Rewriter.used_rewrite("asg", clause_0) == expected_0 clause_1 = "used" assert C7N_Rewriter.primitive("asg", clause_1) == expected_0 @@ -618,7 +699,9 @@ def test_used_rewrite(): def test_unused_rewrite(): clause_0 = {"type": "unused"} - expected_0 = '! resource["LaunchConfigurationName"] in all_launch_configuration_names()' + expected_0 = ( + '! resource["LaunchConfigurationName"] in all_launch_configuration_names()' + ) assert C7N_Rewriter.unused_rewrite("asg", clause_0) == expected_0 clause_1 = "unused" assert C7N_Rewriter.primitive("asg", clause_1) == expected_0 @@ -655,47 +738,52 @@ def test_health_event_rewrite(): def test_shield_enabled_rewrite(): clause_0 = {"type": "shield-enabled", "state": False} - expected_0 = '! resource.shield_protection()' + expected_0 = "! resource.shield_protection()" assert C7N_Rewriter.shield_enabled_rewrite("elb", clause_0) == expected_0 - expected_1 = '! resource.shield_subscription()' + expected_1 = "! resource.shield_subscription()" assert C7N_Rewriter.primitive("account", clause_0) == expected_1 def test_waf_enabled_rewrite(): - clause_0 = {"type": "waf-enabled", "state": False, "web-acl": "WebACL to allow or restrict by IP"} + clause_0 = { + "type": "waf-enabled", + "state": False, + "web-acl": "WebACL to allow or restrict by IP", + } expected_0 = '! resource.web_acls().contains("WebACL to allow or restrict by IP")' assert C7N_Rewriter.waf_enabled_rewrite("distribution", clause_0) == expected_0 def test_network_location_rewrite(): clause_0 = { - 'compare': ['resource', 'security-group'], - 'ignore': [ - {'Description': 'New VPC Enterprise All Instances SG 2016'}, - {'Description': 'Enterprise All Instances Security Group'}, - {'Description': 'CoreServicesAccess-SG'}, - {'tag:Asset': 'SomeAssetTag'}], - 'key': 'tag:Asset', - 'max-cardinality': 1, - 'missing-ok': False, - 'type': 'network-location' + "compare": ["resource", "security-group"], + "ignore": [ + {"Description": "New VPC Enterprise All Instances SG 2016"}, + {"Description": "Enterprise All Instances Security Group"}, + {"Description": "CoreServicesAccess-SG"}, + {"tag:Asset": "SomeAssetTag"}, + ], + "key": "tag:Asset", + "max-cardinality": 1, + "missing-ok": False, + "type": "network-location", } expected_0 = ( '! (["New VPC Enterprise All Instances SG 2016", "Enterprise All Instances Security Group", "CoreServicesAccess-SG"].contains(resource.Description) || ["SomeAssetTag"].contains(resource.Tags["Asset"])) ' '&& (resource.SecurityGroupId.security_group().Tags["Asset"] == resource.Tags["Asset"]) ' - '&& (size(resource.SecurityGroupId.security_group()) == 1)' + "&& (size(resource.SecurityGroupId.security_group()) == 1)" ) assert C7N_Rewriter.network_location_rewrite("ec2", clause_0) == expected_0 clause_1 = { - 'compare': ['resource', 'subnet'], - 'key': 'tag:Asset', - 'max-cardinality': 1, - 'missing-ok': False, - 'type': 'network-location' + "compare": ["resource", "subnet"], + "key": "tag:Asset", + "max-cardinality": 1, + "missing-ok": False, + "type": "network-location", } expected_1 = ( '(resource.SubnetId.subnet().Tags["Asset"] == resource.Tags["Asset"]) ' - '&& (size(resource.SubnetId.subnet()) == 1)' + "&& (size(resource.SubnetId.subnet()) == 1)" ) assert C7N_Rewriter.network_location_rewrite("ec2", clause_1) == expected_1 diff --git a/tests/test_c7nlib.py b/tests/test_c7nlib.py index 6371685..e3fd9fd 100644 --- a/tests/test_c7nlib.py +++ b/tests/test_c7nlib.py @@ -23,6 +23,7 @@ - Integration Tests which depend on the ``celfilter_instance`` fixture. These tests are essential for making sure we have C7N compatibility. """ + import datetime import io import zlib @@ -74,12 +75,16 @@ def test_unique_size(): def test_parse_cidr(): assert len(list(celpy.c7nlib.parse_cidr("192.168.100.0/22").hosts())) == 1022 - assert celpy.c7nlib.parse_cidr("192.168.100.0") in celpy.c7nlib.parse_cidr("192.168.100.0/22") + assert celpy.c7nlib.parse_cidr("192.168.100.0") in celpy.c7nlib.parse_cidr( + "192.168.100.0/22" + ) assert celpy.c7nlib.parse_cidr("192.168.100.0").packed == bytes([192, 168, 100, 0]) assert celpy.c7nlib.parse_cidr("localhost") is None - assert not celpy.c7nlib.parse_cidr("localhost") in celpy.c7nlib.parse_cidr("192.168.100.0/22") - assert ( - celpy.c7nlib.parse_cidr("192.168.100.0/22") in celpy.c7nlib.parse_cidr("192.168.100.0/22") + assert not celpy.c7nlib.parse_cidr("localhost") in celpy.c7nlib.parse_cidr( + "192.168.100.0/22" + ) + assert celpy.c7nlib.parse_cidr("192.168.100.0/22") in celpy.c7nlib.parse_cidr( + "192.168.100.0/22" ) @@ -97,93 +102,98 @@ def test_version(): value_from_examples = [ ( - ".txt", "text", b"data\n", - celpy.celtypes.ListType( - [celpy.celtypes.StringType('data')] - ) + ".txt", + "text", + b"data\n", + celpy.celtypes.ListType([celpy.celtypes.StringType("data")]), ), ( - ".txt", "gzip", zlib.compress(b"data\n"), - celpy.celtypes.ListType( - [celpy.celtypes.StringType('data')] - ) + ".txt", + "gzip", + zlib.compress(b"data\n"), + celpy.celtypes.ListType([celpy.celtypes.StringType("data")]), ), ( - ".json", "text", b'{"key": "data"}\n', + ".json", + "text", + b'{"key": "data"}\n', celpy.celtypes.MapType( - { - celpy.celtypes.StringType('key'): celpy.celtypes.StringType('data') - } - ) + {celpy.celtypes.StringType("key"): celpy.celtypes.StringType("data")} + ), ), ( - ".ldjson", "text", b'{"row": 1}\n{"row": 2}\n', + ".ldjson", + "text", + b'{"row": 1}\n{"row": 2}\n', celpy.celtypes.ListType( [ celpy.celtypes.MapType( - { - celpy.celtypes.StringType('row'): celpy.celtypes.IntType(1) - } + {celpy.celtypes.StringType("row"): celpy.celtypes.IntType(1)} ), celpy.celtypes.MapType( - { - celpy.celtypes.StringType('row'): celpy.celtypes.IntType(2) - } - ) + {celpy.celtypes.StringType("row"): celpy.celtypes.IntType(2)} + ), ] - ) + ), ), ( - ".csv", "text", (b"row,value\r\n1,42\r\n"), + ".csv", + "text", + (b"row,value\r\n1,42\r\n"), celpy.celtypes.ListType( [ celpy.celtypes.ListType( [ - celpy.celtypes.StringType('row'), - celpy.celtypes.StringType('value'), + celpy.celtypes.StringType("row"), + celpy.celtypes.StringType("value"), ] ), celpy.celtypes.ListType( [ - celpy.celtypes.StringType('1'), - celpy.celtypes.StringType('42'), + celpy.celtypes.StringType("1"), + celpy.celtypes.StringType("42"), ] ), ] - ) + ), ), ( - ".csv2dict", "text", (b"row,value\r\n1,42\r\n"), + ".csv2dict", + "text", + (b"row,value\r\n1,42\r\n"), celpy.celtypes.ListType( [ celpy.celtypes.MapType( { - celpy.celtypes.StringType('row'): celpy.celtypes.StringType('1'), - celpy.celtypes.StringType('value'): celpy.celtypes.StringType('42'), + celpy.celtypes.StringType("row"): celpy.celtypes.StringType( + "1" + ), + celpy.celtypes.StringType("value"): celpy.celtypes.StringType( + "42" + ), } ), ] - ) + ), ), ] + @pytest.fixture(params=value_from_examples) def mock_urllib_request(monkeypatch, request): suffix, encoding, raw_bytes, expected = request.param urllib_request = Mock( Request=Mock(return_value=Mock()), - urlopen=Mock(return_value=Mock( - info=Mock(return_value=Mock(get=Mock(return_value=encoding))), - read=Mock(return_value=raw_bytes) - )) - ) - monkeypatch.setattr(celpy.c7nlib.urllib, 'request', urllib_request) - mock_os = Mock( - splitext=Mock( - return_value=("path", suffix) - ) + urlopen=Mock( + return_value=Mock( + info=Mock(return_value=Mock(get=Mock(return_value=encoding))), + read=Mock(return_value=raw_bytes), + ) + ), ) - monkeypatch.setattr(celpy.c7nlib.os, 'path', mock_os) + monkeypatch.setattr(celpy.c7nlib.urllib, "request", urllib_request) + mock_os = Mock(splitext=Mock(return_value=("path", suffix))) + monkeypatch.setattr(celpy.c7nlib.os, "path", mock_os) return urllib_request, expected @@ -191,7 +201,7 @@ def test_value_from(mock_urllib_request): urllib_request, expected = mock_urllib_request data = celpy.c7nlib.value_from(sentinel.URL) assert urllib_request.Request.mock_calls == [ - call(sentinel.URL, headers={'Accept-Encoding': 'gzip'}) + call(sentinel.URL, headers={"Accept-Encoding": "gzip"}) ] assert expected == data @@ -204,16 +214,21 @@ def test_value_from_bad_format(): jmes_path_examples = [ ({"foo": {"bar": "baz"}}, "foo.bar", "baz"), ({"foo": {"bar": ["one", "two"]}}, "foo.bar[0]", "one"), - ({"foo": {"bar": [{"name": "one"}, {"name": "two"}]}}, "foo.bar[*].name", ["one", "two"]), + ( + {"foo": {"bar": [{"name": "one"}, {"name": "two"}]}}, + "foo.bar[*].name", + ["one", "two"], + ), ] + @pytest.fixture(params=jmes_path_examples) def doc_path_expected(request): json_doc, path, expected = request.param return ( celpy.adapter.json_to_cel(json_doc), celpy.celtypes.StringType(path), - expected + expected, ) @@ -229,9 +244,10 @@ def doclist_path_expected(request): return ( celpy.celtypes.ListType([celpy.adapter.json_to_cel(json_doc)]), celpy.celtypes.StringType(path), - [expected] + [expected], ) + def test_jmes_path_map(doclist_path_expected): doclist, path, expected_list = doclist_path_expected actual_list = celpy.c7nlib.jmes_path_map(doclist, path) @@ -255,21 +271,28 @@ def test_marked_key_good(): [ celpy.celtypes.MapType( { - celpy.celtypes.StringType("Key"): - celpy.celtypes.StringType("c7n-tag-compliance"), - celpy.celtypes.StringType("Value"): - celpy.celtypes.StringType("hello:stop@2020-09-10"), + celpy.celtypes.StringType("Key"): celpy.celtypes.StringType( + "c7n-tag-compliance" + ), + celpy.celtypes.StringType("Value"): celpy.celtypes.StringType( + "hello:stop@2020-09-10" + ), } ), ] ) doc = celpy.c7nlib.marked_key( - tags_good, - celpy.celtypes.StringType("c7n-tag-compliance") + tags_good, celpy.celtypes.StringType("c7n-tag-compliance") + ) + assert doc.get(celpy.celtypes.StringType("message")) == celpy.celtypes.StringType( + "hello" + ) + assert doc.get(celpy.celtypes.StringType("action")) == celpy.celtypes.StringType( + "stop" ) - assert doc.get(celpy.celtypes.StringType("message")) == celpy.celtypes.StringType("hello") - assert doc.get(celpy.celtypes.StringType("action")) == celpy.celtypes.StringType("stop") - assert doc.get(celpy.celtypes.StringType("action_date")) == celpy.celtypes.TimestampType("2020-09-10") + assert doc.get( + celpy.celtypes.StringType("action_date") + ) == celpy.celtypes.TimestampType("2020-09-10") def test_marked_key_missing(): @@ -277,17 +300,18 @@ def test_marked_key_missing(): [ celpy.celtypes.MapType( { - celpy.celtypes.StringType("Key"): - celpy.celtypes.StringType("ASSET"), - celpy.celtypes.StringType("Value"): - celpy.celtypes.StringType("hello:stop@2020-09-10"), + celpy.celtypes.StringType("Key"): celpy.celtypes.StringType( + "ASSET" + ), + celpy.celtypes.StringType("Value"): celpy.celtypes.StringType( + "hello:stop@2020-09-10" + ), } ), ] ) doc = celpy.c7nlib.marked_key( - tags_good, - celpy.celtypes.StringType("c7n-tag-compliance") + tags_good, celpy.celtypes.StringType("c7n-tag-compliance") ) assert doc is None @@ -297,17 +321,18 @@ def test_marked_key_wrong_format(): [ celpy.celtypes.MapType( { - celpy.celtypes.StringType("Key"): - celpy.celtypes.StringType("c7n-tag-compliance"), - celpy.celtypes.StringType("Value"): - celpy.celtypes.StringType("nope:"), + celpy.celtypes.StringType("Key"): celpy.celtypes.StringType( + "c7n-tag-compliance" + ), + celpy.celtypes.StringType("Value"): celpy.celtypes.StringType( + "nope:" + ), } ), ] ) doc = celpy.c7nlib.marked_key( - tags_good, - celpy.celtypes.StringType("c7n-tag-compliance") + tags_good, celpy.celtypes.StringType("c7n-tag-compliance") ) assert doc is None @@ -341,21 +366,17 @@ def test_arn_split(): @pytest.fixture def mock_manager(): - datapoints = [ - {"Average": str(sentinel.average)} - ] + datapoints = [{"Average": str(sentinel.average)}] health_events = [ { "category": "issue", "code": "AWS_EC2_SYSTEM_MAINTENANCE_EVENT", - "service": "EC2" + "service": "EC2", } ] cloudwatch_client = Mock( name="cloudwatch_client", - get_metric_statistics=Mock( - return_value={"Datapoints": datapoints} - ) + get_metric_statistics=Mock(return_value={"Datapoints": datapoints}), ) ec2_client = Mock( name="ec2_client", @@ -369,11 +390,8 @@ def mock_manager(): elb_client = Mock( name="elb_client", describe_load_balancer_attributes=Mock( - return_value={ - 'LoadBalancerAttributes': [ - {"Enabled": True}] - } - ) + return_value={"LoadBalancerAttributes": [{"Enabled": True}]} + ), ) elbv2_client = Mock( name="elbv2_client", @@ -386,30 +404,25 @@ def mock_manager(): {"Key": "string", "Value": "other"}, ] } - ) + ), ) health_client = Mock( name="health_client", - describe_events=Mock( - return_value={"events": health_events} - ) + describe_events=Mock(return_value={"events": health_events}), ) kms_client = Mock( name="kms_client", - get_key_policy=Mock( - return_value={"Policy": str(sentinel.policy)}), + get_key_policy=Mock(return_value={"Policy": str(sentinel.policy)}), ) logs_client = Mock( name="logs_cient", describe_subscription_filters=Mock( return_value={"subscriptionFilters": [str(sentinel.subscription_filter)]} - ) + ), ) shield_client = Mock( name="shield_client", - describe_subscription=Mock( - return_value={"Subscription": str(sentinel.shield)} - ) + describe_subscription=Mock(return_value={"Subscription": str(sentinel.shield)}), ) clients = { "ec2": ec2_client, @@ -423,7 +436,7 @@ def mock_manager(): } mock_session = Mock( name="mock_session instance", - client=Mock(side_effect=lambda name, region_name=None: clients.get(name)) + client=Mock(side_effect=lambda name, region_name=None: clients.get(name)), ) asg_resource_manager = Mock( @@ -435,7 +448,7 @@ def mock_manager(): "AutoScalingGroupName": str(sentinel.asg_name), }, ] - ) + ), ) rds_resource_manager = Mock( name="rds_resource_manager", @@ -446,7 +459,7 @@ def mock_manager(): "DBInstanceIdentifier": str(sentinel.rds_instance_identifier), }, ] - ) + ), ) waf_resource_manager = Mock( name="waf_resource_manager", @@ -454,7 +467,7 @@ def mock_manager(): return_value=[ {"Name": str(sentinel.waf_name), "WebACLId": str(sentinel.waf_acl_id)} ] - ) + ), ) resource_managers = { "asg": asg_resource_manager, @@ -464,18 +477,21 @@ def mock_manager(): manager = Mock( name="mock_manager", session_factory=Mock(return_value=mock_session), - get_model=Mock(return_value=Mock(dimension="InstanceId", id="InstanceId", service="ec2")), + get_model=Mock( + return_value=Mock(dimension="InstanceId", id="InstanceId", service="ec2") + ), get_resource_manager=Mock(side_effect=lambda name: resource_managers.get(name)), retry=Mock(side_effect=lambda f, **kwargs: f(**kwargs)), resource_type="ec2", - config = Mock( + config=Mock( account_id="123456789012", region="us-east-1", ), - data={"resource": "ec2"} + data={"resource": "ec2"}, ) return locals() + @pytest.fixture def mock_filter_class(): """ @@ -487,15 +503,12 @@ def mock_filter_class(): return_value={ "off": [ {"days": [1, 2, 3, 4, 5], "hour": 21}, - {"days": [0], "hour": 18} - ], - "on": [ - {"days": [1, 2, 3, 4, 5], "hour": 6}, - {"days": [0], "hour": 10} + {"days": [0], "hour": 18}, ], - "tz": "pt" + "on": [{"days": [1, 2, 3, 4, 5], "hour": 6}, {"days": [0], "hour": 10}], + "tz": "pt", } - ) + ), ) def get_related_results(resources): @@ -512,6 +525,7 @@ def get_related_results(resources): # Class foundation from C7n. class Filter: """Mock of c7n.filters.core.Filter""" + def __init__(self, data, manager): self.data = data self.manager = manager @@ -519,7 +533,10 @@ def __init__(self, data, manager): # Mixins from C7N. class InstanceImageMixin: get_instance_image = Mock( - return_value={"CreationDate": "2020-09-10T11:12:13Z", "Name": str(sentinel.name)} + return_value={ + "CreationDate": "2020-09-10T11:12:13Z", + "Name": str(sentinel.name), + } ) class RelatedResourceMixin: @@ -542,8 +559,8 @@ class ResourceKmsKeyAliasMixin: class CrossAccountAccessMixin: get_accounts = Mock(return_value=[str(sentinel.account)]) get_vpcs = Mock(return_value=[str(sentinel.vpc)]) - get_vpces=Mock(return_value=[str(sentinel.vpce)]) - get_orgids=Mock(return_value=[str(sentinel.orgid)]) + get_vpces = Mock(return_value=[str(sentinel.vpce)]) + get_orgids = Mock(return_value=[str(sentinel.orgid)]) get_resource_policy = Mock(return_value=[str(sentinel.policy)]) class SNSCrossAccountMixin: @@ -566,26 +583,39 @@ class SGUsageMixin: scan_groups = Mock(return_value=[str(sentinel.scan_group)]) class IsShieldProtectedMixin: - get_type_protections = Mock(return_value=[{"ResourceArn": str(sentinel.shield)}]) + get_type_protections = Mock( + return_value=[{"ResourceArn": str(sentinel.shield)}] + ) class ShieldEnabledMixin: account_shield_subscriptions = Mock(return_value=[str(sentinel.shield)]) class CELFilter( - InstanceImageMixin, RelatedResourceMixin, CredentialReportMixin, - ResourceKmsKeyAliasMixin, CrossAccountAccessMixin, SNSCrossAccountMixin, - ImagesUnusedMixin, SnapshotUnusedMixin, IamRoleUsageMixin, SGUsageMixin, - IsShieldProtectedMixin, ShieldEnabledMixin, + InstanceImageMixin, + RelatedResourceMixin, + CredentialReportMixin, + ResourceKmsKeyAliasMixin, + CrossAccountAccessMixin, + SNSCrossAccountMixin, + ImagesUnusedMixin, + SnapshotUnusedMixin, + IamRoleUsageMixin, + SGUsageMixin, + IsShieldProtectedMixin, + ShieldEnabledMixin, Filter, ): """Mocked subclass of c7n.filters.core.Filter with Mocked mixins.""" + def __init__(self, data, manager): super().__init__(data, manager) assert self.data["type"].lower() == "cel" self.expr = self.data["expr"] self.parser = mock_parser + return CELFilter + @pytest.fixture def celfilter_instance(mock_filter_class, mock_manager): """ @@ -595,55 +625,62 @@ def celfilter_instance(mock_filter_class, mock_manager): mock_policy_filter_source = {"type": "cel", "expr": "1+1==2"} # The mock for the ``CELFilter`` instance C7N must provide. - the_filter = mock_filter_class(mock_policy_filter_source, mock_manager['manager']) + the_filter = mock_filter_class(mock_policy_filter_source, mock_manager["manager"]) return locals() def test_image_age_good(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] resource = celpy.celtypes.MapType({}) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc = celpy.c7nlib.image( - resource - ) - assert doc.get(celpy.celtypes.StringType('CreationDate')) == celpy.celtypes.TimestampType("2020-09-10T11:12:13Z") + doc = celpy.c7nlib.image(resource) + assert doc.get( + celpy.celtypes.StringType("CreationDate") + ) == celpy.celtypes.TimestampType("2020-09-10T11:12:13Z") def test_image_age_missing(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] - mock_filter.get_instance_image=Mock(return_value=None) + mock_filter = celfilter_instance["the_filter"] + mock_filter.get_instance_image = Mock(return_value=None) resource = celpy.celtypes.MapType({}) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc = celpy.c7nlib.image( - resource - ) - assert doc.get(celpy.celtypes.StringType('CreationDate')) == celpy.celtypes.TimestampType("2000-01-01T01:01:01.000Z") + doc = celpy.c7nlib.image(resource) + assert doc.get( + celpy.celtypes.StringType("CreationDate") + ) == celpy.celtypes.TimestampType("2000-01-01T01:01:01.000Z") def test_get_raw_metrics(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] - datapoints = mock_manager['datapoints'] + mock_filter = celfilter_instance["the_filter"] + datapoints = mock_manager["datapoints"] now = celpy.celtypes.TimestampType("2000-01-01T01:01:01.000Z") resource = celpy.celtypes.MapType({}) request = celpy.celtypes.MapType( { - celpy.celtypes.StringType("Namespace"): celpy.celtypes.StringType("AWS/EC2"), - celpy.celtypes.StringType("MetricName"): celpy.celtypes.StringType("CPUUtilization"), + celpy.celtypes.StringType("Namespace"): celpy.celtypes.StringType( + "AWS/EC2" + ), + celpy.celtypes.StringType("MetricName"): celpy.celtypes.StringType( + "CPUUtilization" + ), celpy.celtypes.StringType("Dimensions"): celpy.celtypes.MapType( { - celpy.celtypes.StringType("Name"): celpy.celtypes.StringType("InstanceId"), - celpy.celtypes.StringType("Value"): celpy.celtypes.StringType("i-1234567890abcdef0"), + celpy.celtypes.StringType("Name"): celpy.celtypes.StringType( + "InstanceId" + ), + celpy.celtypes.StringType("Value"): celpy.celtypes.StringType( + "i-1234567890abcdef0" + ), } ), celpy.celtypes.StringType("Statistics"): celpy.celtypes.ListType( - [ - celpy.celtypes.StringType("Average") - ] + [celpy.celtypes.StringType("Average")] ), - celpy.celtypes.StringType("StartTime"): now - celpy.celtypes.DurationType("4d"), + celpy.celtypes.StringType("StartTime"): now + - celpy.celtypes.DurationType("4d"), celpy.celtypes.StringType("EndTime"): now, - celpy.celtypes.StringType("Period"): celpy.celtypes.DurationType("86400s") + celpy.celtypes.StringType("Period"): celpy.celtypes.DurationType("86400s"), } ) with celpy.c7nlib.C7NContext(filter=mock_filter): @@ -657,37 +694,37 @@ def test_get_metrics(celfilter_instance, mock_manager): :func:`get_raw_metrics`. We use approach 2 in case the implmentation of `get_metrics` is changed. """ - mock_filter = celfilter_instance['the_filter'] - datapoints = mock_manager['datapoints'] + mock_filter = celfilter_instance["the_filter"] + datapoints = mock_manager["datapoints"] now = celpy.celtypes.TimestampType("2000-01-01T01:01:01.000Z") resource = celpy.celtypes.MapType({"InstanceId": "i-123456789012"}) request = celpy.celtypes.MapType( { - celpy.celtypes.StringType("MetricName"): celpy.celtypes.StringType("CPUUtilization"), - celpy.celtypes.StringType("Statistic"): celpy.celtypes.StringType("Average"), - celpy.celtypes.StringType("StartTime"): now - celpy.celtypes.DurationType("4d"), + celpy.celtypes.StringType("MetricName"): celpy.celtypes.StringType( + "CPUUtilization" + ), + celpy.celtypes.StringType("Statistic"): celpy.celtypes.StringType( + "Average" + ), + celpy.celtypes.StringType("StartTime"): now + - celpy.celtypes.DurationType("4d"), celpy.celtypes.StringType("EndTime"): now, - celpy.celtypes.StringType("Period"): celpy.celtypes.DurationType("86400s") + celpy.celtypes.StringType("Period"): celpy.celtypes.DurationType("86400s"), } ) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc = celpy.c7nlib.get_metrics( - resource, - request - ) + doc = celpy.c7nlib.get_metrics(resource, request) assert doc == celpy.celtypes.ListType( - [celpy.celtypes.StringType('sentinel.average')] + [celpy.celtypes.StringType("sentinel.average")] ) def test_get_related_ids(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] resource = celpy.celtypes.MapType({}) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc = celpy.c7nlib.get_related_ids( - resource - ) + doc = celpy.c7nlib.get_related_ids(resource) assert doc == celpy.celtypes.ListType( [ celpy.celtypes.StringType("sentinel.sg_id"), @@ -704,30 +741,36 @@ def test_security_group(celfilter_instance): SecurityGroupId="sg-23456789", SecurityGroupName="AnotherName", ) - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] mock_filter.get_related = Mock(return_value=[mock_sg_1, mock_sg_2]) resource = celpy.celtypes.MapType( {celpy.celtypes.StringType("ResourceType"): celpy.celtypes.StringType("sg")} ) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc = celpy.c7nlib.security_group( - resource - ) + doc = celpy.c7nlib.security_group(resource) assert doc == celpy.celtypes.ListType( [ - celpy.celtypes.MapType({ - celpy.celtypes.StringType("SecurityGroupId"): - celpy.celtypes.StringType("sg-12345678"), - celpy.celtypes.StringType("SecurityGroupName"): - celpy.celtypes.StringType("SomeName"), - }), - celpy.celtypes.MapType({ - celpy.celtypes.StringType("SecurityGroupId"): - celpy.celtypes.StringType("sg-23456789"), - celpy.celtypes.StringType("SecurityGroupName"): - celpy.celtypes.StringType("AnotherName"), - }), + celpy.celtypes.MapType( + { + celpy.celtypes.StringType( + "SecurityGroupId" + ): celpy.celtypes.StringType("sg-12345678"), + celpy.celtypes.StringType( + "SecurityGroupName" + ): celpy.celtypes.StringType("SomeName"), + } + ), + celpy.celtypes.MapType( + { + celpy.celtypes.StringType( + "SecurityGroupId" + ): celpy.celtypes.StringType("sg-23456789"), + celpy.celtypes.StringType( + "SecurityGroupName" + ): celpy.celtypes.StringType("AnotherName"), + } + ), ] ) @@ -737,15 +780,15 @@ def test_subnet(celfilter_instance): SubnetID="subnet-12345678", SubnetArn="arn:aws:asg:us-east-1:123456789012:subnet-12345678", ) - mock_filter = celfilter_instance['the_filter'] - mock_filter.get_related=Mock(return_value=mock_subnet) + mock_filter = celfilter_instance["the_filter"] + mock_filter.get_related = Mock(return_value=mock_subnet) resource = celpy.celtypes.MapType({}) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc = celpy.c7nlib.subnet( - resource - ) - assert doc.get(celpy.celtypes.StringType("SubnetID")) == celpy.celtypes.StringType("subnet-12345678") + doc = celpy.c7nlib.subnet(resource) + assert doc.get(celpy.celtypes.StringType("SubnetID")) == celpy.celtypes.StringType( + "subnet-12345678" + ) def test_flow_logs(celfilter_instance): @@ -754,200 +797,254 @@ def test_flow_logs(celfilter_instance): .. todo:: Refactor :func:`c7nlib.flow_logs` -- it exposes too much implementation detail. """ - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] resource_1 = celpy.celtypes.MapType( - {celpy.celtypes.StringType("InstanceId"): celpy.celtypes.StringType("i-123456789")}) + { + celpy.celtypes.StringType("InstanceId"): celpy.celtypes.StringType( + "i-123456789" + ) + } + ) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc_1 = celpy.c7nlib.flow_logs( - resource_1 - ) + doc_1 = celpy.c7nlib.flow_logs(resource_1) assert doc_1 == [{"ResourceId": "i-123456789"}] resource_2 = celpy.celtypes.MapType( - {celpy.celtypes.StringType("InstanceId"): celpy.celtypes.StringType("i-111111111")}) + { + celpy.celtypes.StringType("InstanceId"): celpy.celtypes.StringType( + "i-111111111" + ) + } + ) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc_2 = celpy.c7nlib.flow_logs( - resource_2 - ) + doc_2 = celpy.c7nlib.flow_logs(resource_2) assert doc_2 == [] def test_vpc(celfilter_instance): vpc_1 = {"ResourceId": "vpc-123456789", "More": "Details"} - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] mock_filter.get_related = Mock(return_value=vpc_1) resource_1 = celpy.celtypes.MapType( - {celpy.celtypes.StringType("InstanceId"): celpy.celtypes.StringType("vpc-123456789")}) + { + celpy.celtypes.StringType("InstanceId"): celpy.celtypes.StringType( + "vpc-123456789" + ) + } + ) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc_1 = celpy.c7nlib.vpc( - resource_1 - ) + doc_1 = celpy.c7nlib.vpc(resource_1) assert doc_1 == vpc_1 def test_subst(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] with celpy.c7nlib.C7NContext(filter=mock_filter): assert celpy.c7nlib.subst("this") == "this" assert celpy.c7nlib.subst("this {account_id}") == "this 123456789012" def test_credentials(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] resource_1 = celpy.celtypes.MapType( - {celpy.celtypes.StringType("ResourceType"): celpy.celtypes.StringType("iam-user")}) + { + celpy.celtypes.StringType("ResourceType"): celpy.celtypes.StringType( + "iam-user" + ) + } + ) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc_1 = celpy.c7nlib.credentials( - resource_1 - ) + doc_1 = celpy.c7nlib.credentials(resource_1) assert doc_1 == celpy.adapter.json_to_cel(str(sentinel.credential)) def test_kms_alias(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] resource_1 = celpy.celtypes.MapType( - {celpy.celtypes.StringType("ResourceType"): celpy.celtypes.StringType("rds")}) + {celpy.celtypes.StringType("ResourceType"): celpy.celtypes.StringType("rds")} + ) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc_1 = celpy.c7nlib.kms_alias( - resource_1 - ) + doc_1 = celpy.c7nlib.kms_alias(resource_1) assert doc_1 == celpy.adapter.json_to_cel([str(sentinel.kms_alias)]) def test_kms_key(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] resource_1 = celpy.celtypes.MapType( - {celpy.celtypes.StringType("ResourceType"): celpy.celtypes.StringType("ebs")}) + {celpy.celtypes.StringType("ResourceType"): celpy.celtypes.StringType("ebs")} + ) with celpy.c7nlib.C7NContext(filter=mock_filter): - doc_1 = celpy.c7nlib.kms_key( - resource_1 - ) + doc_1 = celpy.c7nlib.kms_key(resource_1) assert doc_1 == celpy.adapter.json_to_cel([{"AliasName": str(sentinel.alias_name)}]) def test_C7N_resource_schedule(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = { "ResourceType": "ec2", "Tags": [ { "key": "maid_offhours", - "value": "off=[(M-F,21),(U,18)];on=[(M-F,6),(U,10)];tz=pt" + "value": "off=[(M-F,21),(U,18)];on=[(M-F,6),(U,10)];tz=pt", } - ] + ], } with celpy.c7nlib.C7NContext(filter=mock_filter): other_tz_names = { - 'et': 'US/Eastern', - 'pt': 'US/Pacific', + "et": "US/Eastern", + "pt": "US/Pacific", } celpy.celtypes.TimestampType.TZ_ALIASES.update(other_tz_names) schedule = celpy.c7nlib.resource_schedule(ec2_doc) assert schedule == { - celpy.celtypes.StringType('off'): celpy.celtypes.ListType([ - celpy.celtypes.MapType({ - celpy.celtypes.StringType('days'): celpy.celtypes.ListType([ - celpy.celtypes.IntType(1), celpy.celtypes.IntType(2), - celpy.celtypes.IntType(3), celpy.celtypes.IntType(4), - celpy.celtypes.IntType(5) - ]), - celpy.celtypes.StringType('hour'): celpy.celtypes.IntType(21), - celpy.celtypes.StringType('tz'): celpy.celtypes.StringType('pt'), - }), - celpy.celtypes.MapType({ - celpy.celtypes.StringType('days'): celpy.celtypes.ListType([ - celpy.celtypes.IntType(0) - ]), - celpy.celtypes.StringType('hour'): celpy.celtypes.IntType(18), - celpy.celtypes.StringType('tz'): celpy.celtypes.StringType('pt'), - }) - ]), - celpy.celtypes.StringType('on'): celpy.celtypes.ListType([ - celpy.celtypes.MapType({ - celpy.celtypes.StringType('days'): celpy.celtypes.ListType([ - celpy.celtypes.IntType(1), celpy.celtypes.IntType(2), - celpy.celtypes.IntType(3), celpy.celtypes.IntType(4), - celpy.celtypes.IntType(5) - ]), - celpy.celtypes.StringType('hour'): celpy.celtypes.IntType(6), - celpy.celtypes.StringType('tz'): celpy.celtypes.StringType('pt'), - }), - celpy.celtypes.MapType({ - celpy.celtypes.StringType('days'): celpy.celtypes.ListType([ - celpy.celtypes.IntType(0) - ]), - celpy.celtypes.StringType('hour'): celpy.celtypes.IntType(10), - celpy.celtypes.StringType('tz'): celpy.celtypes.StringType('pt'), - }) - ]), + celpy.celtypes.StringType("off"): celpy.celtypes.ListType( + [ + celpy.celtypes.MapType( + { + celpy.celtypes.StringType("days"): celpy.celtypes.ListType( + [ + celpy.celtypes.IntType(1), + celpy.celtypes.IntType(2), + celpy.celtypes.IntType(3), + celpy.celtypes.IntType(4), + celpy.celtypes.IntType(5), + ] + ), + celpy.celtypes.StringType("hour"): celpy.celtypes.IntType(21), + celpy.celtypes.StringType("tz"): celpy.celtypes.StringType( + "pt" + ), + } + ), + celpy.celtypes.MapType( + { + celpy.celtypes.StringType("days"): celpy.celtypes.ListType( + [celpy.celtypes.IntType(0)] + ), + celpy.celtypes.StringType("hour"): celpy.celtypes.IntType(18), + celpy.celtypes.StringType("tz"): celpy.celtypes.StringType( + "pt" + ), + } + ), + ] + ), + celpy.celtypes.StringType("on"): celpy.celtypes.ListType( + [ + celpy.celtypes.MapType( + { + celpy.celtypes.StringType("days"): celpy.celtypes.ListType( + [ + celpy.celtypes.IntType(1), + celpy.celtypes.IntType(2), + celpy.celtypes.IntType(3), + celpy.celtypes.IntType(4), + celpy.celtypes.IntType(5), + ] + ), + celpy.celtypes.StringType("hour"): celpy.celtypes.IntType(6), + celpy.celtypes.StringType("tz"): celpy.celtypes.StringType( + "pt" + ), + } + ), + celpy.celtypes.MapType( + { + celpy.celtypes.StringType("days"): celpy.celtypes.ListType( + [celpy.celtypes.IntType(0)] + ), + celpy.celtypes.StringType("hour"): celpy.celtypes.IntType(10), + celpy.celtypes.StringType("tz"): celpy.celtypes.StringType( + "pt" + ), + } + ), + ] + ), } + def test_get_accounts(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ami_doc = {"ResourceType": "ami"} with celpy.c7nlib.C7NContext(filter=mock_filter): accounts = celpy.c7nlib.get_accounts(ami_doc) assert accounts == [str(sentinel.account)] + def test_get_vpcs(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ami_doc = {"ResourceType": "ami"} with celpy.c7nlib.C7NContext(filter=mock_filter): vpcs = celpy.c7nlib.get_vpcs(ami_doc) assert vpcs == [str(sentinel.vpc)] + def test_get_vpces(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ami_doc = {"ResourceType": "ami"} with celpy.c7nlib.C7NContext(filter=mock_filter): vpces = celpy.c7nlib.get_vpces(ami_doc) assert vpces == [str(sentinel.vpce)] + def test_get_orgids(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ami_doc = {"ResourceType": "ami"} with celpy.c7nlib.C7NContext(filter=mock_filter): orgids = celpy.c7nlib.get_orgids(ami_doc) assert orgids == [str(sentinel.orgid)] + def test_get_endpoints(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ami_doc = {"ResourceType": "sns"} with celpy.c7nlib.C7NContext(filter=mock_filter): endpoints = celpy.c7nlib.get_endpoints(ami_doc) assert endpoints == [str(sentinel.endpoint)] + def test_get_protocols(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ami_doc = {"ResourceType": "sns"} with celpy.c7nlib.C7NContext(filter=mock_filter): protocols = celpy.c7nlib.get_protocols(ami_doc) assert protocols == [str(sentinel.protocol)] + def test_get_resource_policy(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ami_doc = {"ResourceType": "iam-group"} with celpy.c7nlib.C7NContext(filter=mock_filter): policies = celpy.c7nlib.get_resource_policy(ami_doc) assert policies == [str(sentinel.policy)] + def test_get_key_policy(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] kms_doc = {"ResourceType": "kms", "KeyId": str(sentinel.key_id)} with celpy.c7nlib.C7NContext(filter=mock_filter): policy = celpy.c7nlib.get_key_policy(kms_doc) assert policy == str(sentinel.policy) + def test_describe_subscription_filters(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] - log_group_doc = {"ResourceType": "log-group", "logGroupName": str(sentinel.log_group_name)} + mock_filter = celfilter_instance["the_filter"] + log_group_doc = { + "ResourceType": "log-group", + "logGroupName": str(sentinel.log_group_name), + } with celpy.c7nlib.C7NContext(filter=mock_filter): policy = celpy.c7nlib.describe_subscription_filters(log_group_doc) assert policy == [str(sentinel.subscription_filter)] + def test_describe_db_snapshot_attributes(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] - rds_snapshot_doc = {"ResourceType": "rds-snapshot", "SnapshotId": str(sentinel.snapshot_id)} + mock_filter = celfilter_instance["the_filter"] + rds_snapshot_doc = { + "ResourceType": "rds-snapshot", + "SnapshotId": str(sentinel.snapshot_id), + } with celpy.c7nlib.C7NContext(filter=mock_filter): policy = celpy.c7nlib.describe_db_snapshot_attributes(rds_snapshot_doc) assert policy == [str(sentinel.snashot_permission)] @@ -967,7 +1064,7 @@ def test_C7N_interpreted_runner(celfilter_instance): 2. Build Activation. 3. Evaluate. """ - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] # This will be part of ``CELFilter.validate()`` decls = { @@ -975,7 +1072,9 @@ def test_C7N_interpreted_runner(celfilter_instance): "now": celpy.celtypes.TimestampType, } decls.update(celpy.c7nlib.DECLARATIONS) - cel_env = celpy.Environment(annotations=decls, runner_class=celpy.c7nlib.C7N_Interpreted_Runner) + cel_env = celpy.Environment( + annotations=decls, runner_class=celpy.c7nlib.C7N_Interpreted_Runner + ) cel_ast = cel_env.compile(mock_filter.expr) # This will be implemented in ``CELFilter.process()`` or ``CELFilter.__call__()``. @@ -990,12 +1089,12 @@ def test_C7N_interpreted_runner(celfilter_instance): # Did it work? assert cel_result + def test_C7N_extension_function(mock_filter_class, mock_manager, caplog): mock_policy_filter_source = {"type": "cel", "expr": '"PRE-this".glob("PRE-*")'} # The mock for the ``CELFilter`` instance C7N must provide. - the_filter = mock_filter_class(mock_policy_filter_source, - mock_manager['manager']) + the_filter = mock_filter_class(mock_policy_filter_source, mock_manager["manager"]) cel_env = celpy.Environment(runner_class=celpy.c7nlib.C7N_Interpreted_Runner) cel_ast = cel_env.compile(the_filter.expr) @@ -1014,26 +1113,29 @@ def test_C7N_extension_function(mock_filter_class, mock_manager, caplog): def test_C7N_CELFilter_image(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2"} with celpy.c7nlib.C7NContext(filter=mock_filter): image = celpy.c7nlib.image(ec2_doc) - assert image == {'CreationDate': celpy.celtypes.TimestampType('2020-09-10T11:12:13Z') , "Name": str(sentinel.name)} + assert image == { + "CreationDate": celpy.celtypes.TimestampType("2020-09-10T11:12:13Z"), + "Name": str(sentinel.name), + } assert mock_filter.get_instance_image.mock_calls == [call(ec2_doc)] def test_C7N_CELFilter_get_raw_metrics(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] metrics_doc = { - "Namespace": "AWS/EC2", - "MetricName": "CPUUtilization", - "Dimensions": {"Name": "InstanceId", "Value": "i-12345678"}, - "Statistics": ["Average"], - "StartTime": "2020-09-10T11:12:13Z", - "EndTime": "2020-09-11T11:12:13Z", - "Period": 86400, - } + "Namespace": "AWS/EC2", + "MetricName": "CPUUtilization", + "Dimensions": {"Name": "InstanceId", "Value": "i-12345678"}, + "Statistics": ["Average"], + "StartTime": "2020-09-10T11:12:13Z", + "EndTime": "2020-09-11T11:12:13Z", + "Period": 86400, + } with celpy.c7nlib.C7NContext(filter=mock_filter): metrics = celpy.c7nlib.get_raw_metrics(metrics_doc) assert metrics == [{"Average": str(sentinel.average)}] @@ -1047,23 +1149,28 @@ def test_C7N_CELFilter_get_raw_metrics(celfilter_instance, mock_manager): Period=metrics_doc["Period"], Dimensions=metrics_doc["Dimensions"], ) - cloudwatch_client = mock_manager['cloudwatch_client'] + cloudwatch_client = mock_manager["cloudwatch_client"] print(f"cloudwatch_client {cloudwatch_client}") - assert cloudwatch_client.mock_calls == [call.get_metric_statistics(**expected_request)] + assert cloudwatch_client.mock_calls == [ + call.get_metric_statistics(**expected_request) + ] def test_C7N_CELFilter_get_metrics(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} request = { - "MetricName": "CPUUtilization", "Statistic": "Average", - "StartTime": "2020-09-10T11:12:13Z", "EndTime": "2020-09-11T11:12:13Z", "Period": 86400 + "MetricName": "CPUUtilization", + "Statistic": "Average", + "StartTime": "2020-09-10T11:12:13Z", + "EndTime": "2020-09-11T11:12:13Z", + "Period": 86400, } with celpy.c7nlib.C7NContext(filter=mock_filter): metrics = celpy.c7nlib.get_metrics(ec2_doc, request) assert metrics == [str(sentinel.average)] - cloudwatch_client = mock_manager['cloudwatch_client'] + cloudwatch_client = mock_manager["cloudwatch_client"] expected_request = dict( Namespace=celpy.celtypes.StringType("ec2"), MetricName=request["MetricName"], @@ -1071,91 +1178,110 @@ def test_C7N_CELFilter_get_metrics(celfilter_instance, mock_manager): StartTime=request["StartTime"], EndTime=request["EndTime"], Period=request["Period"], - Dimensions=celpy.celtypes.ListType([ - celpy.celtypes.MapType({ - celpy.celtypes.StringType("Name"): celpy.celtypes.StringType("InstanceId"), - celpy.celtypes.StringType("Value"): celpy.celtypes.StringType("i-123456789") - }) - ]), + Dimensions=celpy.celtypes.ListType( + [ + celpy.celtypes.MapType( + { + celpy.celtypes.StringType("Name"): celpy.celtypes.StringType( + "InstanceId" + ), + celpy.celtypes.StringType("Value"): celpy.celtypes.StringType( + "i-123456789" + ), + } + ) + ] + ), ) print(cloudwatch_client.mock_calls) - assert cloudwatch_client.mock_calls == [call.get_metric_statistics(**expected_request)] + assert cloudwatch_client.mock_calls == [ + call.get_metric_statistics(**expected_request) + ] def test_C7N_CELFilter_get_related_ids(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): sg_ids = celpy.c7nlib.get_related_ids(ec2_doc) assert sg_ids == [str(sentinel.sg_id)] assert mock_filter.get_related_ids.mock_calls == [call(ec2_doc)] + def test_C7N_CELFilter_get_related_sgs(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): sg = celpy.c7nlib.get_related_sgs(ec2_doc) assert sg == [str(sentinel.sg)] assert mock_filter.get_related_sgs.mock_calls == [call(ec2_doc)] + def test_C7N_CELFilter_get_related_subnets(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): subnet = celpy.c7nlib.get_related_subnets(ec2_doc) assert subnet == [str(sentinel.subnet)] assert mock_filter.get_related_subnets.mock_calls == [call(ec2_doc)] + def test_C7N_CELFilter_get_related_nat_gateways(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): nat_gateway = celpy.c7nlib.get_related_nat_gateways(ec2_doc) assert nat_gateway == [str(sentinel.nat_gateway)] assert mock_filter.get_related_nat_gateways.mock_calls == [call(ec2_doc)] + def test_C7N_CELFilter_get_related_igws(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): igw = celpy.c7nlib.get_related_igws(ec2_doc) assert igw == [str(sentinel.igw)] assert mock_filter.get_related_igws.mock_calls == [call(ec2_doc)] + def test_C7N_CELFilter_get_related_security_configs(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] glue_doc = {"ResourceType": "glue", "Name": "default-security-config"} with celpy.c7nlib.C7NContext(filter=mock_filter): sec_config = celpy.c7nlib.get_related_security_configs(glue_doc) assert sec_config == [str(sentinel.sec_config)] assert mock_filter.get_related_security_configs.mock_calls == [call(glue_doc)] + def test_C7N_CELFilter_get_related_vpc(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): vpc = celpy.c7nlib.get_related_vpc(ec2_doc) assert vpc == [str(sentinel.vpc)] assert mock_filter.get_related_vpc.mock_calls == [call(ec2_doc)] + def test_C7N_CELFilter_get_related_kms_keys(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): vpc = celpy.c7nlib.get_related_kms_keys(ec2_doc) assert vpc == [str(sentinel.kms_key)] assert mock_filter.get_related_kms_keys.mock_calls == [call(ec2_doc)] + def test_C7N_CELFilter_security_group(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): sg_ids = celpy.c7nlib.security_group(ec2_doc) assert sg_ids == [str(sentinel.sg_id)] assert mock_filter.get_related.mock_calls == [call([ec2_doc])] + def test_C7N_CELFilter_subnet(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): subnet_ids = celpy.c7nlib.subnet(ec2_doc) @@ -1164,7 +1290,7 @@ def test_C7N_CELFilter_subnet(celfilter_instance): def test_C7N_CELFilter_flow_logs(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): flow_logs = celpy.c7nlib.flow_logs(ec2_doc) @@ -1172,17 +1298,19 @@ def test_C7N_CELFilter_flow_logs(celfilter_instance, mock_manager): [ celpy.celtypes.MapType( { - celpy.celtypes.StringType('ResourceId'): - celpy.celtypes.StringType('i-123456789') + celpy.celtypes.StringType("ResourceId"): celpy.celtypes.StringType( + "i-123456789" + ) } ) ] ) - ec2_client = mock_manager['ec2_client'] + ec2_client = mock_manager["ec2_client"] assert ec2_client.describe_flow_logs.mock_calls == [call()] + def test_C7N_CELFilter_vpc(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): vpc_ids = celpy.c7nlib.vpc(ec2_doc) @@ -1191,7 +1319,7 @@ def test_C7N_CELFilter_vpc(celfilter_instance): def test_C7N_CELFilter_subst(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): revised_path = celpy.c7nlib.subst("some_jmespath_with.{account_id}.in_it") @@ -1199,18 +1327,18 @@ def test_C7N_CELFilter_subst(celfilter_instance): def test_C7N_CELFilter_credentials(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): credentials = celpy.c7nlib.credentials(ec2_doc) assert credentials == str(sentinel.credential) - assert mock_filter.get_credential_report.mock_calls == [call( - {'ResourceType': 'ec2', 'InstanceId': 'i-123456789'} - )] + assert mock_filter.get_credential_report.mock_calls == [ + call({"ResourceType": "ec2", "InstanceId": "i-123456789"}) + ] def test_C7N_CELFilter_kms_alias(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): aliases = celpy.c7nlib.kms_alias(ec2_doc) @@ -1221,7 +1349,7 @@ def test_C7N_CELFilter_kms_alias(celfilter_instance): def test_C7N_CELFilter_kms_key(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ec2_doc = {"ResourceType": "ec2", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): keys = celpy.c7nlib.kms_key(ec2_doc) @@ -1232,7 +1360,7 @@ def test_C7N_CELFilter_kms_key(celfilter_instance): def test_C7N_CELFilter_all_images(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ami_doc = {"ResourceType": "ami", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): images = celpy.c7nlib.all_images() @@ -1244,7 +1372,7 @@ def test_C7N_CELFilter_all_images(celfilter_instance): def test_C7N_CELFilter_all_snapshots(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] ebs_doc = {"ResourceType": "ebs", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): images = celpy.c7nlib.all_snapshots() @@ -1256,19 +1384,19 @@ def test_C7N_CELFilter_all_snapshots(celfilter_instance): def test_C7N_CELFilter_all_launch_configuration_names(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] asg_doc = {"ResourceType": "asg", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): launch_config_names = celpy.c7nlib.all_launch_configuration_names() assert launch_config_names == celpy.celtypes.ListType( [celpy.celtypes.StringType(str(sentinel.asg_launch_config_name))] ) - assert mock_filter.manager.get_resource_manager.mock_calls == [call('asg')] - assert mock_manager['asg_resource_manager'].resources.mock_calls == [call()] + assert mock_filter.manager.get_resource_manager.mock_calls == [call("asg")] + assert mock_manager["asg_resource_manager"].resources.mock_calls == [call()] def test_C7N_CELFilter_all_service_roles(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] iam_doc = {"ResourceType": "iam-role", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): launch_config_names = celpy.c7nlib.all_service_roles() @@ -1279,7 +1407,7 @@ def test_C7N_CELFilter_all_service_roles(celfilter_instance): def test_C7N_CELFilter_all_instance_profiles(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] iam_doc = {"ResourceType": "iam-profile", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): launch_config_names = celpy.c7nlib.all_instance_profiles() @@ -1290,19 +1418,19 @@ def test_C7N_CELFilter_all_instance_profiles(celfilter_instance): def test_C7N_CELFilter_all_dbsubenet_groups(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] rds_doc = {"ResourceType": "rds-subnet-group", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): launch_config_names = celpy.c7nlib.all_dbsubenet_groups() assert launch_config_names == celpy.celtypes.ListType( [celpy.celtypes.StringType(str(sentinel.rds_subnet_group_name))] ) - assert mock_filter.manager.get_resource_manager.mock_calls == [call('rds')] - assert mock_manager['rds_resource_manager'].resources.mock_calls == [call()] + assert mock_filter.manager.get_resource_manager.mock_calls == [call("rds")] + assert mock_manager["rds_resource_manager"].resources.mock_calls == [call()] def test_C7N_CELFilter_all_scan_groups(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] vpc_doc = {"ResourceType": "vpc", "InstanceId": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): launch_config_names = celpy.c7nlib.all_scan_groups() @@ -1313,59 +1441,76 @@ def test_C7N_CELFilter_all_scan_groups(celfilter_instance): def test_C7N_CELFilter_get_access_log(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] elb_doc = {"ResourceType": "elb", "LoadBalancerName": "i-123456789"} with celpy.c7nlib.C7NContext(filter=mock_filter): launch_config_names = celpy.c7nlib.get_access_log(elb_doc) - assert launch_config_names == celpy.celtypes.ListType([ - celpy.celtypes.MapType({ - celpy.celtypes.StringType("Enabled"): celpy.celtypes.BoolType(True), - }) - ]) + assert launch_config_names == celpy.celtypes.ListType( + [ + celpy.celtypes.MapType( + { + celpy.celtypes.StringType("Enabled"): celpy.celtypes.BoolType(True), + } + ) + ] + ) assert mock_filter.manager.session_factory.return_value.client.mock_calls == [ - call('elb') + call("elb") ] - assert mock_manager['elb_client'].describe_load_balancer_attributes.mock_calls == [ - call(LoadBalancerName='i-123456789') + assert mock_manager["elb_client"].describe_load_balancer_attributes.mock_calls == [ + call(LoadBalancerName="i-123456789") ] + def test_C7N_CELFilter_get_load_balancer(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] - elb_doc = {"ResourceType": "app-elb", "LoadBalancerArn": "arn:us-east-1:app-elb:123456789:etc"} + mock_filter = celfilter_instance["the_filter"] + elb_doc = { + "ResourceType": "app-elb", + "LoadBalancerArn": "arn:us-east-1:app-elb:123456789:etc", + } with celpy.c7nlib.C7NContext(filter=mock_filter): launch_config_names = celpy.c7nlib.get_load_balancer(elb_doc) - assert launch_config_names == celpy.celtypes.MapType({ - celpy.celtypes.StringType("access_logs.s3.enabled"): celpy.celtypes.BoolType(True), - celpy.celtypes.StringType("boolean"): celpy.celtypes.BoolType(False), - celpy.celtypes.StringType("integer"): celpy.celtypes.IntType(42), - celpy.celtypes.StringType("string"): celpy.celtypes.StringType("other"), - }) + assert launch_config_names == celpy.celtypes.MapType( + { + celpy.celtypes.StringType( + "access_logs.s3.enabled" + ): celpy.celtypes.BoolType(True), + celpy.celtypes.StringType("boolean"): celpy.celtypes.BoolType(False), + celpy.celtypes.StringType("integer"): celpy.celtypes.IntType(42), + celpy.celtypes.StringType("string"): celpy.celtypes.StringType("other"), + } + ) assert mock_filter.manager.session_factory.return_value.client.mock_calls == [ - call('elbv2') + call("elbv2") ] - assert mock_manager['elbv2_client'].describe_load_balancer_attributes.mock_calls == [ - call(LoadBalancerArn='arn:us-east-1:app-elb:123456789:etc') + assert mock_manager[ + "elbv2_client" + ].describe_load_balancer_attributes.mock_calls == [ + call(LoadBalancerArn="arn:us-east-1:app-elb:123456789:etc") ] def test_C7N_CELFilter_get_raw_health_events(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] - health_events = mock_manager['health_events'] + mock_filter = celfilter_instance["the_filter"] + health_events = mock_manager["health_events"] request = celpy.celtypes.MapType( { - celpy.celtypes.StringType("services"): - celpy.celtypes.ListType([celpy.celtypes.StringType("ELASTICFILESYSTEM")]), - celpy.celtypes.StringType("regions"): - celpy.celtypes.ListType([ + celpy.celtypes.StringType("services"): celpy.celtypes.ListType( + [celpy.celtypes.StringType("ELASTICFILESYSTEM")] + ), + celpy.celtypes.StringType("regions"): celpy.celtypes.ListType( + [ celpy.celtypes.StringType("us-east-1"), - celpy.celtypes.StringType("global") - ]), - celpy.celtypes.StringType("eventStatusCodes"): - celpy.celtypes.ListType([ - celpy.celtypes.StringType('open'), - celpy.celtypes.StringType('upcoming') - ]), - } + celpy.celtypes.StringType("global"), + ] + ), + celpy.celtypes.StringType("eventStatusCodes"): celpy.celtypes.ListType( + [ + celpy.celtypes.StringType("open"), + celpy.celtypes.StringType("upcoming"), + ] + ), + } ) with celpy.c7nlib.C7NContext(filter=mock_filter): doc = celpy.c7nlib.get_raw_health_events(request) @@ -1373,62 +1518,65 @@ def test_C7N_CELFilter_get_raw_health_events(celfilter_instance, mock_manager): def test_C7N_CELFilter_get_health_events(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] - health_events = mock_manager['health_events'] - directory_doc = {"ResourceType": "directory", "arn": "arn:us-east-1:app-elb:123456789:etc"} + mock_filter = celfilter_instance["the_filter"] + health_events = mock_manager["health_events"] + directory_doc = { + "ResourceType": "directory", + "arn": "arn:us-east-1:app-elb:123456789:etc", + } with celpy.c7nlib.C7NContext(filter=mock_filter): health_events = celpy.c7nlib.get_health_events(directory_doc) assert health_events == celpy.json_to_cel(health_events) assert mock_filter.manager.session_factory.return_value.client.mock_calls == [ - call('health', region_name='us-east-1') + call("health", region_name="us-east-1") ] - assert mock_manager['health_client'].describe_events.mock_calls == [ + assert mock_manager["health_client"].describe_events.mock_calls == [ call( filter={ - 'services': ['EC2'], - 'regions': ['us-east-1', 'global'], - 'eventStatusCodes': ['open', 'upcoming'] + "services": ["EC2"], + "regions": ["us-east-1", "global"], + "eventStatusCodes": ["open", "upcoming"], } ) ] def test_C7N_CELFilter_shield_protection(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] + mock_filter = celfilter_instance["the_filter"] elb_doc = {"ResourceType": "elb", "arn": "arn:us-east-1:app-elb:123456789:etc"} with celpy.c7nlib.C7NContext(filter=mock_filter): shield_protection = celpy.c7nlib.shield_protection(elb_doc) assert shield_protection == celpy.json_to_cel([str(sentinel.shield)]) assert mock_filter.manager.session_factory.return_value.client.mock_calls == [ - call('shield', region_name='us-east-1') + call("shield", region_name="us-east-1") ] assert mock_filter.get_type_protections.mock_calls == [ - call(mock_manager['shield_client'], mock_filter.manager.get_model()) + call(mock_manager["shield_client"], mock_filter.manager.get_model()) ] def test_C7N_CELFilter_shield_subscription(celfilter_instance): - mock_filter = celfilter_instance['the_filter'] - account_doc = {"ResourceType": "account", "arn": "arn:us-east-1:app-elb:123456789:etc"} + mock_filter = celfilter_instance["the_filter"] + account_doc = { + "ResourceType": "account", + "arn": "arn:us-east-1:app-elb:123456789:etc", + } with celpy.c7nlib.C7NContext(filter=mock_filter): shield_subscription = celpy.c7nlib.shield_subscription(account_doc) assert shield_subscription == celpy.json_to_cel([str(sentinel.shield)]) - assert mock_filter.account_shield_subscriptions.mock_calls == [ - call(account_doc) - ] + assert mock_filter.account_shield_subscriptions.mock_calls == [call(account_doc)] def test_C7N_CELFilter_web_acls(celfilter_instance, mock_manager): - mock_filter = celfilter_instance['the_filter'] - distribution_doc = {"ResourceType": "distribution", "arn": "arn:us-east-1:app-elb:123456789:etc"} + mock_filter = celfilter_instance["the_filter"] + distribution_doc = { + "ResourceType": "distribution", + "arn": "arn:us-east-1:app-elb:123456789:etc", + } with celpy.c7nlib.C7NContext(filter=mock_filter): web_acls = celpy.c7nlib.web_acls(distribution_doc) assert web_acls == celpy.json_to_cel( {str(sentinel.waf_name): str(sentinel.waf_acl_id)} ) - assert mock_filter.manager.get_resource_manager.mock_calls == [ - call("waf") - ] - assert mock_manager['waf_resource_manager'].resources.mock_calls == [ - call() - ] + assert mock_filter.manager.get_resource_manager.mock_calls == [call("waf")] + assert mock_manager["waf_resource_manager"].resources.mock_calls == [call()] diff --git a/tests/test_celtypes.py b/tests/test_celtypes.py index 582c4b9..0f7e7bf 100644 --- a/tests/test_celtypes.py +++ b/tests/test_celtypes.py @@ -15,6 +15,7 @@ """ Test all the celtype methods. """ + import datetime import math from unittest.mock import sentinel @@ -28,7 +29,7 @@ def test_bool_type(): t, f = BoolType(True), BoolType(False) - exc = CELEvalError(('summary', 'details')) + exc = CELEvalError(("summary", "details")) assert logical_condition(t, sentinel.true, sentinel.false) == sentinel.true assert logical_condition(f, sentinel.true, sentinel.false) == sentinel.false @@ -73,15 +74,15 @@ def test_bool_type(): def test_bytes_type(): - b_0 = BytesType(b'bytes') - b_1 = BytesType('bytes') + b_0 = BytesType(b"bytes") + b_1 = BytesType("bytes") b_2 = BytesType([98, 121, 116, 101, 115]) with pytest.raises(TypeError): BytesType(3.14) assert repr(b_0) == "BytesType(b'bytes')" - assert BytesType(None) == BytesType(b'') - assert BytesType(MessageType({"value": BytesType(b'42')})) == BytesType(b'42') - assert b_0.contains(b'byte') + assert BytesType(None) == BytesType(b"") + assert BytesType(MessageType({"value": BytesType(b"42")})) == BytesType(b"42") + assert b_0.contains(b"byte") def test_double_type(): @@ -105,7 +106,7 @@ def test_double_type(): assert 2 / DoubleType(0.0) == float("inf") assert 3.0 / DoubleType(4.0) == DoubleType(0.75) assert DoubleType(None) == DoubleType(0.0) - assert DoubleType(MessageType({"value": DoubleType('4.2')})) == DoubleType(4.2) + assert DoubleType(MessageType({"value": DoubleType("4.2")})) == DoubleType(4.2) def test_int_type(): @@ -206,7 +207,9 @@ def test_uint_type(): def test_list_type(): l_1 = ListType([IntType(42), IntType(6), IntType(7)]) - l_2 = ListType([IntType(42), StringType("2.718281828459045**1.791759469228055"), IntType(7)]) + l_2 = ListType( + [IntType(42), StringType("2.718281828459045**1.791759469228055"), IntType(7)] + ) assert l_1 == l_1 with pytest.raises(TypeError): assert l_1 != l_2 @@ -230,24 +233,35 @@ def test_list_type(): assert ListType(ListType([IntType(42)])) == ListType([IntType(42)]) assert l_1.contains(IntType(42)) + def test_map_type(): m_0 = MapType() - m_1 = MapType({ - StringType("A"): IntType(42), - StringType("X"): IntType(6), - StringType("Y"): IntType(7)} + m_1 = MapType( + { + StringType("A"): IntType(42), + StringType("X"): IntType(6), + StringType("Y"): IntType(7), + } + ) + m_2 = MapType( + { + StringType("A"): IntType(42), + StringType("X"): StringType("2.718281828459045**1.791759469228055"), + StringType("Y"): IntType(7), + } ) - m_2 = MapType({ - StringType("A"): IntType(42), - StringType("X"): StringType("2.718281828459045**1.791759469228055"), - StringType("Y"): IntType(7)} + m_3 = MapType( + [ + ListType([StringType("A"), IntType(42)]), + ListType([StringType("X"), IntType(6)]), + ListType([StringType("Y"), IntType(7)]), + ] ) - m_3 = MapType([ - ListType([StringType("A"), IntType(42)]), - ListType([StringType("X"), IntType(6)]), - ListType([StringType("Y"), IntType(7)])] + m_single = MapType( + { + StringType("A"): IntType(42), + } ) - m_single = MapType({StringType("A"): IntType(42),}) assert m_1 == m_1 assert m_1 == m_3 assert not m_1 != m_1 @@ -261,7 +275,8 @@ def test_map_type(): assert repr(m_1) == ( "MapType({StringType('A'): IntType(42), " "StringType('X'): IntType(6), " - "StringType('Y'): IntType(7)})") + "StringType('Y'): IntType(7)})" + ) assert m_1[StringType("A")] == IntType(42) with pytest.raises(TypeError): m_1[ListType([StringType("A")])] @@ -279,10 +294,12 @@ def test_map_type(): m_1 == DoubleType("42.0") with pytest.raises(TypeError): assert m_1 != DoubleType("42.0") - assert m_1 != MapType({ - StringType("A"): IntType(42), - StringType("X"): IntType(42), - StringType("Y"): IntType(42)} + assert m_1 != MapType( + { + StringType("A"): IntType(42), + StringType("X"): IntType(42), + StringType("Y"): IntType(42), + } ) assert m_1.contains(StringType("A")) assert m_1.get(StringType("A")) == IntType(42) @@ -294,7 +311,7 @@ def test_map_type(): def test_string_type(): - s_1 = StringType(b'bytes') + s_1 = StringType(b"bytes") s_2 = StringType("string") s_3 = StringType(42) assert repr(s_1) == "StringType('bytes')" @@ -334,10 +351,9 @@ def test_timestamp_type(): assert DurationType("30s") + TimestampType(2009, 2, 13, 23, 31, 0) == ts_1 with pytest.raises(TypeError): assert StringType("30s") + TimestampType(2009, 2, 13, 23, 31, 0) - assert ( - TimestampType(2009, 2, 13, 0, 0, 0) - TimestampType(2009, 1, 1, 0, 0, 0) - == DurationType(datetime.timedelta(days=43)) - ) + assert TimestampType(2009, 2, 13, 0, 0, 0) - TimestampType( + 2009, 1, 1, 0, 0, 0 + ) == DurationType(datetime.timedelta(days=43)) with pytest.raises(TypeError): assert TimestampType(2009, 2, 13, 23, 31, 0) - StringType("30s") assert TimestampType(2009, 2, 13, 23, 32, 0) - DurationType("30s") == ts_1 @@ -358,8 +374,8 @@ def test_timestamp_type(): def test_timestamp_type_issue_28(): - utc = TimestampType('2020-10-20T12:00:00Z') - not_utc = TimestampType('2020-10-20T12:00:00-05:00') + utc = TimestampType("2020-10-20T12:00:00Z") + not_utc = TimestampType("2020-10-20T12:00:00-05:00") assert repr(utc) == "TimestampType('2020-10-20T12:00:00Z')" assert repr(not_utc) == "TimestampType('2020-10-20T12:00:00-05:00')" @@ -370,7 +386,7 @@ def test_timestamp_type_issue_28(): def test_extended_timestamp_type(): others = { - 'et': 'US/Eastern', + "et": "US/Eastern", } TimestampType.TZ_ALIASES.update(others) ts_1 = TimestampType("2009-02-13T23:31:30Z") @@ -399,7 +415,9 @@ def test_duration_type(): assert repr(d_1) == "DurationType('43200s')" assert str(d_1) == "43200s" assert d_1 + d_1 == DurationType(IntType(86400)) - assert d_1 + TimestampType(2009, 2, 13, 11, 31, 30) == TimestampType("2009-02-13T23:31:30Z") + assert d_1 + TimestampType(2009, 2, 13, 11, 31, 30) == TimestampType( + "2009-02-13T23:31:30Z" + ) assert DurationType("8454s").getHours() == IntType(2) assert DurationType("8454s").getMinutes() == IntType(140) assert DurationType("8454s").getSeconds() == IntType(8454) diff --git a/tests/test_evaluation.py b/tests/test_evaluation.py index 33aa672..2250366 100644 --- a/tests/test_evaluation.py +++ b/tests/test_evaluation.py @@ -17,7 +17,7 @@ A large number of tests exercise :py:meth:`Evaluator.evaluate`. -The approach used here may not be ideal from a unit testing perspective. +The approach used here may not be ideal from a unit testing perspective. This approach tends to test the superclass :py:meth:`lark.visitors.Interpreter.visit`, which involves re-testing a fair amount of Lark code. @@ -29,6 +29,7 @@ visitor method directly. """ + from unittest.mock import Mock, call, sentinel import os @@ -46,18 +47,24 @@ def test_exception_syntax_error(): with pytest.raises(CELSyntaxError) as exc_info_1: - raise CELSyntaxError(sentinel.syntax_message, sentinel.syntax_line, sentinel.syntax_col) + raise CELSyntaxError( + sentinel.syntax_message, sentinel.syntax_line, sentinel.syntax_col + ) assert exc_info_1.value.args == (sentinel.syntax_message,) assert exc_info_1.value.line == sentinel.syntax_line assert exc_info_1.value.column == sentinel.syntax_col + def test_exception_unsupported_error(): with pytest.raises(CELUnsupportedError) as exc_info_2: - raise CELUnsupportedError(sentinel.unsup_message, sentinel.unsup_line, sentinel.unsup_col) + raise CELUnsupportedError( + sentinel.unsup_message, sentinel.unsup_line, sentinel.unsup_col + ) assert exc_info_2.value.args == (sentinel.unsup_message,) assert exc_info_2.value.line == sentinel.unsup_line assert exc_info_2.value.column == sentinel.unsup_col + def test_exception_eval_error(): mock_tree = Mock( meta=Mock( @@ -92,14 +99,14 @@ def test_exception_eval_error(): assert ex / 1 == ex assert ex // 1 == ex assert ex % 1 == ex - assert ex ** 1 == ex + assert ex**1 == ex assert 1 + ex == ex assert 1 - ex == ex assert 1 * ex == ex assert 1 / ex == ex assert 1 // ex == ex assert 1 % ex == ex - assert 1 ** ex == ex + assert 1**ex == ex assert not 1 == ex assert not ex == 1 assert ex() == ex @@ -118,7 +125,11 @@ def mock_operation(a, b): result_1 = mock_operation(sentinel.TypeError, sentinel.VALUE) assert isinstance(result_1, CELEvalError) - assert result_1.args == (sentinel.eval_message, TypeError, (sentinel.type_error_message,)) + assert result_1.args == ( + sentinel.eval_message, + TypeError, + (sentinel.type_error_message,), + ) assert result_1.__cause__.__class__ == TypeError with pytest.raises(ValueError) as exc_info: @@ -152,24 +163,30 @@ def test_operator_in(): Was a separate function. Revised with 0.4.0 release to be method of String,Type ListType, and MapType. """ - container_1 = celtypes.ListType([ - celtypes.IntType(42), - celtypes.IntType(6), - celtypes.IntType(7), - ]) + container_1 = celtypes.ListType( + [ + celtypes.IntType(42), + celtypes.IntType(6), + celtypes.IntType(7), + ] + ) assert operator_in(celtypes.IntType(42), container_1) assert not operator_in(celtypes.IntType(-1), container_1) - container_2 = celtypes.ListType([ - celtypes.IntType(42), - celtypes.StringType("six"), - celtypes.IntType(7), - ]) + container_2 = celtypes.ListType( + [ + celtypes.IntType(42), + celtypes.StringType("six"), + celtypes.IntType(7), + ] + ) assert operator_in(celtypes.IntType(42), container_2) assert isinstance(operator_in(celtypes.IntType(-1), container_2), CELEvalError) -@pytest.mark.skipif("re2" not in celpy.evaluation.function_matches.__globals__, reason="Not using RE2") +@pytest.mark.skipif( + "re2" not in celpy.evaluation.function_matches.__globals__, reason="Not using RE2" +) def test_function_matches_re2(): empty_string = celtypes.StringType("") # re-specific patterns which behave differently than re2 @@ -177,7 +194,9 @@ def test_function_matches_re2(): assert isinstance(function_matches(empty_string, "^\\Z"), CELEvalError) -@pytest.mark.skipif("re2" in celpy.evaluation.function_matches.__globals__, reason="Using RE2") +@pytest.mark.skipif( + "re2" in celpy.evaluation.function_matches.__globals__, reason="Using RE2" +) def test_function_matches_re(): empty_string = celtypes.StringType("") # re2-specific patterns which behave differently than standard re @@ -191,11 +210,13 @@ def test_function_matches(): def test_function_size(): - container_1 = celtypes.ListType([ - celtypes.IntType(42), - celtypes.IntType(6), - celtypes.IntType(7), - ]) + container_1 = celtypes.ListType( + [ + celtypes.IntType(42), + celtypes.IntType(6), + celtypes.IntType(7), + ] + ) assert function_size(container_1) == celtypes.IntType(3) with pytest.raises(TypeError): @@ -220,7 +241,10 @@ def test_referent(): assert r_1.value == celtypes.IntType(42) nc = NameContainer() r_1.container = nc - assert repr(r_1) == f"Referent(annotation={celtypes.IntType!r}, container={nc!r}, _value={celtypes.IntType(42)!r})" + assert ( + repr(r_1) + == f"Referent(annotation={celtypes.IntType!r}, container={nc!r}, _value={celtypes.IntType(42)!r})" + ) assert r_1.annotation is celtypes.IntType assert r_1.container is nc assert r_1.value == nc # preferred over the assigned value. @@ -241,8 +265,12 @@ def test_name_container(): } ) assert nc.find_name([]).value == nc - assert nc.find_name(["a","b","c"]).value == celtypes.StringType("yeah") - member_dot = nc.resolve_name("", "a").container.resolve_name("", "b").container.resolve_name("", "c") + assert nc.find_name(["a", "b", "c"]).value == celtypes.StringType("yeah") + member_dot = ( + nc.resolve_name("", "a") + .container.resolve_name("", "b") + .container.resolve_name("", "c") + ) assert member_dot.value == celtypes.StringType("yeah") nc2 = NameContainer() @@ -255,6 +283,7 @@ def test_name_container_init(): nc = NameContainer("a", celtypes.MapType) assert nc["a"] == celtypes.MapType + def test_name_container_errors(): nc = NameContainer("a", celtypes.MapType) assert nc["a"] == celtypes.MapType @@ -270,8 +299,8 @@ def test_activation_no_package_no_vars(): a.resolve_variable("x") assert a.identifiers == {} a_n = a.nested_activation( - annotations={"x": celtypes.IntType}, - vars={"x": celtypes.IntType(42)}) + annotations={"x": celtypes.IntType}, vars={"x": celtypes.IntType(42)} + ) assert a_n.resolve_variable("x") == celtypes.IntType(42) @@ -290,39 +319,31 @@ def test_activation_jq_package_vars(): a = Activation( annotations={"jq": celtypes.MapType}, package="jq", - vars={ - "jq": {celtypes.StringType("json"): celtypes.StringType("document")} - } + vars={"jq": {celtypes.StringType("json"): celtypes.StringType("document")}}, ) # The JQ-like ``.json`` expression is resolved inside the "jq" package. - assert a.resolve_variable(celtypes.StringType("json")) == celtypes.StringType("document") + assert a.resolve_variable(celtypes.StringType("json")) == celtypes.StringType( + "document" + ) # A nested activation (inside a macro, for example) a_n = a.nested_activation( - annotations={"x": celtypes.IntType}, - vars={"x": celtypes.IntType(42)} + annotations={"x": celtypes.IntType}, vars={"x": celtypes.IntType(42)} ) assert a_n.resolve_variable("x") == celtypes.IntType(42) # We should see globals (in the outer context) - assert a_n.resolve_variable(celtypes.StringType("json")) == celtypes.StringType("document") + assert a_n.resolve_variable(celtypes.StringType("json")) == celtypes.StringType( + "document" + ) def test_activation_activation(): - b = Activation( - vars={ - celtypes.StringType("param"): celtypes.DoubleType(42.0) - } - ) + b = Activation(vars={celtypes.StringType("param"): celtypes.DoubleType(42.0)}) c = b.clone() assert c.resolve_variable(celtypes.StringType("param")) == celtypes.DoubleType(42.0) def test_activation_dot_names(): - a = Activation( - package='x', - vars={ - 'x.y': celtypes.DoubleType(42.0) - } - ) + a = Activation(package="x", vars={"x.y": celtypes.DoubleType(42.0)}) assert a.resolve_variable(celtypes.StringType("y")) == celtypes.DoubleType(42.0) with pytest.raises(KeyError): a.resolve_variable(celtypes.StringType("z")) @@ -331,12 +352,12 @@ def test_activation_dot_names(): def test_activation_overlapping_dot_names(): a = Activation( annotations={ - 'A.B': celtypes.DoubleType, - 'A.C': celtypes.BoolType, + "A.B": celtypes.DoubleType, + "A.C": celtypes.BoolType, } ) assert isinstance(a.resolve_variable("A"), NameContainer) - print(f'{a.resolve_variable("A")!r}') + print(f"{a.resolve_variable('A')!r}") assert a.resolve_variable("A")["B"].value == celtypes.DoubleType assert a.resolve_variable("A")["C"].value == celtypes.BoolType @@ -344,33 +365,23 @@ def test_activation_overlapping_dot_names(): def test_activation_multi_package_name(): a = Activation( annotations={ - 'A.B.a': celtypes.DoubleType, - 'A.B.C.a': celtypes.BoolType, - 'A.B.C': celtypes.IntType, # This is ambiguous and is ignored when finding "a". + "A.B.a": celtypes.DoubleType, + "A.B.C.a": celtypes.BoolType, + "A.B.C": celtypes.IntType, # This is ambiguous and is ignored when finding "a". }, - package="A.B.C" + package="A.B.C", ) assert a.resolve_variable("a") == celtypes.BoolType def test_activation_bad_dot_name_syntax(): with pytest.raises(ValueError): - a = Activation( - package='x', - vars={ - 'x.y+z': celtypes.DoubleType(42.0) - } - ) + a = Activation(package="x", vars={"x.y+z": celtypes.DoubleType(42.0)}) + @pytest.fixture def mock_tree(): - tree = Mock( - name='mock_tree', - data='ident', - children=[ - Mock(value=sentinel.ident) - ] - ) + tree = Mock(name="mock_tree", data="ident", children=[Mock(value=sentinel.ident)]) return tree @@ -380,6 +391,7 @@ class Mock_Eval: def __init__(self): self.logger = Mock() self.level = 1 + @trace def method(self, tree): return sentinel.result @@ -389,180 +401,144 @@ def method(self, tree): assert result == sentinel.result assert e.logger.debug.mock_calls == [ - call('%s%r', '| ', mock_tree), - call('%s%s -> %r', '| ', 'ident', sentinel.result) + call("%s%r", "| ", mock_tree), + call("%s%s -> %r", "| ", "ident", sentinel.result), ] + def test_set_activation(): tree = lark.Tree(data="literal", children=[]) - activation = Activation( - vars={ - 'name': sentinel.value - } - ) + activation = Activation(vars={"name": sentinel.value}) e_0 = Evaluator(tree, activation) - assert e_0.ident_value('name') == sentinel.value - assert e_0.ident_value('int') == celtypes.IntType + assert e_0.ident_value("name") == sentinel.value + assert e_0.ident_value("int") == celtypes.IntType e_1 = Evaluator(ast=e_0.tree, activation=e_0.activation) - e_1.set_activation( - {'name': sentinel.local_value} - ) - assert e_1.ident_value('name') == sentinel.local_value - assert e_1.ident_value('int') == celtypes.IntType - assert e_0.ident_value('name') == sentinel.value - assert e_0.ident_value('int') == celtypes.IntType + e_1.set_activation({"name": sentinel.local_value}) + assert e_1.ident_value("name") == sentinel.local_value + assert e_1.ident_value("int") == celtypes.IntType + assert e_0.ident_value("name") == sentinel.value + assert e_0.ident_value("int") == celtypes.IntType def test_function_eval_0(monkeypatch): - tree = lark.Tree( - data="primary", - children=[] - ) + tree = lark.Tree(data="primary", children=[]) activation = Mock(spec=Activation, resolve_function=Mock(side_effect=KeyError)) - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) unknown_function_result = evaluator.function_eval(lark.Token("IDENT", "nope")) print(f"{unknown_function_result=}") assert isinstance(unknown_function_result, CELEvalError) + def test_function_eval_1(monkeypatch): - tree = lark.Tree( - data="primary", - children=[] - ) - activation = Mock(spec=Activation, resolve_function=Mock(return_value=function_size)) - evaluator = Evaluator( - tree, - activation + tree = lark.Tree(data="primary", children=[]) + activation = Mock( + spec=Activation, resolve_function=Mock(return_value=function_size) ) + evaluator = Evaluator(tree, activation) error = CELEvalError(sentinel.message) - function_of_error_result = evaluator.function_eval(lark.Token("IDENT", "size"), error) + function_of_error_result = evaluator.function_eval( + lark.Token("IDENT", "size"), error + ) print(f"{function_of_error_result=}") assert function_of_error_result == error + def test_function_eval_2(monkeypatch): mock_size = Mock(side_effect=ValueError(sentinel.value)) - tree = lark.Tree( - data="primary", - children=[] - ) - activation = Mock(spec=Activation, - resolve_function=Mock(return_value=mock_size)) - evaluator = Evaluator( - tree, - activation - ) + tree = lark.Tree(data="primary", children=[]) + activation = Mock(spec=Activation, resolve_function=Mock(return_value=mock_size)) + evaluator = Evaluator(tree, activation) value = evaluator.function_eval(lark.Token("IDENT", "size")) assert isinstance(value, CELEvalError) assert value.args[1] == ValueError, f"{value.args} != (..., ValueError, ...)" - assert value.args[2] == (sentinel.value,), f"{value.args} != (..., ..., (sentinel.value,))" + assert value.args[2] == (sentinel.value,), ( + f"{value.args} != (..., ..., (sentinel.value,))" + ) + def test_function_eval_3(monkeypatch): mock_size = Mock(side_effect=TypeError(sentinel.type)) - tree = lark.Tree( - data="primary", - children=[] - ) - activation = Mock(spec=Activation, - resolve_function=Mock(return_value=mock_size)) - evaluator = Evaluator( - tree, - activation - ) + tree = lark.Tree(data="primary", children=[]) + activation = Mock(spec=Activation, resolve_function=Mock(return_value=mock_size)) + evaluator = Evaluator(tree, activation) value = evaluator.function_eval(lark.Token("IDENT", "size")) assert isinstance(value, CELEvalError) assert value.args[1] == TypeError, f"{value.args} != (..., TypeError, ...)" - assert value.args[2] == (sentinel.type,), f"{value.args} != (..., ..., (sentinel.type,))" + assert value.args[2] == (sentinel.type,), ( + f"{value.args} != (..., ..., (sentinel.type,))" + ) def test_method_eval_0(monkeypatch): - tree = lark.Tree( - data="primary", - children=[] - ) - activation = Mock(spec=Activation, functions=sentinel.FUNCTIONS, resolve_function=Mock(side_effect=KeyError)) - evaluator = Evaluator( - tree, - activation + tree = lark.Tree(data="primary", children=[]) + activation = Mock( + spec=Activation, + functions=sentinel.FUNCTIONS, + resolve_function=Mock(side_effect=KeyError), ) + evaluator = Evaluator(tree, activation) unknown_method_result = evaluator.method_eval(None, lark.Token("IDENT", "nope")) print(f"{unknown_method_result=}") assert isinstance(unknown_method_result, CELEvalError) + def test_method_eval_1(monkeypatch): - tree = lark.Tree( - data="primary", - children=[] - ) - activation = Mock(spec=Activation, resolve_function=Mock(return_value=function_size)) - evaluator = Evaluator( - tree, - activation + tree = lark.Tree(data="primary", children=[]) + activation = Mock( + spec=Activation, resolve_function=Mock(return_value=function_size) ) + evaluator = Evaluator(tree, activation) error = CELEvalError(sentinel.message) assert evaluator.method_eval(error, lark.Token("IDENT", "size"), None) == error assert evaluator.method_eval(None, lark.Token("IDENT", "size"), error) == error + def test_method_eval_2(monkeypatch): mock_function = Mock(side_effect=ValueError(sentinel.value)) - tree = lark.Tree( - data="primary", - children=[] - ) - activation = Mock(spec=Activation, - resolve_function=Mock(return_value=mock_function)) - evaluator = Evaluator( - tree, - activation + tree = lark.Tree(data="primary", children=[]) + activation = Mock( + spec=Activation, resolve_function=Mock(return_value=mock_function) ) + evaluator = Evaluator(tree, activation) value = evaluator.method_eval(None, lark.Token("IDENT", "size")) assert isinstance(value, CELEvalError) assert value.args[1] == ValueError, f"{value.args} != (..., ValueError, ...)" - assert value.args[2] == (sentinel.value,), f"{value.args} != (..., ..., (sentinel.value,))" + assert value.args[2] == (sentinel.value,), ( + f"{value.args} != (..., ..., (sentinel.value,))" + ) + def test_method_eval_3(monkeypatch): mock_function = Mock(side_effect=TypeError(sentinel.type)) - tree = lark.Tree( - data="primary", - children=[] - ) - activation = Mock(spec=Activation, - resolve_function=Mock(return_value=mock_function)) - evaluator = Evaluator( - tree, - activation + tree = lark.Tree(data="primary", children=[]) + activation = Mock( + spec=Activation, resolve_function=Mock(return_value=mock_function) ) + evaluator = Evaluator(tree, activation) value = evaluator.method_eval(None, lark.Token("IDENT", "size")) assert isinstance(value, CELEvalError) assert value.args[1] == TypeError, f"{value.args} != (..., TypeError, ...)" - assert value.args[2] == (sentinel.type,), f"{value.args} != (..., ..., (sentinel.type,))" + assert value.args[2] == (sentinel.type,), ( + f"{value.args} != (..., ..., (sentinel.type,))" + ) def test_macro_has_eval(monkeypatch): - visit_children = Mock( - return_value=[sentinel.values] - ) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) - tree = lark.Tree( - data="exprlist", - children=[], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + visit_children = Mock(return_value=[sentinel.values]) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) + tree = lark.Tree(data="exprlist", children=[], meta=Mock(line=1, column=1)) + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.macro_has_eval(sentinel.exprlist) == celpy.celtypes.BoolType( + True ) - assert evaluator_0.macro_has_eval(sentinel.exprlist) == celpy.celtypes.BoolType(True) # Many of the following tests all use :py:meth:`Evaluator.evaluate`. @@ -577,54 +553,51 @@ def test_eval_expr_1(): expr : conditionalor ["?" conditionalor ":" expr] """ tree = lark.Tree( - data='expr', + data="expr", children=[ lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_="INT_LIT", value="42"), - ] + ], ), - ] + ], ) activation = Mock() - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) assert evaluator.evaluate() == celtypes.IntType(42) + @pytest.fixture def mock_left_expr_tree(): tree = lark.Tree( - data='expr', + data="expr", children=[ lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_="BOOL_LIT", value="true"), - ] + ], ), lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_="INT_LIT", value="6"), - ] + ], ), - sentinel.DO_NOT_EVALUATE # Test will crash if this is evaluated + sentinel.DO_NOT_EVALUATE, # Test will crash if this is evaluated ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) return tree def test_eval_expr_3_left_good(mock_left_expr_tree): """Assert ``true ? 6 : invalid`` does not execute the invalid expression.""" - activation = Mock(resolve_function=Mock(return_value=celpy.celtypes.logical_condition)) - evaluator = Evaluator( - mock_left_expr_tree, - activation + activation = Mock( + resolve_function=Mock(return_value=celpy.celtypes.logical_condition) ) + evaluator = Evaluator(mock_left_expr_tree, activation) assert evaluator.evaluate() == celtypes.IntType(6) # assert did not crash; therefore, invalid node not touched @@ -632,6 +605,7 @@ def test_eval_expr_3_left_good(mock_left_expr_tree): def test_eval_expr_3_bad_override(mock_left_expr_tree): def bad_condition(a, b, c): raise TypeError + activation = Mock(resolve_function=Mock(return_value=bad_condition)) evaluator = Evaluator( mock_left_expr_tree, @@ -639,11 +613,17 @@ def bad_condition(a, b, c): ) with pytest.raises(celpy.evaluation.CELEvalError) as exc_info: evaluator.evaluate() - assert exc_info.value.args == ("found no matching overload for _?_:_ applied to '(, , )'", TypeError, ()) + assert exc_info.value.args == ( + "found no matching overload for _?_:_ applied to '(, , )'", + 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(resolve_function=Mock(return_value=bad_condition)) evaluator = Evaluator( mock_left_expr_tree, @@ -652,54 +632,45 @@ def bad_condition(a, b, c): with pytest.raises(celpy.evaluation.CELEvalError) as exc_info: evaluator.evaluate() print(repr(exc_info.value.args)) - assert exc_info.value.args == ('Baseline Error',) + assert exc_info.value.args == ("Baseline Error",) @pytest.fixture def mock_right_expr_tree(): tree = lark.Tree( - data='expr', + data="expr", children=[ lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_="BOOL_LIT", value="false"), - ] + ], ), sentinel.DO_NOT_EVALUATE, # Test will crash if this is evaluated lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_="INT_LIT", value="7"), - ] + ], ), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) return tree + def test_eval_expr_3_right_good(mock_right_expr_tree): """Assert ``false ? invalid : 7`` does not execute the invalid expression.""" activation = Mock(resolve_function=Mock(return_value=celtypes.logical_condition)) - evaluator = Evaluator( - mock_right_expr_tree, - activation - ) + evaluator = Evaluator(mock_right_expr_tree, activation) assert evaluator.evaluate() == celtypes.IntType(7) # assert did not crash; therefore, invalid node not touched def test_eval_expr_0(): - tree = lark.Tree( - data='expr', - children=[], - meta=Mock(line=1, column=1) - ) + tree = lark.Tree(data="expr", children=[], meta=Mock(line=1, column=1)) activation = Mock() - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) with pytest.raises(celpy.evaluation.CELSyntaxError): evaluator.evaluate() @@ -709,12 +680,12 @@ def binop_1_tree(data, lit_type, lit_value): data=data, children=[ lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_=lit_type, value=lit_value), - ] + ], ), - ] + ], ) return tree @@ -722,10 +693,7 @@ def binop_1_tree(data, lit_type, lit_value): def test_eval_conditionalor_1(): tree = binop_1_tree("conditionalor", "INT_LIT", "42") activation = Mock() - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) assert evaluator.evaluate() == celtypes.IntType(42) @@ -734,35 +702,34 @@ def binop_2_tree(data, lit_type, lit_value_1, lit_value_2): data=data, children=[ lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_=lit_type, value=lit_value_1), - ] + ], ), lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_=lit_type, value=lit_value_2), - ] + ], ), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) return tree + def test_eval_conditionalor_2_good(): tree = binop_2_tree("conditionalor", "BOOL_LIT", "false", "true") activation = Mock(resolve_function=Mock(return_value=celtypes.logical_or)) - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) assert evaluator.evaluate() == celtypes.BoolType(True) def test_eval_conditionalor_2_bad_override(): def bad_logical_or(a, b): raise TypeError + tree = binop_2_tree("conditionalor", "BOOL_LIT", "false", "true") activation = Mock(resolve_function=Mock(return_value=bad_logical_or)) evaluator = Evaluator( @@ -773,21 +740,16 @@ def bad_logical_or(a, b): with pytest.raises(celpy.evaluation.CELEvalError): evaluator.evaluate() + def binop_broken_tree(data): - tree = lark.Tree( - data=data, - children=[], - meta=Mock(line=1, column=1) - ) + tree = lark.Tree(data=data, children=[], meta=Mock(line=1, column=1)) return tree + def test_eval_conditionalor_0(): tree = binop_broken_tree("conditionalor") activation = Mock() - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) with pytest.raises(celpy.evaluation.CELSyntaxError): evaluator.evaluate() @@ -795,26 +757,21 @@ def test_eval_conditionalor_0(): def test_eval_conditionaland_1(): tree = binop_1_tree("conditionaland", "INT_LIT", "42") activation = Mock() - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) assert evaluator.evaluate() == celtypes.IntType(42) def test_eval_conditionaland_2_good(): tree = binop_2_tree("conditionaland", "BOOL_LIT", "false", "true") activation = Mock(resolve_function=Mock(return_value=celtypes.logical_and)) - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) assert evaluator.evaluate() == celtypes.BoolType(False) def test_eval_conditionaland_2_bad_override(): def bad_logical_and(a, b): raise TypeError + tree = binop_2_tree("conditionaland", "BOOL_LIT", "false", "true") activation = Mock(resolve_function=Mock(return_value=bad_logical_and)) evaluator = Evaluator( @@ -824,13 +781,11 @@ def bad_logical_and(a, b): with pytest.raises(celpy.evaluation.CELEvalError): evaluator.evaluate() + def test_eval_conditionaland_0(): tree = binop_broken_tree("conditionaland") activation = Mock() - evaluator = Evaluator( - tree, - activation - ) + evaluator = Evaluator(tree, activation) with pytest.raises(celpy.evaluation.CELSyntaxError): evaluator.evaluate() @@ -843,20 +798,75 @@ def test_eval_conditionaland_0(): ("relation", "relation_gt", "INT_LIT", "6", "7", celtypes.BoolType(False), "_>_"), ("relation", "relation_ge", "INT_LIT", "6", "7", celtypes.BoolType(False), "_>=_"), ("relation", "relation_eq", "INT_LIT", "42", "42", celtypes.BoolType(True), "_==_"), - ("relation", "relation_ne", "INT_LIT", "42", "42", celtypes.BoolType(False), "_!=_"), - ("relation", "relation_in", - "STRING_LIT", "b", ["a", "b", "c"], celtypes.BoolType(True), "_in_"), + ( + "relation", + "relation_ne", + "INT_LIT", + "42", + "42", + celtypes.BoolType(False), + "_!=_", + ), + ( + "relation", + "relation_in", + "STRING_LIT", + "b", + ["a", "b", "c"], + celtypes.BoolType(True), + "_in_", + ), ("addition", "addition_add", "INT_LIT", "40", "2", celtypes.IntType(42), "_+_"), ("addition", "addition_sub", "INT_LIT", "44", "2", celtypes.IntType(42), "_-_"), - ("addition", "addition_add", "INT_LIT", "9223372036854775807", "1", CELEvalError, "_+_"), - ("multiplication", "multiplication_mul", "INT_LIT", "6", "7", celtypes.IntType(42), "_*_"), - ("multiplication", "multiplication_div", "INT_LIT", "84", "2", celtypes.IntType(42), "_/_"), - ("multiplication", "multiplication_mod", "INT_LIT", "85", "43", celtypes.IntType(42), "_%_"), - ("multiplication", "multiplication_mul", - "INT_LIT", "9223372036854775807", "2", CELEvalError, "_*_"), + ( + "addition", + "addition_add", + "INT_LIT", + "9223372036854775807", + "1", + CELEvalError, + "_+_", + ), + ( + "multiplication", + "multiplication_mul", + "INT_LIT", + "6", + "7", + celtypes.IntType(42), + "_*_", + ), + ( + "multiplication", + "multiplication_div", + "INT_LIT", + "84", + "2", + celtypes.IntType(42), + "_/_", + ), + ( + "multiplication", + "multiplication_mod", + "INT_LIT", + "85", + "43", + celtypes.IntType(42), + "_%_", + ), + ( + "multiplication", + "multiplication_mul", + "INT_LIT", + "9223372036854775807", + "2", + CELEvalError, + "_*_", + ), ("multiplication", "multiplication_div", "INT_LIT", "84", "0", CELEvalError, "_/_"), ] + @pytest.fixture(params=binary_operator_params, ids=lambda f: f[6]) def binop_trees(request): """Creates three binary operator trees: @@ -878,14 +888,18 @@ def binop_trees(request): The function name is used to exercise the ``t_2`` tree with a bad function binding that raises an expected TypeError. """ - parent_tree_data, tree_data, lit_type, lit_value_1, lit_value_2, expected, function = request.param + ( + parent_tree_data, + tree_data, + lit_type, + lit_value_1, + lit_value_2, + expected, + function, + ) = request.param # Broken tree. - t_0 = lark.Tree( - data=parent_tree_data, - children=[], - meta=Mock(line=1, column=1) - ) + t_0 = lark.Tree(data=parent_tree_data, children=[], meta=Mock(line=1, column=1)) # No operand tree. t_1 = binop_1_tree(parent_tree_data, "INT_LIT", "42") @@ -893,23 +907,20 @@ def binop_trees(request): # A two-operand treee with either a simple or complex right-hand-side. if isinstance(lit_value_2, list): right_hand_side = lark.Tree( - data='exprlist', + data="exprlist", children=[ lark.Tree( - data='literal', - children=[ - lark.Token(type_=lit_type, value=expr) - ] + data="literal", children=[lark.Token(type_=lit_type, value=expr)] ) for expr in lit_value_2 - ] + ], ) else: right_hand_side = lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_=lit_type, value=lit_value_2), - ] + ], ) t_2 = lark.Tree( @@ -919,17 +930,17 @@ def binop_trees(request): data=tree_data, children=[ lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_=lit_type, value=lit_value_1), - ] + ], ), lark.Token(type_="relop", value="not used"), - ] + ], ), - right_hand_side + right_hand_side, ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) return t_0, t_1, t_2, expected, function @@ -942,23 +953,14 @@ def test_binops(binop_trees): t_0, t_1, t_2, expected, function = binop_trees activation = Mock(resolve_function=Mock(return_value=base_functions[function])) - evaluator_0 = Evaluator( - t_0, - activation - ) + evaluator_0 = Evaluator(t_0, activation) with pytest.raises(celpy.evaluation.CELSyntaxError): evaluator_0.evaluate() - evaluator_1 = Evaluator( - t_1, - activation - ) + evaluator_1 = Evaluator(t_1, activation) assert evaluator_1.evaluate() == celtypes.IntType(42) - evaluator_2_g = Evaluator( - t_2, - activation - ) + evaluator_2_g = Evaluator(t_2, activation) if isinstance(expected, type): with pytest.raises(expected): evaluator_2_g.evaluate() @@ -967,6 +969,7 @@ def test_binops(binop_trees): def bad_function(a, b): raise TypeError + activation = Mock(resolve_function=Mock(return_value=bad_function)) evaluator_2_b = Evaluator( t_2, @@ -984,6 +987,7 @@ def bad_function(a, b): ("unary", "unary_neg", "INT_LIT", "-9223372036854775808", None, CELEvalError, "-_"), ] + @pytest.fixture(params=unary_operator_params, ids=lambda f: f[6]) def unop_trees(request): """Creates three unary operator trees: @@ -1005,24 +1009,22 @@ def unop_trees(request): The function name is used to exercise the ``t_2`` tree with a bad function binding that raises an expected TypeError. """ - parent_tree_data, tree_data, lit_type, lit_value, ignored, expected, function = request.param + parent_tree_data, tree_data, lit_type, lit_value, ignored, expected, function = ( + request.param + ) # Broken tree. - t_0 = lark.Tree( - data=parent_tree_data, - children=[], - meta=Mock(line=1, column=1) - ) + t_0 = lark.Tree(data=parent_tree_data, children=[], meta=Mock(line=1, column=1)) # No operand tree. t_1 = binop_1_tree(parent_tree_data, "INT_LIT", "42") # A two-operand treee. right_hand_side = lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_=lit_type, value=lit_value), - ] + ], ) t_2 = lark.Tree( @@ -1032,14 +1034,15 @@ def unop_trees(request): data=tree_data, children=[ lark.Token(type_="operator", value="not used"), - ] + ], ), - right_hand_side + right_hand_side, ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) return t_0, t_1, t_2, expected, function + def test_unops(unop_trees): """ The unop_trees fixture provides three trees, an expected value, and a function name @@ -1048,23 +1051,14 @@ def test_unops(unop_trees): t_0, t_1, t_2, expected, function = unop_trees activation = Mock(resolve_function=Mock(return_value=base_functions[function])) - evaluator_0 = Evaluator( - t_0, - activation - ) + evaluator_0 = Evaluator(t_0, activation) with pytest.raises(celpy.evaluation.CELSyntaxError): evaluator_0.evaluate() - evaluator_1 = Evaluator( - t_1, - activation - ) + evaluator_1 = Evaluator(t_1, activation) assert evaluator_1.evaluate() == celtypes.IntType(42) - evaluator_2_g = Evaluator( - t_2, - activation - ) + evaluator_2_g = Evaluator(t_2, activation) if isinstance(expected, type): with pytest.raises(expected): evaluator_2_g.evaluate() @@ -1073,6 +1067,7 @@ def test_unops(unop_trees): def bad_function(a, b): raise TypeError + activation = Mock(resolve_function=Mock(return_value=bad_function)) evaluator_2_b = Evaluator( t_2, @@ -1088,20 +1083,9 @@ def test_member(monkeypatch): It simplifies the required :py:class:`lark.Tree` object. """ visit_children = Mock(return_value=[celtypes.IntType(42)]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) - tree = lark.Tree( - data="member", - children=[ - lark.Tree( - data="primary", - children=[] - ) - ] - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) + tree = lark.Tree(data="member", children=[lark.Tree(data="primary", children=[])]) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.member(tree) == celtypes.IntType(42) @@ -1112,9 +1096,11 @@ def test_member_dot_good_found(monkeypatch): PYTHONPATH=src python -m celpy -v -n '{"name": 42}.name' """ visit = Mock( - return_value=celtypes.MapType({celtypes.StringType("name"): celtypes.IntType(42)}) + return_value=celtypes.MapType( + {celtypes.StringType("name"): celtypes.IntType(42)} + ) ) - monkeypatch.setattr(Evaluator, 'visit', visit) + monkeypatch.setattr(Evaluator, "visit", visit) tree = lark.Tree( data="member", @@ -1122,30 +1108,27 @@ def test_member_dot_good_found(monkeypatch): lark.Tree( data="member_dot", children=[ - lark.Tree( - data="primary", - children=[] - ), - lark.Token("IDENT", "name") + lark.Tree(data="primary", children=[]), + lark.Token("IDENT", "name"), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) - ] - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + ], ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.member_dot(tree.children[0]) == celtypes.IntType(42) + def test_member_dot_message_found(monkeypatch): """ Made a fake parse tree for a protobuf message-like structure. """ visit = Mock( - return_value=celtypes.MessageType({celtypes.StringType("name"): celtypes.IntType(42)}) + return_value=celtypes.MessageType( + {celtypes.StringType("name"): celtypes.IntType(42)} + ) ) - monkeypatch.setattr(Evaluator, 'visit', visit) + monkeypatch.setattr(Evaluator, "visit", visit) tree = lark.Tree( data="member", @@ -1153,28 +1136,24 @@ def test_member_dot_message_found(monkeypatch): lark.Tree( data="member_dot", children=[ - lark.Tree( - data="primary", - children=[] - ), - lark.Token("IDENT", "name") + lark.Tree(data="primary", children=[]), + lark.Token("IDENT", "name"), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) - ] - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + ], ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.member_dot(tree.children[0]) == celtypes.IntType(42) def test_member_dot_good_notfound(monkeypatch): visit = Mock( - return_value=celtypes.MapType({celtypes.StringType("name"): celtypes.IntType(42)}) + return_value=celtypes.MapType( + {celtypes.StringType("name"): celtypes.IntType(42)} + ) ) - monkeypatch.setattr(Evaluator, 'visit', visit) + monkeypatch.setattr(Evaluator, "visit", visit) tree = lark.Tree( data="member", @@ -1186,30 +1165,24 @@ def test_member_dot_good_notfound(monkeypatch): data="primary", children=[ lark.Tree( - data="literal", - children=[ - lark.Token("IDENT", "member") - ] + data="literal", children=[lark.Token("IDENT", "member")] ) - ] + ], ), - lark.Token("IDENT", "not_the_name") + lark.Token("IDENT", "not_the_name"), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert isinstance(evaluator_0.member_dot(tree.children[0]), CELEvalError) def test_member_dot_no_overload(monkeypatch): visit = Mock(return_value=celtypes.StringType("whatever")) - monkeypatch.setattr(Evaluator, 'visit', visit) + monkeypatch.setattr(Evaluator, "visit", visit) tree = lark.Tree( data="member", @@ -1221,31 +1194,25 @@ def test_member_dot_no_overload(monkeypatch): data="primary", children=[ lark.Tree( - data="literal", - children=[ - lark.Token("IDENT", "member") - ] + data="literal", children=[lark.Token("IDENT", "member")] ) - ] + ], ), - lark.Token("IDENT", "name") + lark.Token("IDENT", "name"), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert isinstance(evaluator_0.member_dot(tree.children[0]), CELEvalError) def test_member_dot_error(monkeypatch): the_error = CELEvalError(sentinel.error, 1, 1) visit = Mock(return_value=the_error) - monkeypatch.setattr(Evaluator, 'visit', visit) + monkeypatch.setattr(Evaluator, "visit", visit) tree = lark.Tree( data="member", @@ -1253,20 +1220,14 @@ def test_member_dot_error(monkeypatch): lark.Tree( data="member_dot", children=[ - lark.Tree( - data="primary", - children=[] - ), - lark.Token("IDENT", "name") + lark.Tree(data="primary", children=[]), + lark.Token("IDENT", "name"), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) - ] - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + ], ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.member_dot(tree.children[0]) == the_error @@ -1277,10 +1238,8 @@ def test_member_dot_package(monkeypatch): PYTHONPATH=src python -m celpy -v -n 'name1.name2' """ - visit = Mock( - return_value=NameContainer("name2", Referent(celtypes.IntType)) - ) - monkeypatch.setattr(Evaluator, 'visit', visit) + visit = Mock(return_value=NameContainer("name2", Referent(celtypes.IntType))) + monkeypatch.setattr(Evaluator, "visit", visit) tree = lark.Tree( data="member", @@ -1292,23 +1251,17 @@ def test_member_dot_package(monkeypatch): data="primary", children=[ lark.Tree( - data="ident", - children=[ - lark.Token("IDENT", "name1") - ] + data="ident", children=[lark.Token("IDENT", "name1")] ) - ] + ], ), - lark.Token("IDENT", "name2") + lark.Token("IDENT", "name2"), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) - ] - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + ], ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.member_dot(tree.children[0]) == celtypes.IntType @@ -1322,7 +1275,7 @@ def test_member_dot_missing_package(monkeypatch): visit = Mock( return_value=NameContainer("not the expected name", Referent(celtypes.IntType)) ) - monkeypatch.setattr(Evaluator, 'visit', visit) + monkeypatch.setattr(Evaluator, "visit", visit) tree = lark.Tree( data="member", @@ -1334,24 +1287,23 @@ def test_member_dot_missing_package(monkeypatch): data="primary", children=[ lark.Tree( - data="ident", - children=[ - lark.Token("IDENT", "name1") - ] + data="ident", children=[lark.Token("IDENT", "name1")] ) - ] + ], ), - lark.Token("IDENT", "name2") + lark.Token("IDENT", "name2"), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) - ] + ], ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.member_dot(tree.children[0]) == CELEvalError( + "No 'name2' in bindings ['not the expected name']", + KeyError, + None, + tree=tree.children[0], ) - assert evaluator_0.member_dot(tree.children[0]) == CELEvalError("No 'name2' in bindings ['not the expected name']", KeyError, None, tree=tree.children[0]) def test_member_dot_arg_method_0(monkeypatch): @@ -1362,110 +1314,99 @@ def test_member_dot_arg_method_0(monkeypatch): lark.Token("IDENT", "getMonth"), ] ) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="member", children=[ lark.Tree( data="member_dot_arg", children=[ - lark.Tree( - data="primary", - children=[] - ), + lark.Tree(data="primary", children=[]), lark.Token("IDENT", "getMonth"), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) evaluator_0 = Evaluator( - tree, - activation=Mock(resolve_function=Mock(return_value=function_getMonth)) + tree, activation=Mock(resolve_function=Mock(return_value=function_getMonth)) ) assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.IntType(1) + def test_member_dot_arg_method_1(monkeypatch): """A method, e.g., ["hello", "world"].contains("hello"); distinct from the macros.""" visit_children = Mock( return_value=[ - celtypes.ListType([celtypes.StringType("hello"), celtypes.StringType("world"),]), + celtypes.ListType( + [ + celtypes.StringType("hello"), + celtypes.StringType("world"), + ] + ), lark.Token("IDENT", "contains"), [celtypes.StringType("hello")], ] ) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="member", children=[ lark.Tree( data="member_dot_arg", children=[ - lark.Tree( - data="primary", - children=[] - ), + lark.Tree(data="primary", children=[]), lark.Token("IDENT", "contains"), - lark.Tree( - data="literal", - children=[] - ), + lark.Tree(data="literal", children=[]), ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) ], - meta = Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) evaluator_0 = Evaluator( - tree, - activation=Mock(resolve_function=Mock(return_value=function_contains)) + tree, activation=Mock(resolve_function=Mock(return_value=function_contains)) ) assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.BoolType(True) def test_build_macro_eval(monkeypatch): - evaluator_0 = Evaluator( - None, - activation=Mock() - ) + evaluator_0 = Evaluator(None, activation=Mock()) mock_evaluator_class = Mock( return_value=Mock( # OLD DESIGN set_activation=Mock( - return_value=Mock( - evaluate=Mock(return_value=sentinel.output) - ) + return_value=Mock(evaluate=Mock(return_value=sentinel.output)) ), - evaluate=Mock(return_value=sentinel.output) + evaluate=Mock(return_value=sentinel.output), ) ) - monkeypatch.setattr(celpy.evaluation, 'Evaluator', mock_evaluator_class) + monkeypatch.setattr(celpy.evaluation, "Evaluator", mock_evaluator_class) sub_expression = lark.Tree(data="expr", children=[]) child = lark.Tree( data="member_dot_arg", children=[ - lark.Tree( - data="primary", - children=[] - ), + lark.Tree(data="primary", children=[]), lark.Token("IDENT", "map"), lark.Tree( data="exprlist", children=[ lark.Tree(data="ident", children=[lark.Token("IDENT", "variable")]), - sub_expression - ] + sub_expression, + ], ), - ] + ], ) subexpr = evaluator_0.build_macro_eval(child) # Nested `Evaluator` instance created assert mock_evaluator_class.mock_calls == [ - call(sub_expression, activation=evaluator_0.activation) # , functions=evaluator_0.functions) + call( + sub_expression, activation=evaluator_0.activation + ) # , functions=evaluator_0.functions) ] # When we evaluated the sub-expression created, it uses the nest `Evaluator` instance. @@ -1473,15 +1414,12 @@ def test_build_macro_eval(monkeypatch): # The nested evaluator's top-level activation had the input value set. assert mock_evaluator_class.return_value.evaluate.mock_calls == [ - call({'variable': sentinel.input}) + call({"variable": sentinel.input}) ] def test_build_ss_macro_eval(monkeypatch): - evaluator_0 = Evaluator( - None, - activation=Mock() - ) + evaluator_0 = Evaluator(None, activation=Mock()) mock_evaluator_class = Mock( return_value=Mock( @@ -1491,34 +1429,33 @@ def test_build_ss_macro_eval(monkeypatch): evaluate=Mock(side_effect=[sentinel.output, CELEvalError]) ) ), - evaluate=Mock(side_effect=[sentinel.output, CELEvalError]) + evaluate=Mock(side_effect=[sentinel.output, CELEvalError]), ) ) - monkeypatch.setattr(celpy.evaluation, 'Evaluator', mock_evaluator_class) + monkeypatch.setattr(celpy.evaluation, "Evaluator", mock_evaluator_class) sub_expression = lark.Tree(data="expr", children=[]) child = lark.Tree( data="member_dot_arg", children=[ - lark.Tree( - data="primary", - children=[] - ), + lark.Tree(data="primary", children=[]), lark.Token("IDENT", "map"), lark.Tree( data="exprlist", children=[ lark.Tree(data="ident", children=[lark.Token("IDENT", "variable")]), - sub_expression - ] + sub_expression, + ], ), - ] + ], ) subexpr = evaluator_0.build_ss_macro_eval(child) # Nested `Evaluator` instance created assert mock_evaluator_class.mock_calls == [ - call(sub_expression, activation=evaluator_0.activation) # , functions=evaluator_0.functions) + call( + sub_expression, activation=evaluator_0.activation + ) # , functions=evaluator_0.functions) ] # When we evaluated the sub-expression created, it uses the nest `Evaluator` instance. @@ -1531,38 +1468,31 @@ def test_build_ss_macro_eval(monkeypatch): # The nested evaluator's top-level activation had the input value set. assert mock_evaluator_class.return_value.evaluate.mock_calls == [ - call({'variable': sentinel.input}), - call({'variable': sentinel.input}), + call({"variable": sentinel.input}), + call({"variable": sentinel.input}), ] + def test_build_reduce_macro_eval(monkeypatch): - evaluator_0 = Evaluator( - None, - activation=Mock() - ) + evaluator_0 = Evaluator(None, activation=Mock()) mock_evaluator_class = Mock( return_value=Mock( # OLD DESIGN set_activation=Mock( - return_value=Mock( - evaluate=Mock(return_value=sentinel.output) - ) + return_value=Mock(evaluate=Mock(return_value=sentinel.output)) ), - evaluate=Mock(return_value=sentinel.output) + evaluate=Mock(return_value=sentinel.output), ) ) - monkeypatch.setattr(celpy.evaluation, 'Evaluator', mock_evaluator_class) + monkeypatch.setattr(celpy.evaluation, "Evaluator", mock_evaluator_class) sub_expression_1 = lark.Tree(data="expr", children=["1"]) sub_expression_2 = lark.Tree(data="expr", children=["2"]) child = lark.Tree( data="member_dot_arg", children=[ - lark.Tree( - data="primary", - children=[] - ), + lark.Tree(data="primary", children=[]), lark.Token("IDENT", "reduce"), lark.Tree( data="exprlist", @@ -1571,15 +1501,17 @@ def test_build_reduce_macro_eval(monkeypatch): lark.Tree(data="ident", children=[lark.Token("IDENT", "i")]), sub_expression_1, sub_expression_2, - ] + ], ), - ] + ], ) subexpr, init_value = evaluator_0.build_reduce_macro_eval(child) # Nested `Evaluator` instance created assert mock_evaluator_class.mock_calls == [ - call(sub_expression_2, activation=evaluator_0.activation) # , functions=evaluator_0.functions) + call( + sub_expression_2, activation=evaluator_0.activation + ) # , functions=evaluator_0.functions) ] # init_value is the sub_expression @@ -1590,7 +1522,7 @@ def test_build_reduce_macro_eval(monkeypatch): # The nested evaluator's top-level activation had the input value set. assert mock_evaluator_class.return_value.evaluate.mock_calls == [ - call({'r': sentinel.input1, 'i': sentinel.input2}) + call({"r": sentinel.input1, "i": sentinel.input2}) ] @@ -1606,8 +1538,10 @@ def macro_member_tree(macro_name, *args): # monkeypatch to visit mocks member values data="primary", children=[ - lark.Tree("ident", children=[lark.Token("IDENT", "placeholder")]) - ] + lark.Tree( + "ident", children=[lark.Token("IDENT", "placeholder")] + ) + ], ), lark.Token("IDENT", macro_name), lark.Tree( @@ -1616,139 +1550,109 @@ def macro_member_tree(macro_name, *args): # Most macros are variable and expression # reduce is two variables and two expressions. [ - lark.Tree("ident", children=[lark.Token("IDENT", "variable")]), - lark.Tree("expr", children=[lark.Token("INT", "0")]) + lark.Tree( + "ident", children=[lark.Token("IDENT", "variable")] + ), + lark.Tree("expr", children=[lark.Token("INT", "0")]), ] - if not args else args + if not args + else args ), - meta=Mock(line=1) + meta=Mock(line=1), ), ], - meta=Mock(line=1) + meta=Mock(line=1), ) ], - meta=Mock(line=1) + meta=Mock(line=1), ) return tree + def test_member_dot_arg_map(monkeypatch): """The map macro ["hello", "world"].map(x, x) == ["hello", "world"]""" visit = Mock( return_value=[celtypes.StringType("hello"), celtypes.StringType("world")] ) - monkeypatch.setattr(Evaluator, 'visit', visit) - build_macro_eval = Mock( - return_value=lambda x: x - ) - monkeypatch.setattr(Evaluator, 'build_macro_eval', build_macro_eval) + monkeypatch.setattr(Evaluator, "visit", visit) + build_macro_eval = Mock(return_value=lambda x: x) + monkeypatch.setattr(Evaluator, "build_macro_eval", build_macro_eval) tree = macro_member_tree("map") - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) - assert ( - evaluator_0.member_dot_arg(tree.children[0]) - == celtypes.ListType([celtypes.StringType("hello"), celtypes.StringType("world"),]) + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.ListType( + [ + celtypes.StringType("hello"), + celtypes.StringType("world"), + ] ) + def test_member_dot_arg_filter(monkeypatch): """The filter macro [true, false].filter(x, x) == [true]""" - visit = Mock( - return_value=[celtypes.BoolType(True), celtypes.BoolType(False)] - ) - monkeypatch.setattr(Evaluator, 'visit', visit) - build_macro_eval = Mock( - return_value=lambda x: x - ) - monkeypatch.setattr(Evaluator, 'build_macro_eval', build_macro_eval) + visit = Mock(return_value=[celtypes.BoolType(True), celtypes.BoolType(False)]) + monkeypatch.setattr(Evaluator, "visit", visit) + build_macro_eval = Mock(return_value=lambda x: x) + monkeypatch.setattr(Evaluator, "build_macro_eval", build_macro_eval) tree = macro_member_tree("filter") - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) - assert ( - evaluator_0.member_dot_arg(tree.children[0]) - == celtypes.ListType([celtypes.BoolType(True),]) + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.ListType( + [ + celtypes.BoolType(True), + ] ) def test_member_dot_arg_all(monkeypatch): """The filter macro [true, false].all(x, x) == [true]""" - visit = Mock( - return_value=[celtypes.BoolType(True), celtypes.BoolType(False)] - ) - monkeypatch.setattr(Evaluator, 'visit', visit) - build_ss_macro_eval = Mock( - return_value=lambda x: x - ) - monkeypatch.setattr(Evaluator, 'build_ss_macro_eval', build_ss_macro_eval) + visit = Mock(return_value=[celtypes.BoolType(True), celtypes.BoolType(False)]) + monkeypatch.setattr(Evaluator, "visit", visit) + build_ss_macro_eval = Mock(return_value=lambda x: x) + monkeypatch.setattr(Evaluator, "build_ss_macro_eval", build_ss_macro_eval) tree = macro_member_tree("all") - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) - assert ( - evaluator_0.member_dot_arg(tree.children[0]) == celtypes.BoolType(False) - ) + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.BoolType(False) def test_member_dot_arg_all_issue_41(monkeypatch): """The filter macro CelEvalError().all(x, x) == CelEvalError()""" tree = macro_member_tree("all") the_error = CELEvalError() - eval_0 = Evaluator(tree, activation=Mock(resolve_variable=Mock(return_value=the_error))) + eval_0 = Evaluator( + tree, activation=Mock(resolve_variable=Mock(return_value=the_error)) + ) assert eval_0.member_dot_arg(tree.children[0]) is the_error - def test_member_dot_arg_exists(monkeypatch): """The filter macro [true, false].exists(x, x) == [true]""" - visit = Mock( - return_value=[celtypes.BoolType(True), celtypes.BoolType(False)] - ) - monkeypatch.setattr(Evaluator, 'visit', visit) - build_ss_macro_eval = Mock( - return_value=lambda x: x - ) - monkeypatch.setattr(Evaluator, 'build_ss_macro_eval', build_ss_macro_eval) + visit = Mock(return_value=[celtypes.BoolType(True), celtypes.BoolType(False)]) + monkeypatch.setattr(Evaluator, "visit", visit) + build_ss_macro_eval = Mock(return_value=lambda x: x) + monkeypatch.setattr(Evaluator, "build_ss_macro_eval", build_ss_macro_eval) tree = macro_member_tree("exists") - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) - assert ( - evaluator_0.member_dot_arg(tree.children[0]) == celtypes.BoolType(True) - ) + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.BoolType(True) def test_member_dot_arg_exists_one(monkeypatch): """The filter macro [true, false].exists_one(x, x) == [true]""" - visit = Mock( - return_value=[celtypes.BoolType(True), celtypes.BoolType(False)] - ) - monkeypatch.setattr(Evaluator, 'visit', visit) - build_macro_eval = Mock( - return_value=lambda x: x - ) - monkeypatch.setattr(Evaluator, 'build_macro_eval', build_macro_eval) + visit = Mock(return_value=[celtypes.BoolType(True), celtypes.BoolType(False)]) + monkeypatch.setattr(Evaluator, "visit", visit) + build_macro_eval = Mock(return_value=lambda x: x) + monkeypatch.setattr(Evaluator, "build_macro_eval", build_macro_eval) tree = macro_member_tree("exists_one") - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) - assert ( - evaluator_0.member_dot_arg(tree.children[0]) == celtypes.BoolType(True) - ) + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.BoolType(True) def test_member_dot_arg_reduce(monkeypatch): @@ -1756,30 +1660,23 @@ def test_member_dot_arg_reduce(monkeypatch): visit = Mock( side_effect=[ [celtypes.IntType(0), celtypes.IntType(1), celtypes.IntType(2)], - celtypes.IntType(0) + celtypes.IntType(0), ] ) - monkeypatch.setattr(Evaluator, 'visit', visit) - build_reduce_macro_eval = Mock( - return_value=(lambda x, y: x + 2*y+1, 0) - ) - monkeypatch.setattr(Evaluator, 'build_reduce_macro_eval', build_reduce_macro_eval) + monkeypatch.setattr(Evaluator, "visit", visit) + build_reduce_macro_eval = Mock(return_value=(lambda x, y: x + 2 * y + 1, 0)) + monkeypatch.setattr(Evaluator, "build_reduce_macro_eval", build_reduce_macro_eval) tree = macro_member_tree( "reduce", lark.Tree("ident", children=[lark.Token("IDENT", "r")]), lark.Tree("ident", children=[lark.Token("IDENT", "i")]), - lark.Tree(data="expr", children=[]), # Initialization - lark.Tree(data="expr", children=[]), # Reduction function + lark.Tree(data="expr", children=[]), # Initialization + lark.Tree(data="expr", children=[]), # Reduction function ) - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) - assert ( - evaluator_0.member_dot_arg(tree.children[0]) == celtypes.IntType(9) - ) + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.IntType(9) def test_member_dot_arg_min(monkeypatch): @@ -1787,59 +1684,90 @@ def test_member_dot_arg_min(monkeypatch): visit = Mock( return_value=[celtypes.IntType(3), celtypes.IntType(1), celtypes.IntType(2)] ) - monkeypatch.setattr(Evaluator, 'visit', visit) + monkeypatch.setattr(Evaluator, "visit", visit) tree = macro_member_tree("min") - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) - assert ( - evaluator_0.member_dot_arg(tree.children[0]) == celtypes.IntType(1) - ) + evaluator_0 = Evaluator(tree, activation=Mock()) + assert evaluator_0.member_dot_arg(tree.children[0]) == celtypes.IntType(1) def test_member_dot_arg_min_error(monkeypatch): """The macro [].min() is an error""" - visit = Mock( - return_value=[] - ) - monkeypatch.setattr(Evaluator, 'visit', visit) + visit = Mock(return_value=[]) + monkeypatch.setattr(Evaluator, "visit", visit) tree = macro_member_tree("min") - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) + evaluator_0 = Evaluator(tree, activation=Mock()) result = evaluator_0.member_dot_arg(tree.children[0]) assert isinstance(result, CELEvalError) index_operator_params = [ - (celtypes.ListType([celtypes.StringType("hello"), celtypes.StringType("world"),]), - celtypes.IntType(0), celtypes.StringType("hello"), "_[_]"), - (celtypes.ListType([celtypes.StringType("hello"), celtypes.StringType("world"),]), - celtypes.IntType(42), CELEvalError, "_[_]"), - (celtypes.ListType([celtypes.StringType("hello"), celtypes.StringType("world"),]), - celtypes.DoubleType(3.14), CELEvalError, "_[_]"), - (celtypes.MapType({celtypes.StringType("name"): celtypes.StringType("hello"),}), - celtypes.StringType("name"), celtypes.StringType("hello"), "_[_]"), - (celtypes.MapType({celtypes.StringType("name"): celtypes.StringType("hello"), }), - celtypes.StringType("nope"), CELEvalError, "_[_]"), + ( + celtypes.ListType( + [ + celtypes.StringType("hello"), + celtypes.StringType("world"), + ] + ), + celtypes.IntType(0), + celtypes.StringType("hello"), + "_[_]", + ), + ( + celtypes.ListType( + [ + celtypes.StringType("hello"), + celtypes.StringType("world"), + ] + ), + celtypes.IntType(42), + CELEvalError, + "_[_]", + ), + ( + celtypes.ListType( + [ + celtypes.StringType("hello"), + celtypes.StringType("world"), + ] + ), + celtypes.DoubleType(3.14), + CELEvalError, + "_[_]", + ), + ( + celtypes.MapType( + { + celtypes.StringType("name"): celtypes.StringType("hello"), + } + ), + celtypes.StringType("name"), + celtypes.StringType("hello"), + "_[_]", + ), + ( + celtypes.MapType( + { + celtypes.StringType("name"): celtypes.StringType("hello"), + } + ), + celtypes.StringType("nope"), + CELEvalError, + "_[_]", + ), ] -@pytest.fixture(params=index_operator_params, ids=lambda f: "{0}[{1!r}] == {2}".format(*f)) + +@pytest.fixture( + params=index_operator_params, ids=lambda f: "{0}[{1!r}] == {2}".format(*f) +) def index_trees(request, monkeypatch): container, index, expected, function = request.param - visit_children = Mock( - return_value=[ - container, - index - ] - ) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + visit_children = Mock(return_value=[container, index]) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="member", @@ -1854,21 +1782,19 @@ def index_trees(request, monkeypatch): data="literal", children=[ lark.Token(type_="STRING_LIT", value=str(container)) - ] + ], ) - ] + ], ), lark.Tree( data="literal", - children=[ - lark.Token(type_="STRING_LIT", value=str(index)) - ] + children=[lark.Token(type_="STRING_LIT", value=str(index))], ), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) return tree, function, expected @@ -1879,13 +1805,13 @@ def test_member_index(index_trees): tree, function, expected = index_trees evaluator_0 = Evaluator( - tree, - activation=Mock(resolve_function=Mock(return_value=operator.getitem)) + tree, activation=Mock(resolve_function=Mock(return_value=operator.getitem)) ) if isinstance(expected, type): # Does the member_index() method produce a CELEvalError instance? - assert isinstance(evaluator_0.member_index(tree.children[0]), expected), \ + assert isinstance(evaluator_0.member_index(tree.children[0]), expected), ( "{0!r} is not {1}".format(evaluator_0.member(tree), expected) + ) else: # Does the member_index() method produce the expected concrete object? assert evaluator_0.member_index(tree.children[0]) == expected @@ -1900,18 +1826,11 @@ def test_member_object_0(): tree = lark.Tree( data="member", children=[ - lark.Tree( - data="member_object", - children=[], - meta=Mock(line=1, column=1) - ) + lark.Tree(data="member_object", children=[], meta=Mock(line=1, column=1)) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) with pytest.raises(CELSyntaxError): evaluator_0.member_object(tree.children[0]) @@ -1934,30 +1853,28 @@ def test_member_object_1(): data="member_object", children=[ lark.Tree( - data='primary', + data="primary", children=[ lark.Tree( - data='literal', + data="literal", children=[ lark.Token(type_="INT_LIT", value="42"), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ), ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.member_object(tree.children[0]) == celtypes.IntType(42) + def test_member_object_2(monkeypatch): """ :: @@ -1970,7 +1887,7 @@ def test_member_object_2(monkeypatch): visit_children = Mock( return_value=[protobuf_annotation, {"field": sentinel.fieldinit}] ) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="member", @@ -1978,29 +1895,22 @@ def test_member_object_2(monkeypatch): lark.Tree( data="member_object", children=[ + lark.Tree(data="member", children=[]), lark.Tree( - data='member', - children=[] - ), - lark.Tree( - data='fieldinits', + data="fieldinits", children=[], ), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ), ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) pb = evaluator_0.member_object(tree.children[0]) assert pb == sentinel.protobuf_object - assert protobuf_annotation.mock_calls == [ - call({"field": sentinel.fieldinit}) - ] + assert protobuf_annotation.mock_calls == [call({"field": sentinel.fieldinit})] + def test_member_object_3(monkeypatch): """ @@ -2011,10 +1921,8 @@ def test_member_object_3(monkeypatch): Create protobuf message without field inits. """ protobuf_annotation = Mock(return_value=sentinel.protobuf_object) - visit_children = Mock( - return_value=[protobuf_annotation] - ) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + visit_children = Mock(return_value=[protobuf_annotation]) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="member", @@ -2022,20 +1930,14 @@ def test_member_object_3(monkeypatch): lark.Tree( data="member_object", children=[ - lark.Tree( - data='member', - children=[] - ), + lark.Tree(data="member", children=[]), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ), ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) pb = evaluator_0.member_object(tree.children[0]) assert pb == sentinel.protobuf_object assert protobuf_annotation.mock_calls == [call(None)] @@ -2048,10 +1950,8 @@ def test_member_object_error(monkeypatch): member_object : member "{" [fieldinits] "}" """ the_error = CELEvalError() - visit_children = Mock( - return_value=[the_error, {"field": sentinel.fieldinit}] - ) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + visit_children = Mock(return_value=[the_error, {"field": sentinel.fieldinit}]) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="member", @@ -2059,24 +1959,18 @@ def test_member_object_error(monkeypatch): lark.Tree( data="member_object", children=[ + lark.Tree(data="member", children=[]), lark.Tree( - data='member', - children=[] - ), - lark.Tree( - data='fieldinits', + data="fieldinits", children=[], ), ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ), ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.member_object(tree.children[0]) == the_error @@ -2088,19 +1982,12 @@ def test_primary_0(): | paren_expr | list_lit | map_lit | literal """ - tree = lark.Tree( - data="primary", - children=[ - ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) + tree = lark.Tree(data="primary", children=[], meta=Mock(line=1, column=1)) + evaluator_0 = Evaluator(tree, activation=Mock()) with pytest.raises(CELSyntaxError): evaluator_0.primary(tree) + def test_primary_broken(): """ :: @@ -2111,25 +1998,17 @@ def test_primary_broken(): """ tree = lark.Tree( data="primary", - children=[ - lark.Tree( - data="unexpected", - children=[] - ) - ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + children=[lark.Tree(data="unexpected", children=[])], + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) with pytest.raises(CELSyntaxError): evaluator_0.primary(tree) def test_primary_dot_ident_arg(monkeypatch): ident_value = Mock(return_value=sentinel.value) - monkeypatch.setattr(Evaluator, 'ident_value', ident_value) + monkeypatch.setattr(Evaluator, "ident_value", ident_value) tree = lark.Tree( data="primary", @@ -2138,26 +2017,20 @@ def test_primary_dot_ident_arg(monkeypatch): data="dot_ident_arg", children=[ lark.Token("IDENT", "name"), - lark.Tree( - data="exprlist", - children=[] - ) - ] + lark.Tree(data="exprlist", children=[]), + ], ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.value assert ident_value.mock_calls == [call("name", root_scope=True)] def test_primary_dot_ident(monkeypatch): ident_value = Mock(return_value=sentinel.value) - monkeypatch.setattr(Evaluator, 'ident_value', ident_value) + monkeypatch.setattr(Evaluator, "ident_value", ident_value) tree = lark.Tree( data="primary", @@ -2166,22 +2039,19 @@ def test_primary_dot_ident(monkeypatch): data="dot_ident", children=[ lark.Token("IDENT", "name"), - ] + ], ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.value assert ident_value.mock_calls == [call("name", root_scope=True)] def test_primary_dot_ident_not_found(monkeypatch): ident_value = Mock(side_effect=KeyError("name")) - monkeypatch.setattr(Evaluator, 'ident_value', ident_value) + monkeypatch.setattr(Evaluator, "ident_value", ident_value) tree = lark.Tree( data="primary", @@ -2190,104 +2060,67 @@ def test_primary_dot_ident_not_found(monkeypatch): data="dot_ident", children=[ lark.Token("IDENT", "name"), - ] + ], ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert isinstance(evaluator_0.primary(tree), CELEvalError) assert ident_value.mock_calls == [call("name", root_scope=True)] def test_primary_ident_arg_has(monkeypatch): macro_has_eval = Mock(return_value=sentinel.value) - monkeypatch.setattr(Evaluator, 'macro_has_eval', macro_has_eval) + monkeypatch.setattr(Evaluator, "macro_has_eval", macro_has_eval) - sub_expr = lark.Tree( - data="exprlist", - children=[] - ) + sub_expr = lark.Tree(data="exprlist", children=[]) tree = lark.Tree( data="primary", children=[ - lark.Tree( - data="ident_arg", - children=[ - lark.Token("IDENT", "has"), - sub_expr - ] - ) + lark.Tree(data="ident_arg", children=[lark.Token("IDENT", "has"), sub_expr]) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.value assert macro_has_eval.mock_calls == [call(sub_expr)] def test_primary_ident_arg_dyn(monkeypatch): visit_children = Mock(return_value=[sentinel.value]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) - sub_expr = lark.Tree( - data="exprlist", - children=[] - ) + sub_expr = lark.Tree(data="exprlist", children=[]) tree = lark.Tree( data="primary", children=[ - lark.Tree( - data="ident_arg", - children=[ - lark.Token("IDENT", "dyn"), - sub_expr - ] - ) + lark.Tree(data="ident_arg", children=[lark.Token("IDENT", "dyn"), sub_expr]) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.value assert visit_children.mock_calls == [call(sub_expr)] def test_primary_ident_arg_method(monkeypatch): visit_children = Mock(return_value=[sentinel.input]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) function_eval = Mock(return_value=sentinel.output) - monkeypatch.setattr(Evaluator, 'function_eval', function_eval) + monkeypatch.setattr(Evaluator, "function_eval", function_eval) - sub_expr = lark.Tree( - data="exprlist", - children=[] - ) + sub_expr = lark.Tree(data="exprlist", children=[]) tree = lark.Tree( data="primary", children=[ lark.Tree( - data="ident_arg", - children=[ - lark.Token("IDENT", "name"), - sub_expr - ] + data="ident_arg", children=[lark.Token("IDENT", "name"), sub_expr] ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.output assert visit_children.mock_calls == [call(sub_expr)] assert function_eval.mock_calls == [call("name", [sentinel.input])] @@ -2298,7 +2131,7 @@ def test_primary_ident_arg_empty(monkeypatch): https://github.com/cloud-custodian/cel-python/issues/10 """ visit_children = Mock(return_value=[sentinel.value]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="primary", @@ -2307,10 +2140,10 @@ def test_primary_ident_arg_empty(monkeypatch): data="ident_arg", children=[ lark.Token("IDENT", "shake_hands"), - ] + ], ) ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) shake_hands_function = Mock(return_value=sentinel.value) evaluator_0 = Evaluator( @@ -2324,7 +2157,7 @@ def test_primary_ident_arg_empty(monkeypatch): def test_primary_ident_good(monkeypatch): ident_value = Mock(return_value=sentinel.value) - monkeypatch.setattr(Evaluator, 'ident_value', ident_value) + monkeypatch.setattr(Evaluator, "ident_value", ident_value) tree = lark.Tree( data="primary", @@ -2333,22 +2166,19 @@ def test_primary_ident_good(monkeypatch): data="ident", children=[ lark.Token("IDENT", "name"), - ] + ], ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.value assert ident_value.mock_calls == [call("name")] def test_primary_ident_bad(monkeypatch): ident_value = Mock(side_effect=KeyError) - monkeypatch.setattr(Evaluator, 'ident_value', ident_value) + monkeypatch.setattr(Evaluator, "ident_value", ident_value) tree = lark.Tree( data="primary", @@ -2357,41 +2187,25 @@ def test_primary_ident_bad(monkeypatch): data="ident", children=[ lark.Token("IDENT", "name"), - ] + ], ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert isinstance(evaluator_0.primary(tree), CELEvalError) assert ident_value.mock_calls == [call("name")] def test_primary_paren_expr(monkeypatch): visit_children = Mock(return_value=[sentinel.value]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) paren_expr = lark.Tree( - data="paren_expr", - children=[ - lark.Tree( - data="expr", - children=[] - ) - ] - ) - tree = lark.Tree( - data="primary", - children=[paren_expr], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + data="paren_expr", children=[lark.Tree(data="expr", children=[])] ) + tree = lark.Tree(data="primary", children=[paren_expr], meta=Mock(line=1, column=1)) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.value assert visit_children.mock_calls == [call(tree.children[0])] @@ -2399,44 +2213,24 @@ def test_primary_paren_expr(monkeypatch): def test_primary_list_lit_empty(): tree = lark.Tree( data="primary", - children=[ - lark.Tree( - data="list_lit", - children=[] - ) - ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + children=[lark.Tree(data="list_lit", children=[])], + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == celpy.celtypes.ListType() + def test_primary_list_lit_nonempty(monkeypatch): visit_children = Mock(return_value=[sentinel.list_instance]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) - exprlist = lark.Tree( - data="exprlist", - children=[] - ) + exprlist = lark.Tree(data="exprlist", children=[]) tree = lark.Tree( data="primary", - children=[ - lark.Tree( - data="list_lit", - children=[ - exprlist - ] - ) - ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + children=[lark.Tree(data="list_lit", children=[exprlist])], + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.list_instance assert visit_children.mock_calls == [call(tree.children[0])] @@ -2444,18 +2238,10 @@ def test_primary_list_lit_nonempty(monkeypatch): def test_primary_map_lit_empty(): tree = lark.Tree( data="primary", - children=[ - lark.Tree( - data="map_lit", - children=[] - ) - ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + children=[lark.Tree(data="map_lit", children=[])], + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == celpy.celtypes.MapType() @@ -2465,75 +2251,55 @@ def map_init_tree(): data="primary", children=[ lark.Tree( - data="map_lit", - children=[ - lark.Tree( - data="mapinits", - children=[] - ) - ] + data="map_lit", children=[lark.Tree(data="mapinits", children=[])] ) ], - meta=Mock(line=1, column=1) + meta=Mock(line=1, column=1), ) return tree + def test_primary_map_lit_nonempty_good(map_init_tree, monkeypatch): visit_children = Mock(return_value=[sentinel.map_instance]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) - evaluator_0 = Evaluator( - map_init_tree, - activation=Mock() - ) + evaluator_0 = Evaluator(map_init_tree, activation=Mock()) assert evaluator_0.primary(map_init_tree) == sentinel.map_instance assert visit_children.mock_calls == [call(map_init_tree.children[0])] def test_primary_map_lit_nonempty_value_error(map_init_tree, monkeypatch): visit_children = Mock(side_effect=ValueError(sentinel.message)) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) - evaluator_0 = Evaluator( - map_init_tree, - activation=Mock() - ) + evaluator_0 = Evaluator(map_init_tree, activation=Mock()) assert isinstance(evaluator_0.primary(map_init_tree), CELEvalError) assert visit_children.mock_calls == [call(map_init_tree.children[0])] def test_primary_map_lit_nonempty_type_error(map_init_tree, monkeypatch): visit_children = Mock(side_effect=TypeError(sentinel.message)) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) - evaluator_0 = Evaluator( - map_init_tree, - activation=Mock() - ) + evaluator_0 = Evaluator(map_init_tree, activation=Mock()) assert isinstance(evaluator_0.primary(map_init_tree), CELEvalError) assert visit_children.mock_calls == [call(map_init_tree.children[0])] def test_primary_literal(monkeypatch): visit_children = Mock(return_value=[sentinel.literal_value]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="primary", children=[ lark.Tree( - data="literal", - children=[ - lark.Token(type_="INT_LIT", value="42") - ] + data="literal", children=[lark.Token(type_="INT_LIT", value="42")] ) ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.primary(tree) == sentinel.literal_value assert visit_children.mock_calls == [call(tree)] @@ -2546,15 +2312,8 @@ def test_literal_broken(): | BOOL_LIT | NULL_LIT """ - tree = lark.Tree( - data="literal", - children=[], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) + tree = lark.Tree(data="literal", children=[], meta=Mock(line=1, column=1)) + evaluator_0 = Evaluator(tree, activation=Mock()) with pytest.raises(CELSyntaxError): evaluator_0.literal(tree) @@ -2564,49 +2323,56 @@ def test_literal_broken(): ("INT_LIT", "42", celtypes.IntType(42)), ("UINT_LIT", "42u", celtypes.UintType(42)), ("STRING_LIT", r"'s\x74\162\u0069\U0000006eg\n'", celtypes.StringType("string\n")), - ("STRING_LIT", r"'''s\x74\162\u0069\U0000006eg\n'''", celtypes.StringType("string\n")), + ( + "STRING_LIT", + r"'''s\x74\162\u0069\U0000006eg\n'''", + celtypes.StringType("string\n"), + ), ("STRING_LIT", r"r'r\aw'", celtypes.StringType(r"r\aw")), ("STRING_LIT", r"r'''r\aw'''", celtypes.StringType(r"r\aw")), ("BYTES_LIT", r"b'b\171\x74\u0065\x73\n'", celtypes.BytesType(b"bytes\n")), ("BYTES_LIT", r"b'''b\171\x74\u0065\x73\n'''", celtypes.BytesType(b"bytes\n")), - ("BYTES_LIT", r"br'r\aw'", celtypes.BytesType(br"r\aw")), - ("BYTES_LIT", r"br'''r\aw'''", celtypes.BytesType(br"r\aw")), - ("BYTES_LIT", "'no prefix'", - CELEvalError( - 'Invalid bytes literal "\'no prefix\'"', - ValueError, - ('Invalid bytes literal "\'no prefix\'"',)) + ("BYTES_LIT", r"br'r\aw'", celtypes.BytesType(rb"r\aw")), + ("BYTES_LIT", r"br'''r\aw'''", celtypes.BytesType(rb"r\aw")), + ( + "BYTES_LIT", + "'no prefix'", + CELEvalError( + "Invalid bytes literal \"'no prefix'\"", + ValueError, + ("Invalid bytes literal \"'no prefix'\"",), + ), ), ("BOOL_LIT", "true", celtypes.BoolType(True)), ("NULL_LIT", "null", None), ("UINT_LIT", "42", CELSyntaxError), ("BROKEN", "BROKEN", CELUnsupportedError), - ("INT_LIT", "xyzzy", + ( + "INT_LIT", + "xyzzy", CELEvalError( "invalid literal for int() with base 10: 'xyzzy'", ValueError, - ("invalid literal for int() with base 10: 'xyzzy'",)) - ), + ("invalid literal for int() with base 10: 'xyzzy'",), + ), + ), ] + @pytest.fixture(params=literal_params, ids=lambda f: f[0]) def literals(request): token_type, token_value, expected = request.param tree = lark.Tree( data="literal", - children=[ - lark.Token(type_=token_type, value=token_value) - ], - meta=Mock(line=1, column=1) + children=[lark.Token(type_=token_type, value=token_value)], + meta=Mock(line=1, column=1), ) yield tree, expected + def test_literals(literals): tree, expected = literals - evaluator_0 = Evaluator( - tree, - activation=Mock() - ) + evaluator_0 = Evaluator(tree, activation=Mock()) if isinstance(expected, type): with pytest.raises(expected): x = evaluator_0.literal(tree) @@ -2614,6 +2380,7 @@ def test_literals(literals): else: assert evaluator_0.literal(tree) == expected + def test_fieldinits(monkeypatch): """ :: @@ -2621,20 +2388,20 @@ def test_fieldinits(monkeypatch): fieldinits : IDENT ":" expr ("," IDENT ":" expr)* """ visit_children = Mock(return_value=[sentinel.literal_value]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="fieldinits", children=[ lark.Token(type_="IDENT", value="Name"), - lark.Tree(data="literal", children=[lark.Token(type_="STRING_LIT", value="'value'")]), + lark.Tree( + data="literal", + children=[lark.Token(type_="STRING_LIT", value="'value'")], + ), ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.fieldinits(tree) == celpy.celtypes.MapType( {"Name": sentinel.literal_value} ) @@ -2647,22 +2414,25 @@ def test_fieldinits_duplicate(monkeypatch): fieldinits : IDENT ":" expr ("," IDENT ":" expr)* """ visit_children = Mock(return_value=[sentinel.literal_value]) - monkeypatch.setattr(Evaluator, 'visit_children', visit_children) + monkeypatch.setattr(Evaluator, "visit_children", visit_children) tree = lark.Tree( data="fieldinits", children=[ lark.Token(type_="IDENT", value="Name"), - lark.Tree(data="literal", children=[lark.Token(type_="STRING_LIT", value="'value'")]), + lark.Tree( + data="literal", + children=[lark.Token(type_="STRING_LIT", value="'value'")], + ), lark.Token(type_="IDENT", value="Name"), - lark.Tree(data="literal", children=[lark.Token(type_="STRING_LIT", value="'more'")]), + lark.Tree( + data="literal", + children=[lark.Token(type_="STRING_LIT", value="'more'")], + ), ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) with pytest.raises(ValueError): evaluator_0.fieldinits(tree) @@ -2673,61 +2443,44 @@ def test_mapinits_good(): children=[ lark.Tree( data="literal", - children=[ - lark.Token(type_="STRING_LIT", value="'name'") - ] + children=[lark.Token(type_="STRING_LIT", value="'name'")], ), lark.Tree( data="literal", - children=[ - lark.Token(type_="STRING_LIT", value="'value'") - ] + children=[lark.Token(type_="STRING_LIT", value="'value'")], ), ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) assert evaluator_0.mapinits(tree) == celpy.celtypes.MapType( {celtypes.StringType("name"): celtypes.StringType("value")} ) + def test_mapinits_bad(): tree = lark.Tree( data="mapinits", children=[ lark.Tree( data="literal", - children=[ - lark.Token(type_="STRING_LIT", value="'name'") - ] + children=[lark.Token(type_="STRING_LIT", value="'name'")], ), lark.Tree( data="literal", - children=[ - lark.Token(type_="STRING_LIT", value="'value'") - ] + children=[lark.Token(type_="STRING_LIT", value="'value'")], ), lark.Tree( data="literal", - children=[ - lark.Token(type_="STRING_LIT", value="'name'") - ] + children=[lark.Token(type_="STRING_LIT", value="'name'")], ), lark.Tree( data="literal", - children=[ - lark.Token(type_="STRING_LIT", value="'value'") - ] + children=[lark.Token(type_="STRING_LIT", value="'value'")], ), ], - meta=Mock(line=1, column=1) - ) - evaluator_0 = Evaluator( - tree, - activation=Mock() + meta=Mock(line=1, column=1), ) + evaluator_0 = Evaluator(tree, activation=Mock()) with pytest.raises(ValueError): evaluator_0.mapinits(tree) diff --git a/tests/test_main.py b/tests/test_main.py index 4cb28d9..cf4918a 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -132,9 +132,7 @@ def test_arg_combo_bad(capsys, monkeypatch): " [expr]", ] with pytest.raises(SystemExit) as exc_info: - options = celpy.__main__.get_options( - ["-i", "-n", "355./113."] - ) + options = celpy.__main__.get_options(["-i", "-n", "355./113."]) assert exc_info.value.args == (2,) out, err = capsys.readouterr() assert err.splitlines() == error_prefix + [ @@ -142,9 +140,7 @@ def test_arg_combo_bad(capsys, monkeypatch): ] with pytest.raises(SystemExit) as exc_info: - options = celpy.__main__.get_options( - ["-n"] - ) + options = celpy.__main__.get_options(["-n"]) assert exc_info.value.args == (2,) out, err = capsys.readouterr() assert err.splitlines() == error_prefix + [ @@ -203,7 +199,13 @@ def test_main_1(mock_cel_environment, caplog, capsys): status = celpy.__main__.main(argv) assert status == 0 assert mock_cel_environment.mock_calls == [ - call(package=None, annotations={"name": celtypes.StringType, "stat": celpy.celtypes.FunctionType}) + call( + package=None, + annotations={ + "name": celtypes.StringType, + "stat": celpy.celtypes.FunctionType, + }, + ) ] env = mock_cel_environment.return_value assert env.compile.mock_calls == [call('"Hello world! I\'m " + name + "."')] @@ -228,7 +230,7 @@ def test_main_pipe(mock_cel_environment, caplog, capsys): ] env = mock_cel_environment.return_value assert env.compile.mock_calls == [call('"Hello world! I\'m " + name + "."')] - assert env.program.mock_calls == [call(sentinel.AST, functions={'stat': ANY})] + assert env.program.mock_calls == [call(sentinel.AST, functions={"stat": ANY})] prgm = env.program.return_value assert prgm.evaluate.mock_calls == [ call( @@ -244,6 +246,7 @@ def test_main_pipe(mock_cel_environment, caplog, capsys): assert out == '"sentinel.OUTPUT"\n' assert err == "" + def test_main_0_non_boolean(mock_cel_environment, caplog, capsys): """ GIVEN null-input AND boolean option and AND non-bool expr @@ -258,7 +261,7 @@ def test_main_0_non_boolean(mock_cel_environment, caplog, capsys): ] env = mock_cel_environment.return_value assert env.compile.mock_calls == [call('"Hello world! I\'m " + name + "."')] - assert env.program.mock_calls == [call(sentinel.AST, functions={'stat': ANY})] + assert env.program.mock_calls == [call(sentinel.AST, functions={"stat": ANY})] prgm = env.program.return_value assert prgm.evaluate.mock_calls == [call({})] assert caplog.messages == [ @@ -294,7 +297,7 @@ def test_main_0_boolean(mock_cel_environment_false, caplog, capsys): ] env = mock_cel_environment_false.return_value assert env.compile.mock_calls == [call("2 == 1")] - assert env.program.mock_calls == [call(sentinel.AST, functions={'stat': ANY})] + assert env.program.mock_calls == [call(sentinel.AST, functions={"stat": ANY})] prgm = env.program.return_value assert prgm.evaluate.mock_calls == [call({})] assert caplog.messages == [] @@ -326,20 +329,27 @@ def test_main_slurp_int_format(mock_cel_environment_integer, caplog, capsys): sys.stdin = sys.__stdin__ assert status == 0 assert mock_cel_environment_integer.mock_calls == [ - call(package='jq', annotations={"stat": celpy.celtypes.FunctionType}) + call(package="jq", annotations={"stat": celpy.celtypes.FunctionType}) ] env = mock_cel_environment_integer.return_value assert env.compile.mock_calls == [call("339629869*11")] - assert env.program.mock_calls == [call(sentinel.AST, functions={'stat': ANY})] + assert env.program.mock_calls == [call(sentinel.AST, functions={"stat": ANY})] prgm = env.program.return_value assert prgm.evaluate.mock_calls == [ - call({'jq': celtypes.MapType({celtypes.StringType('name'): celtypes.StringType('CEL')})}) + call( + { + "jq": celtypes.MapType( + {celtypes.StringType("name"): celtypes.StringType("CEL")} + ) + } + ) ] assert caplog.messages == [] out, err = capsys.readouterr() assert out == "0xdeadbeef\n" assert err == "" + @pytest.fixture def mock_cel_environment_bool(monkeypatch): mock_runner = Mock(evaluate=Mock(return_value=celtypes.BoolType(False))) @@ -363,14 +373,20 @@ def test_main_slurp_bool_status(mock_cel_environment_bool, caplog, capsys): sys.stdin = sys.__stdin__ assert status == 1 assert mock_cel_environment_bool.mock_calls == [ - call(package='jq', annotations={"stat": celpy.celtypes.FunctionType}) + call(package="jq", annotations={"stat": celpy.celtypes.FunctionType}) ] env = mock_cel_environment_bool.return_value assert env.compile.mock_calls == [call('.name == "not CEL"')] - assert env.program.mock_calls == [call(sentinel.AST, functions={'stat': ANY})] + assert env.program.mock_calls == [call(sentinel.AST, functions={"stat": ANY})] prgm = env.program.return_value assert prgm.evaluate.mock_calls == [ - call({'jq': celtypes.MapType({celtypes.StringType('name'): celtypes.StringType('CEL')})}) + call( + { + "jq": celtypes.MapType( + {celtypes.StringType("name"): celtypes.StringType("CEL")} + ) + } + ) ] assert caplog.messages == [] out, err = capsys.readouterr() @@ -388,13 +404,11 @@ def test_main_0_int_format(mock_cel_environment_integer, caplog, capsys): status = celpy.__main__.main(argv) assert status == 0 assert mock_cel_environment_integer.mock_calls == [ - call(package=None, annotations={'stat': celpy.celtypes.FunctionType}) + call(package=None, annotations={"stat": celpy.celtypes.FunctionType}) ] env = mock_cel_environment_integer.return_value assert env.compile.mock_calls == [call("339629869*11")] - assert env.program.mock_calls == [ - call(sentinel.AST, functions={"stat": ANY}) - ] + assert env.program.mock_calls == [call(sentinel.AST, functions={"stat": ANY})] prgm = env.program.return_value assert prgm.evaluate.mock_calls == [call({})] assert caplog.messages == [] @@ -402,13 +416,14 @@ def test_main_0_int_format(mock_cel_environment_integer, caplog, capsys): assert out == "0xdeadbeef\n" assert err == "" + def test_main_verbose(mock_cel_environment, caplog, capsys): """GIVEN verbose AND expression; WHEN eval; THEN correct log output.""" argv = ["-v", "[2, 4, 5].map(x, x/2)"] status = celpy.__main__.main(argv) assert status == 0 assert mock_cel_environment.mock_calls == [ - call(package="jq", annotations={'stat': celpy.celtypes.FunctionType}) + call(package="jq", annotations={"stat": celpy.celtypes.FunctionType}) ] assert caplog.messages == ["Expr: '[2, 4, 5].map(x, x/2)'"] out, err = capsys.readouterr() @@ -422,13 +437,19 @@ def test_main_very_verbose(mock_cel_environment, caplog, capsys): status = celpy.__main__.main(argv) assert status == 0 assert mock_cel_environment.mock_calls == [ - call(package="jq", annotations={'stat': celpy.celtypes.FunctionType}) + call(package="jq", annotations={"stat": celpy.celtypes.FunctionType}) ] expected_namespace = argparse.Namespace( - verbose=2, arg=None, null_input=False, slurp=False, interactive=False, - package='jq', document=None, - boolean=False, format=None, - expr='[2, 4, 5].map(x, x/2)' + verbose=2, + arg=None, + null_input=False, + slurp=False, + interactive=False, + package="jq", + document=None, + boolean=False, + format=None, + expr="[2, 4, 5].map(x, x/2)", ) assert caplog.messages == [ str(expected_namespace), @@ -457,13 +478,19 @@ def test_main_parse_error(mock_cel_environment_syntax_error, caplog, capsys): status = celpy.__main__.main(argv) assert status == 1 assert mock_cel_environment_syntax_error.mock_calls == [ - call(package=None, annotations={'stat': celpy.celtypes.FunctionType}) + call(package=None, annotations={"stat": celpy.celtypes.FunctionType}) ] expected_namespace = argparse.Namespace( - verbose=0, arg=None, null_input=True, slurp=False, interactive=False, - package='jq', document=None, - boolean=False, format=None, - expr='[nope++]' + verbose=0, + arg=None, + null_input=True, + slurp=False, + interactive=False, + package="jq", + document=None, + boolean=False, + format=None, + expr="[nope++]", ) assert caplog.messages == [ str(expected_namespace), @@ -495,13 +522,19 @@ def test_main_0_eval_error(mock_cel_environment_eval_error, caplog, capsys): status = celpy.__main__.main(argv) assert status == 2 assert mock_cel_environment_eval_error.mock_calls == [ - call(package=None, annotations={'stat': celpy.celtypes.FunctionType}) + call(package=None, annotations={"stat": celpy.celtypes.FunctionType}) ] expected_namespace = argparse.Namespace( - verbose=0, arg=None, null_input=True, slurp=False, interactive=False, - package='jq', document=None, - boolean=False, format=None, - expr='2 / 0' + verbose=0, + arg=None, + null_input=True, + slurp=False, + interactive=False, + package="jq", + document=None, + boolean=False, + format=None, + expr="2 / 0", ) assert caplog.messages == [ str(expected_namespace), @@ -520,18 +553,24 @@ def test_main_pipe_eval_error(mock_cel_environment_eval_error, caplog, capsys): sys.stdin = sys.__stdin__ assert status == 0 assert mock_cel_environment_eval_error.mock_calls == [ - call(package='jq', annotations={'stat': celpy.celtypes.FunctionType}) + call(package="jq", annotations={"stat": celpy.celtypes.FunctionType}) ] expected_namespace = argparse.Namespace( - verbose=0, arg=None, null_input=False, slurp=False, interactive=False, - package='jq', document=None, - boolean=False, format=None, - expr='.json.field / 0' + verbose=0, + arg=None, + null_input=False, + slurp=False, + interactive=False, + package="jq", + document=None, + boolean=False, + format=None, + expr=".json.field / 0", ) assert caplog.messages == [ str(expected_namespace), "Expr: '.json.field / 0'", - "Encountered (sentinel.arg0, sentinel.arg1) on document '{\"name\": \"CEL\"}\\n'", + 'Encountered (sentinel.arg0, sentinel.arg1) on document \'{"name": "CEL"}\\n\'', ] out, err = capsys.readouterr() assert out == "null\n" @@ -541,18 +580,24 @@ def test_main_pipe_eval_error(mock_cel_environment_eval_error, caplog, capsys): def test_main_pipe_json_error(mock_cel_environment_eval_error, caplog, capsys): """GIVEN piped input AND bad expression; WHEN eval; THEN correct stderr output.""" argv = [".json.field / 0"] - sys.stdin = io.StringIO('nope, not json\n') + sys.stdin = io.StringIO("nope, not json\n") status = celpy.__main__.main(argv) sys.stdin = sys.__stdin__ assert status == 3 assert mock_cel_environment_eval_error.mock_calls == [ - call(package='jq', annotations={'stat': celpy.celtypes.FunctionType}) + call(package="jq", annotations={"stat": celpy.celtypes.FunctionType}) ] expected_namespace = argparse.Namespace( - verbose=0, arg=None, null_input=False, slurp=False, interactive=False, - package='jq', document=None, - boolean=False, format=None, - expr='.json.field / 0' + verbose=0, + arg=None, + null_input=False, + slurp=False, + interactive=False, + package="jq", + document=None, + boolean=False, + format=None, + expr=".json.field / 0", ) assert caplog.messages == [ str(expected_namespace), @@ -567,16 +612,12 @@ def test_main_pipe_json_error(mock_cel_environment_eval_error, caplog, capsys): def test_main_repl(monkeypatch, capsys): mock_repl = Mock() mock_repl_class = Mock(return_value=mock_repl) - monkeypatch.setattr(celpy.__main__, 'CEL_REPL', mock_repl_class) + monkeypatch.setattr(celpy.__main__, "CEL_REPL", mock_repl_class) argv = ["-i"] status = celpy.__main__.main(argv) assert status == 0 - assert mock_repl_class.mock_calls == [ - call() - ] - assert mock_repl.cmdloop.mock_calls == [ - call() - ] + assert mock_repl_class.mock_calls == [call()] + assert mock_repl.cmdloop.mock_calls == [call()] def test_repl_class_good_interaction(capsys): @@ -601,7 +642,7 @@ def test_repl_class_good_interaction(capsys): assert lines[0].startswith("3.14159") assert lines[1].startswith("{'pi': DoubleType(3.14159") assert lines[2].startswith("6.28318") - assert c.state == {"pi": celpy.celtypes.DoubleType(355./113.)} + assert c.state == {"pi": celpy.celtypes.DoubleType(355.0 / 113.0)} def test_repl_class_bad_interaction(capsys): @@ -611,40 +652,35 @@ def test_repl_class_bad_interaction(capsys): c.onecmd("this! isn't! valid!!") out, err = capsys.readouterr() lines = err.splitlines() - assert ( - lines[0] == - "ERROR: :1:5 pi ++ nope | not & proper \ CEL" - ) - assert ( - lines[4] == - " | ....^" - ) + assert lines[0] == "ERROR: :1:5 pi ++ nope | not & proper \ CEL" + assert lines[4] == " | ....^" assert c.state == {} def test_stat_good(): cwd = Path.cwd() doc = celpy.__main__.stat(str(cwd)) - assert doc['st_atime'] == celtypes.TimestampType( - datetime.datetime.fromtimestamp( - cwd.stat().st_atime)) - assert doc['st_ctime'] == celtypes.TimestampType( - datetime.datetime.fromtimestamp( - cwd.stat().st_ctime)) - assert doc['st_mtime'] == celtypes.TimestampType( - datetime.datetime.fromtimestamp( - cwd.stat().st_mtime)) + assert doc["st_atime"] == celtypes.TimestampType( + datetime.datetime.fromtimestamp(cwd.stat().st_atime) + ) + assert doc["st_ctime"] == celtypes.TimestampType( + datetime.datetime.fromtimestamp(cwd.stat().st_ctime) + ) + assert doc["st_mtime"] == celtypes.TimestampType( + datetime.datetime.fromtimestamp(cwd.stat().st_mtime) + ) # Not on all versions of Python. # assert doc['st_birthtime'] == celtypes.TimestampType( # datetime.datetime.fromtimestamp( # cwd.stat().st_birthtime)) - assert doc['st_ino'] == celtypes.IntType(cwd.stat().st_ino) - assert doc['st_size'] == celtypes.IntType(cwd.stat().st_size) - assert doc['st_nlink'] == celtypes.IntType(cwd.stat().st_nlink) - assert doc['kind'] == 'd' - assert doc['setuid'] == celtypes.BoolType(os_stat.S_ISUID & cwd.stat().st_mode != 0) - assert doc['setgid'] == celtypes.BoolType(os_stat.S_ISGID & cwd.stat().st_mode != 0) - assert doc['sticky'] == celtypes.BoolType(os_stat.S_ISVTX & cwd.stat().st_mode != 0) + assert doc["st_ino"] == celtypes.IntType(cwd.stat().st_ino) + assert doc["st_size"] == celtypes.IntType(cwd.stat().st_size) + assert doc["st_nlink"] == celtypes.IntType(cwd.stat().st_nlink) + assert doc["kind"] == "d" + assert doc["setuid"] == celtypes.BoolType(os_stat.S_ISUID & cwd.stat().st_mode != 0) + assert doc["setgid"] == celtypes.BoolType(os_stat.S_ISGID & cwd.stat().st_mode != 0) + assert doc["sticky"] == celtypes.BoolType(os_stat.S_ISVTX & cwd.stat().st_mode != 0) + def test_stat_does_not_exist(): path = Path.cwd() / "does_not_exist.tmp" diff --git a/tests/test_package.py b/tests/test_package.py index 77c22e4..3b30d91 100644 --- a/tests/test_package.py +++ b/tests/test_package.py @@ -17,6 +17,7 @@ Test celpy package as a whole. Mostly, this means testing the ``__init__.py`` module that defines the package. """ + import json from unittest.mock import Mock, call, sentinel @@ -37,7 +38,9 @@ def test_json_to_cel(): actual = celpy.json_to_cel(doc) expected = celpy.celtypes.ListType( [ - celpy.celtypes.MapType({celpy.celtypes.StringType("bool"): celpy.celtypes.BoolType(True)}), + celpy.celtypes.MapType( + {celpy.celtypes.StringType("bool"): celpy.celtypes.BoolType(True)} + ), celpy.celtypes.MapType( { celpy.celtypes.StringType("numbers"): celpy.celtypes.ListType( @@ -47,7 +50,11 @@ def test_json_to_cel(): ), celpy.celtypes.MapType({celpy.celtypes.StringType("null"): None}), celpy.celtypes.MapType( - {celpy.celtypes.StringType("string"): celpy.celtypes.StringType('embedded "quote"')} + { + celpy.celtypes.StringType("string"): celpy.celtypes.StringType( + 'embedded "quote"' + ) + } ), ] ) @@ -65,25 +72,30 @@ def test_encoder(): cel_obj = celpy.celtypes.MapType( { celpy.celtypes.StringType("bool"): celpy.celtypes.BoolType(True), - celpy.celtypes.StringType("numbers"): - celpy.celtypes.ListType([ - celpy.celtypes.DoubleType(2.71828), celpy.celtypes.UintType(42) - ]), + celpy.celtypes.StringType("numbers"): celpy.celtypes.ListType( + [celpy.celtypes.DoubleType(2.71828), celpy.celtypes.UintType(42)] + ), celpy.celtypes.StringType("null"): None, - celpy.celtypes.StringType("string"): celpy.celtypes.StringType('embedded "quote"'), - celpy.celtypes.StringType("bytes"): - celpy.celtypes.BytesType(bytes([0x62, 0x79, 0x74, 0x65, 0x73])), - celpy.celtypes.StringType("timestamp"): celpy.celtypes.TimestampType('2009-02-13T23:31:30Z'), - celpy.celtypes.StringType("duration"): celpy.celtypes.DurationType('42s'), + celpy.celtypes.StringType("string"): celpy.celtypes.StringType( + 'embedded "quote"' + ), + celpy.celtypes.StringType("bytes"): celpy.celtypes.BytesType( + bytes([0x62, 0x79, 0x74, 0x65, 0x73]) + ), + celpy.celtypes.StringType("timestamp"): celpy.celtypes.TimestampType( + "2009-02-13T23:31:30Z" + ), + celpy.celtypes.StringType("duration"): celpy.celtypes.DurationType("42s"), } ) json_text = json.dumps(cel_obj, cls=celpy.CELJSONEncoder) assert ( json_text == '{"bool": true, "numbers": [2.71828, 42], "null": null, ' - '"string": "embedded \\"quote\\"", "bytes": "Ynl0ZXM=", ' - '"timestamp": "2009-02-13T23:31:30Z", "duration": "42s"}' + '"string": "embedded \\"quote\\"", "bytes": "Ynl0ZXM=", ' + '"timestamp": "2009-02-13T23:31:30Z", "duration": "42s"}' ) + def test_encoder_unknown(): cel_obj = sentinel.no_json with pytest.raises(TypeError): @@ -95,18 +107,25 @@ def test_decoder(): '{"bool": 1, "numbers": [2.71828, 42], "null": null, ' '"string": "embedded \\"quote\\"", "bytes": "Ynl0ZXM=", ' '"timestamp": "2009-02-13T23:31:30Z", "duration": "42s"}' - ) + ) cel_obj = json.loads(json_text, cls=celpy.CELJSONDecoder) - assert cel_obj == celpy.celtypes.MapType({ - celpy.celtypes.StringType('bool'): celpy.celtypes.IntType(1), - celpy.celtypes.StringType('bytes'): celpy.celtypes.StringType('Ynl0ZXM='), - celpy.celtypes.StringType('duration'): celpy.celtypes.StringType('42s'), - celpy.celtypes.StringType('null'): None, - celpy.celtypes.StringType('numbers'): - celpy.celtypes.ListType([celpy.celtypes.DoubleType(2.71828), celpy.celtypes.IntType(42)]), - celpy.celtypes.StringType('string'): celpy.celtypes.StringType('embedded "quote"'), - celpy.celtypes.StringType('timestamp'): celpy.celtypes.StringType('2009-02-13T23:31:30Z'), - }) + assert cel_obj == celpy.celtypes.MapType( + { + celpy.celtypes.StringType("bool"): celpy.celtypes.IntType(1), + celpy.celtypes.StringType("bytes"): celpy.celtypes.StringType("Ynl0ZXM="), + celpy.celtypes.StringType("duration"): celpy.celtypes.StringType("42s"), + celpy.celtypes.StringType("null"): None, + celpy.celtypes.StringType("numbers"): celpy.celtypes.ListType( + [celpy.celtypes.DoubleType(2.71828), celpy.celtypes.IntType(42)] + ), + celpy.celtypes.StringType("string"): celpy.celtypes.StringType( + 'embedded "quote"' + ), + celpy.celtypes.StringType("timestamp"): celpy.celtypes.StringType( + "2009-02-13T23:31:30Z" + ), + } + ) @pytest.fixture @@ -124,10 +143,18 @@ def test_interp_runner(mock_environment): WHEN InterpretedRunner created and evaluated THEN Runner uses Environment, AST, and the mocked Evaluator """ + def a_function(): return None + functions = [a_function] - ast = Mock(spec=lark.Tree, children=[lark.Token(type_="BOOL_LIT", value="true"),], data="literal") + ast = Mock( + spec=lark.Tree, + children=[ + lark.Token(type_="BOOL_LIT", value="true"), + ], + data="literal", + ) r = celpy.InterpretedRunner(mock_environment, ast, functions) result = r.evaluate({"variable": sentinel.variable}) assert result == celpy.celtypes.BoolType(True) @@ -143,20 +170,27 @@ def mock_ast(): tree = parser.parse(source) return tree + def test_compiled_runner(mock_environment, mock_ast): """ GIVEN Environment and AST and mocked Evaluator WHEN InterpretedRunner created and evaluated THEN Runner uses Environment, AST, and the mocked Evaluator """ + def a_function(): return None + functions = [a_function] r = celpy.CompiledRunner(mock_environment, mock_ast, functions) - assert r.tp.source_text.strip() == "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.BoolType(True))" + assert ( + r.tp.source_text.strip() + == "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.BoolType(True))" + ) result = r.evaluate({"variable": sentinel.variable}) assert result == celpy.celtypes.BoolType(True) + @pytest.fixture def mock_parser(monkeypatch): parser = Mock(parse=Mock(return_value=sentinel.AST)) @@ -182,7 +216,9 @@ def mock_activation(monkeypatch): def test_environment(mock_parser, mock_runner, mock_activation): - e = celpy.Environment(sentinel.package, {sentinel.variable: celpy.celtypes.UintType}) + e = celpy.Environment( + sentinel.package, {sentinel.variable: celpy.celtypes.UintType} + ) ast = e.compile(sentinel.Source) assert ast == sentinel.AST assert mock_parser.return_value.parse.mock_calls == [call(sentinel.Source)] diff --git a/tests/test_parser.py b/tests/test_parser.py index 3accfde..c44017f 100644 --- a/tests/test_parser.py +++ b/tests/test_parser.py @@ -26,6 +26,7 @@ TODO: Create a better, more useful tree-walker than the Tree.pretty() to examine the resulting AST. """ + from textwrap import dedent from lark import Tree @@ -398,9 +399,9 @@ def test_error_text(parser): ) assert lines.splitlines() == [ "ERROR: :1:7 nope*()/-+", - ' ^', - '', - ' | nope*()/-+', + " ^", + "", + " | nope*()/-+", " | ......^", ] @@ -417,11 +418,9 @@ def test_dump_ast(parser): ast2 = parser.parse( '!true in [1<2, 1<=2, 2>1, 2>=1, 3==3, 4!=1, size(x), now(), {"pi": 3.14}]' ) - assert ( - DumpAST.display(ast2) == ( - '! true in [1 < 2, 1 <= 2, 2 > 1, 2 >= 1, 3 == 3, 4 != 1, ' - 'size(x), now(), {"pi": 3.14}]' - ) + assert DumpAST.display(ast2) == ( + "! true in [1 < 2, 1 <= 2, 2 > 1, 2 >= 1, 3 == 3, 4 != 1, " + 'size(x), now(), {"pi": 3.14}]' ) ast3 = parser.parse( ".name.name / .name() + .name(42) * name.name - name.one(1) % name.zero()" @@ -447,5 +446,7 @@ def test_dump_issue_35(): def test_tree_dump(parser): ast = parser.parse("-(3*4+5-1/2%3==1)?name[index]:f(1,2)||false&&true") - assert tree_dump(ast) == '- (3 * 4 + 5 - 1 / 2 % 3 == 1) ? name[index] : f(1, 2) || false && true' - + assert ( + tree_dump(ast) + == "- (3 * 4 + 5 - 1 / 2 % 3 == 1) ? name[index] : f(1, 2) || false && true" + ) diff --git a/tests/test_transpilation.py b/tests/test_transpilation.py index f8d70eb..176c9dc 100644 --- a/tests/test_transpilation.py +++ b/tests/test_transpilation.py @@ -31,6 +31,7 @@ This module cherry-picks tests of CEL expressions separate from the evaluation mechanics. """ + import ast from textwrap import dedent from types import SimpleNamespace @@ -47,15 +48,24 @@ @pytest.fixture def mock_protobuf(): """Used for a few test cases.""" + def get_method(name, default=None): if name == "field": return 42 else: raise KeyError(name) - protobuf_message = Mock(name="protobuf_message", spec=celtypes.MessageType, get=Mock(side_effect=get_method)) - protobuf_message_class = Mock(name="protobuf_message class", return_value=protobuf_message) + + protobuf_message = Mock( + name="protobuf_message", + spec=celtypes.MessageType, + get=Mock(side_effect=get_method), + ) + protobuf_message_class = Mock( + name="protobuf_message class", return_value=protobuf_message + ) return protobuf_message_class + # This may be slightly better for isolating Activation implementation. # @pytest.fixture # def mock_activation(): @@ -64,6 +74,7 @@ def get_method(name, default=None): # ) # return activation + @pytest.fixture def mock_functions(): return {"no_arg_function": no_arg_function} @@ -84,13 +95,14 @@ def mock_activation(mock_protobuf, mock_functions): vars={ "duration": celtypes.DurationType(seconds=123, nanos=123456789), "a.b.c": celtypes.StringType("yeah"), - } + }, ) def no_arg_function(): return celpy.celtypes.IntType(42) + @pytest.fixture def mock_globals(mock_activation, mock_protobuf): # Works, but feels sketchy... @@ -106,6 +118,7 @@ def mock_globals(mock_activation, mock_protobuf): # global_vars = globals().copy() return global_vars + def test_result_builder(mock_globals, mock_activation): def mock_operation(a, b): if isinstance(a, Exception): @@ -113,15 +126,22 @@ def mock_operation(a, b): else: return sentinel.A_OP_B - - expr_1 = lambda activation: mock_operation(TypeError(sentinel.type_error_message), sentinel.VALUE) + expr_1 = lambda activation: mock_operation( + TypeError(sentinel.type_error_message), sentinel.VALUE + ) result_1 = celpy.evaluation.result(mock_activation, expr_1) assert isinstance(result_1, CELEvalError) - assert result_1.args == ('no such overload', TypeError, (sentinel.type_error_message,)) + assert result_1.args == ( + "no such overload", + TypeError, + (sentinel.type_error_message,), + ) assert result_1.__cause__.__class__ == TypeError with pytest.raises(IOError) as exc_info: - expr_2 = lambda activation: mock_operation(IOError(sentinel.io_error_message), sentinel.VALUE) + expr_2 = lambda activation: mock_operation( + IOError(sentinel.io_error_message), sentinel.VALUE + ) result_2 = celpy.evaluation.result(mock_activation, expr_2) assert not isinstance(exc_info.value, CELEvalError) assert exc_info.value.args == (sentinel.io_error_message,) @@ -131,491 +151,734 @@ def mock_operation(a, b): literals = [ - ('3.14', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.DoubleType(3.14))", - celpy.celtypes.DoubleType(3.14), - "literal"), - ('42', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.IntType(42))", - celpy.celtypes.IntType(42), - "literal"), - ('42u', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.UintType(42))", - celpy.celtypes.UintType(42), - "literal"), - ('b"B"', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.BytesType(b'B'))", - celpy.celtypes.BytesType(b'B'), - "literal"), - ('"String"', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.StringType('String'))", - celpy.celtypes.StringType("String"), - "literal"), - ('true', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.BoolType(True))", - celpy.celtypes.BoolType(True), - "literal"), - ('null', - "CEL = celpy.evaluation.result(base_activation, lambda activation: None)", - None, # celpy.celtypes.NullType(), - "literal"), - ('[]', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.ListType([]))", - celpy.celtypes.ListType([]), - "literal"), - ('{}', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.MapType([]))", - celpy.celtypes.MapType({}), - "literal"), - ('bool', - "CEL = celpy.evaluation.result(base_activation, lambda activation: activation.bool)", - celpy.celtypes.BoolType, - "literal"), + ( + "3.14", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.DoubleType(3.14))", + celpy.celtypes.DoubleType(3.14), + "literal", + ), + ( + "42", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.IntType(42))", + celpy.celtypes.IntType(42), + "literal", + ), + ( + "42u", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.UintType(42))", + celpy.celtypes.UintType(42), + "literal", + ), + ( + 'b"B"', + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.BytesType(b'B'))", + celpy.celtypes.BytesType(b"B"), + "literal", + ), + ( + '"String"', + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.StringType('String'))", + celpy.celtypes.StringType("String"), + "literal", + ), + ( + "true", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.BoolType(True))", + celpy.celtypes.BoolType(True), + "literal", + ), + ( + "null", + "CEL = celpy.evaluation.result(base_activation, lambda activation: None)", + None, # celpy.celtypes.NullType(), + "literal", + ), + ( + "[]", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.ListType([]))", + celpy.celtypes.ListType([]), + "literal", + ), + ( + "{}", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.MapType([]))", + celpy.celtypes.MapType({}), + "literal", + ), + ( + "bool", + "CEL = celpy.evaluation.result(base_activation, lambda activation: activation.bool)", + celpy.celtypes.BoolType, + "literal", + ), ] function_params = [ - ("size([42, 6, 7])", - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_size(celpy.celtypes.ListType([celpy.celtypes.IntType(42), celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)])))", - celpy.celtypes.IntType(3), - "IDENT(_)"), - ("size(3.14)", - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_size(celpy.celtypes.DoubleType(3.14)))", - CELEvalError, - "IDENT(_)"), - ('"hello".size()', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_size(celpy.celtypes.StringType('hello')))", - celpy.celtypes.IntType(5), - "_.IDENT()"), + ( + "size([42, 6, 7])", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_size(celpy.celtypes.ListType([celpy.celtypes.IntType(42), celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)])))", + celpy.celtypes.IntType(3), + "IDENT(_)", + ), + ( + "size(3.14)", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_size(celpy.celtypes.DoubleType(3.14)))", + CELEvalError, + "IDENT(_)", + ), + ( + '"hello".size()', + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_size(celpy.celtypes.StringType('hello')))", + celpy.celtypes.IntType(5), + "_.IDENT()", + ), ] method_params = [ - ("[42, 6, 7].size()", - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_size(celpy.celtypes.ListType([celpy.celtypes.IntType(42), celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)])))", - celpy.celtypes.IntType(3), - "_.size()"), - ('timestamp("2009-02-13T23:31:30Z").getMonth()', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getMonth(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))", - celtypes.IntType(1), - "_._())"), - ('["hello", "world"].contains("hello")', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_contains(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.StringType('hello')))", - celtypes.BoolType(True), - "_._(_)"), + ( + "[42, 6, 7].size()", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_size(celpy.celtypes.ListType([celpy.celtypes.IntType(42), celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)])))", + celpy.celtypes.IntType(3), + "_.size()", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getMonth()', + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getMonth(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))", + celtypes.IntType(1), + "_._())", + ), + ( + '["hello", "world"].contains("hello")', + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_contains(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.StringType('hello')))", + celtypes.BoolType(True), + "_._(_)", + ), ] macro_has_params = [ - ('has({"n": 355, "d": 113}.n)', - dedent("""\ + ( + 'has({"n": 355, "d": 113}.n)', + dedent("""\ # ident_arg has: ex_9_h = lambda activation: celpy.celtypes.MapType([(celpy.celtypes.StringType('n'), celpy.celtypes.IntType(355)), (celpy.celtypes.StringType('d'), celpy.celtypes.IntType(113))]).get('n') ex_9 = lambda activation: not isinstance(celpy.evaluation.result(activation, ex_9_h), CELEvalError) CEL = celpy.evaluation.result(base_activation, ex_9)"""), - celtypes.BoolType(True), - "has(_._)"), - ('has({"n": 355, "d": 113}.nope)', - dedent("""\ + celtypes.BoolType(True), + "has(_._)", + ), + ( + 'has({"n": 355, "d": 113}.nope)', + dedent("""\ # ident_arg has: ex_9_h = lambda activation: celpy.celtypes.MapType([(celpy.celtypes.StringType('n'), celpy.celtypes.IntType(355)), (celpy.celtypes.StringType('d'), celpy.celtypes.IntType(113))]).get('nope') ex_9 = lambda activation: not isinstance(celpy.evaluation.result(activation, ex_9_h), CELEvalError) - CEL = celpy.evaluation.result(base_activation, ex_9)""" - ), - celtypes.BoolType(False), - "has(_._)"), - ('dyn(6) * 7', - "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.mul(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", - celtypes.IntType(42), - "dyn(_)"), - ("type(dyn([1, 'one']))", - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.TypeType(celpy.celtypes.ListType([celpy.celtypes.IntType(1), celpy.celtypes.StringType('one')])))", - celtypes.ListType, - "dyn(_)"), + CEL = celpy.evaluation.result(base_activation, ex_9)"""), + celtypes.BoolType(False), + "has(_._)", + ), + ( + "dyn(6) * 7", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.mul(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", + celtypes.IntType(42), + "dyn(_)", + ), + ( + "type(dyn([1, 'one']))", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.TypeType(celpy.celtypes.ListType([celpy.celtypes.IntType(1), celpy.celtypes.StringType('one')])))", + celtypes.ListType, + "dyn(_)", + ), ] unary_operator_params = [ - ("! true", "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.logical_not(celpy.celtypes.BoolType(True)))", celtypes.BoolType(False), "!_"), - ("- 42", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.neg(celpy.celtypes.IntType(42)))", celtypes.IntType(-42), "-_"), - ("- -9223372036854775808", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.neg(celpy.celtypes.IntType(-9223372036854775808)))", CELEvalError, "-_"), + ( + "! true", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.logical_not(celpy.celtypes.BoolType(True)))", + celtypes.BoolType(False), + "!_", + ), + ( + "- 42", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.neg(celpy.celtypes.IntType(42)))", + celtypes.IntType(-42), + "-_", + ), + ( + "- -9223372036854775808", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.neg(celpy.celtypes.IntType(-9223372036854775808)))", + CELEvalError, + "-_", + ), ] binary_operator_params = [ - ("6 < 7", "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_lt(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", celtypes.BoolType(True), "_<_"), - ("6 <= 7", "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_le(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", celtypes.BoolType(True), "_<=_"), - ("6 > 7", "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_gt(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", celtypes.BoolType(False), "_>_"), - ("6 >= 7", "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_ge(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", celtypes.BoolType(False), "_>=_"), - ("42 == 42", "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_eq(celpy.celtypes.IntType(42), celpy.celtypes.IntType(42)))", celtypes.BoolType(True), "_==_"), - ("[] == []", "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_eq(celpy.celtypes.ListType([]), celpy.celtypes.ListType([])))", celtypes.BoolType(True), "_==_"), - ("42 != 42", "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_ne(celpy.celtypes.IntType(42), celpy.celtypes.IntType(42)))", celtypes.BoolType(False), "_!=_"), - ('"b" in ["a", "b", "c"]', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.operator_in(celpy.celtypes.StringType('b'), celpy.celtypes.ListType([celpy.celtypes.StringType('a'), celpy.celtypes.StringType('b'), celpy.celtypes.StringType('c')])))", - celtypes.BoolType(True), - "_in_"), - ("40 + 2", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.add(celpy.celtypes.IntType(40), celpy.celtypes.IntType(2)))", celtypes.IntType(42), "_+_"), - ("44 - 2", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.sub(celpy.celtypes.IntType(44), celpy.celtypes.IntType(2)))", celtypes.IntType(42), "_-_"), - ("6 * 7", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.mul(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", celtypes.IntType(42), "_*_"), - ("84 / 2", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.truediv(celpy.celtypes.IntType(84), celpy.celtypes.IntType(2)))", celtypes.IntType(42), "_/_"), - ("85 % 43", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.mod(celpy.celtypes.IntType(85), celpy.celtypes.IntType(43)))", celtypes.IntType(42), "_%_"), + ( + "6 < 7", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_lt(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", + celtypes.BoolType(True), + "_<_", + ), + ( + "6 <= 7", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_le(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", + celtypes.BoolType(True), + "_<=_", + ), + ( + "6 > 7", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_gt(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", + celtypes.BoolType(False), + "_>_", + ), + ( + "6 >= 7", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_ge(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", + celtypes.BoolType(False), + "_>=_", + ), + ( + "42 == 42", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_eq(celpy.celtypes.IntType(42), celpy.celtypes.IntType(42)))", + celtypes.BoolType(True), + "_==_", + ), + ( + "[] == []", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_eq(celpy.celtypes.ListType([]), celpy.celtypes.ListType([])))", + celtypes.BoolType(True), + "_==_", + ), + ( + "42 != 42", + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_ne(celpy.celtypes.IntType(42), celpy.celtypes.IntType(42)))", + celtypes.BoolType(False), + "_!=_", + ), + ( + '"b" in ["a", "b", "c"]', + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.operator_in(celpy.celtypes.StringType('b'), celpy.celtypes.ListType([celpy.celtypes.StringType('a'), celpy.celtypes.StringType('b'), celpy.celtypes.StringType('c')])))", + celtypes.BoolType(True), + "_in_", + ), + ( + "40 + 2", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.add(celpy.celtypes.IntType(40), celpy.celtypes.IntType(2)))", + celtypes.IntType(42), + "_+_", + ), + ( + "44 - 2", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.sub(celpy.celtypes.IntType(44), celpy.celtypes.IntType(2)))", + celtypes.IntType(42), + "_-_", + ), + ( + "6 * 7", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.mul(celpy.celtypes.IntType(6), celpy.celtypes.IntType(7)))", + celtypes.IntType(42), + "_*_", + ), + ( + "84 / 2", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.truediv(celpy.celtypes.IntType(84), celpy.celtypes.IntType(2)))", + celtypes.IntType(42), + "_/_", + ), + ( + "85 % 43", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.mod(celpy.celtypes.IntType(85), celpy.celtypes.IntType(43)))", + celtypes.IntType(42), + "_%_", + ), # A few error examples - ('42 in ["a", "b", "c"]', - "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.operator_in(celpy.celtypes.IntType(42), celpy.celtypes.ListType([celpy.celtypes.StringType('a'), celpy.celtypes.StringType('b'), celpy.celtypes.StringType('c')])))", - CELEvalError, - "_in_"), - ("9223372036854775807 + 1", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.add(celpy.celtypes.IntType(9223372036854775807), celpy.celtypes.IntType(1)))", CELEvalError, "_+_"), - ("9223372036854775807 * 2", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.mul(celpy.celtypes.IntType(9223372036854775807), celpy.celtypes.IntType(2)))", CELEvalError, "_*_"), - ("84 / 0", "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.truediv(celpy.celtypes.IntType(84), celpy.celtypes.IntType(0)))", CELEvalError, "_/_"), + ( + '42 in ["a", "b", "c"]', + "CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.operator_in(celpy.celtypes.IntType(42), celpy.celtypes.ListType([celpy.celtypes.StringType('a'), celpy.celtypes.StringType('b'), celpy.celtypes.StringType('c')])))", + CELEvalError, + "_in_", + ), + ( + "9223372036854775807 + 1", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.add(celpy.celtypes.IntType(9223372036854775807), celpy.celtypes.IntType(1)))", + CELEvalError, + "_+_", + ), + ( + "9223372036854775807 * 2", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.mul(celpy.celtypes.IntType(9223372036854775807), celpy.celtypes.IntType(2)))", + CELEvalError, + "_*_", + ), + ( + "84 / 0", + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.truediv(celpy.celtypes.IntType(84), celpy.celtypes.IntType(0)))", + CELEvalError, + "_/_", + ), ] short_circuit_params = [ - ("true || (3 / 0 != 0)", - dedent("""\ + ( + "true || (3 / 0 != 0)", + dedent("""\ # conditionalor: ex_1_l = lambda activation: celpy.celtypes.BoolType(True) ex_1_r = lambda activation: celpy.evaluation.bool_ne(operator.truediv(celpy.celtypes.IntType(3), celpy.celtypes.IntType(0)), celpy.celtypes.IntType(0)) ex_1 = lambda activation: celpy.celtypes.logical_or(celpy.evaluation.result(activation, ex_1_l), celpy.evaluation.result(activation, ex_1_r)) CEL = celpy.evaluation.result(base_activation, ex_1)"""), - celtypes.BoolType(True), "_||_"), - ("(3 / 0 != 0) || true", - dedent("""\ + celtypes.BoolType(True), + "_||_", + ), + ( + "(3 / 0 != 0) || true", + dedent("""\ # conditionalor: ex_1_l = lambda activation: celpy.evaluation.bool_ne(operator.truediv(celpy.celtypes.IntType(3), celpy.celtypes.IntType(0)), celpy.celtypes.IntType(0)) ex_1_r = lambda activation: celpy.celtypes.BoolType(True) ex_1 = lambda activation: celpy.celtypes.logical_or(celpy.evaluation.result(activation, ex_1_l), celpy.evaluation.result(activation, ex_1_r)) CEL = celpy.evaluation.result(base_activation, ex_1)"""), - celtypes.BoolType(True), "_||_"), - ("false || (3 / 0 != 0)", - dedent("""\ + celtypes.BoolType(True), + "_||_", + ), + ( + "false || (3 / 0 != 0)", + dedent("""\ # conditionalor: ex_1_l = lambda activation: celpy.celtypes.BoolType(False) ex_1_r = lambda activation: celpy.evaluation.bool_ne(operator.truediv(celpy.celtypes.IntType(3), celpy.celtypes.IntType(0)), celpy.celtypes.IntType(0)) ex_1 = lambda activation: celpy.celtypes.logical_or(celpy.evaluation.result(activation, ex_1_l), celpy.evaluation.result(activation, ex_1_r)) CEL = celpy.evaluation.result(base_activation, ex_1)"""), - CELEvalError, "_||_"), - ("(3 / 0 != 0) || false", - dedent("""\ + CELEvalError, + "_||_", + ), + ( + "(3 / 0 != 0) || false", + dedent("""\ # conditionalor: ex_1_l = lambda activation: celpy.evaluation.bool_ne(operator.truediv(celpy.celtypes.IntType(3), celpy.celtypes.IntType(0)), celpy.celtypes.IntType(0)) ex_1_r = lambda activation: celpy.celtypes.BoolType(False) ex_1 = lambda activation: celpy.celtypes.logical_or(celpy.evaluation.result(activation, ex_1_l), celpy.evaluation.result(activation, ex_1_r)) CEL = celpy.evaluation.result(base_activation, ex_1)"""), - CELEvalError, "_||_"), - - ("true && 3 / 0", - dedent("""\ + CELEvalError, + "_||_", + ), + ( + "true && 3 / 0", + dedent("""\ # conditionaland: ex_2_l = lambda activation: celpy.celtypes.BoolType(True) ex_2_r = lambda activation: operator.truediv(celpy.celtypes.IntType(3), celpy.celtypes.IntType(0)) ex_2 = lambda activation: celpy.celtypes.logical_and(celpy.evaluation.result(activation, ex_2_l), celpy.evaluation.result(activation, ex_2_r)) CEL = celpy.evaluation.result(base_activation, ex_2)"""), - CELEvalError, "_&&_"), - ("false && 3 / 0", - dedent("""\ + CELEvalError, + "_&&_", + ), + ( + "false && 3 / 0", + dedent("""\ # conditionaland: ex_2_l = lambda activation: celpy.celtypes.BoolType(False) ex_2_r = lambda activation: operator.truediv(celpy.celtypes.IntType(3), celpy.celtypes.IntType(0)) ex_2 = lambda activation: celpy.celtypes.logical_and(celpy.evaluation.result(activation, ex_2_l), celpy.evaluation.result(activation, ex_2_r)) CEL = celpy.evaluation.result(base_activation, ex_2)"""), - celpy.celtypes.BoolType(False), "_&&_"), - ("3 / 0 && true", - dedent("""\ + celpy.celtypes.BoolType(False), + "_&&_", + ), + ( + "3 / 0 && true", + dedent("""\ # conditionaland: ex_2_l = lambda activation: operator.truediv(celpy.celtypes.IntType(3), celpy.celtypes.IntType(0)) ex_2_r = lambda activation: celpy.celtypes.BoolType(True) ex_2 = lambda activation: celpy.celtypes.logical_and(celpy.evaluation.result(activation, ex_2_l), celpy.evaluation.result(activation, ex_2_r)) CEL = celpy.evaluation.result(base_activation, ex_2)"""), - CELEvalError, "_&&_"), - ("3 / 0 && false", - dedent("""\ + CELEvalError, + "_&&_", + ), + ( + "3 / 0 && false", + dedent("""\ # conditionaland: ex_2_l = lambda activation: operator.truediv(celpy.celtypes.IntType(3), celpy.celtypes.IntType(0)) ex_2_r = lambda activation: celpy.celtypes.BoolType(False) ex_2 = lambda activation: celpy.celtypes.logical_and(celpy.evaluation.result(activation, ex_2_l), celpy.evaluation.result(activation, ex_2_r)) CEL = celpy.evaluation.result(base_activation, ex_2)"""), - celpy.celtypes.BoolType(False), "_&&_"), - - ("(13 % 2 != 0) ? (13 * 3 + 1) : (13 / 0)", - dedent("""\ + celpy.celtypes.BoolType(False), + "_&&_", + ), + ( + "(13 % 2 != 0) ? (13 * 3 + 1) : (13 / 0)", + dedent("""\ # expr: ex_0_c = lambda activation: celpy.evaluation.bool_ne(operator.mod(celpy.celtypes.IntType(13), celpy.celtypes.IntType(2)), celpy.celtypes.IntType(0)) ex_0_l = lambda activation: operator.add(operator.mul(celpy.celtypes.IntType(13), celpy.celtypes.IntType(3)), celpy.celtypes.IntType(1)) ex_0_r = lambda activation: operator.truediv(celpy.celtypes.IntType(13), celpy.celtypes.IntType(0)) ex_0 = lambda activation: celpy.celtypes.logical_condition(celpy.evaluation.result(activation, ex_0_c), celpy.evaluation.result(activation, ex_0_l), celpy.evaluation.result(activation, ex_0_r)) CEL = celpy.evaluation.result(base_activation, ex_0)"""), - celtypes.IntType(40), - "_?_:_"), - ("(12 % 2 != 0) ? (12 / 0) : (12 / 2)", - dedent("""\ + celtypes.IntType(40), + "_?_:_", + ), + ( + "(12 % 2 != 0) ? (12 / 0) : (12 / 2)", + dedent("""\ # expr: ex_0_c = lambda activation: celpy.evaluation.bool_ne(operator.mod(celpy.celtypes.IntType(12), celpy.celtypes.IntType(2)), celpy.celtypes.IntType(0)) ex_0_l = lambda activation: operator.truediv(celpy.celtypes.IntType(12), celpy.celtypes.IntType(0)) ex_0_r = lambda activation: operator.truediv(celpy.celtypes.IntType(12), celpy.celtypes.IntType(2)) ex_0 = lambda activation: celpy.celtypes.logical_condition(celpy.evaluation.result(activation, ex_0_c), celpy.evaluation.result(activation, ex_0_l), celpy.evaluation.result(activation, ex_0_r)) CEL = celpy.evaluation.result(base_activation, ex_0)"""), - celtypes.IntType(6), - "_?_:_"), - ("(14 % 0 != 0) ? (14 * 3 + 1) : (14 / 2)", - dedent("""\ + celtypes.IntType(6), + "_?_:_", + ), + ( + "(14 % 0 != 0) ? (14 * 3 + 1) : (14 / 2)", + dedent("""\ # expr: ex_0_c = lambda activation: celpy.evaluation.bool_ne(operator.mod(celpy.celtypes.IntType(14), celpy.celtypes.IntType(0)), celpy.celtypes.IntType(0)) ex_0_l = lambda activation: operator.add(operator.mul(celpy.celtypes.IntType(14), celpy.celtypes.IntType(3)), celpy.celtypes.IntType(1)) ex_0_r = lambda activation: operator.truediv(celpy.celtypes.IntType(14), celpy.celtypes.IntType(2)) ex_0 = lambda activation: celpy.celtypes.logical_condition(celpy.evaluation.result(activation, ex_0_c), celpy.evaluation.result(activation, ex_0_l), celpy.evaluation.result(activation, ex_0_r)) CEL = celpy.evaluation.result(base_activation, ex_0)"""), - CELEvalError, - "_?_:_"), + CELEvalError, + "_?_:_", + ), ] member_dot_params = [ - ('{"field": 42}.field', - dedent("""\ + ( + '{"field": 42}.field', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.celtypes.MapType([(celpy.celtypes.StringType('field'), celpy.celtypes.IntType(42))]).get('field'))"""), - celtypes.IntType(42), - "_._"), + celtypes.IntType(42), + "_._", + ), # Must match the mock_protobuf message - ('protobuf_message{field: 42}.field', - dedent("""\ + ( + "protobuf_message{field: 42}.field", + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: activation.protobuf_message([('field', celpy.celtypes.IntType(42))]).get('field'))"""), - celtypes.IntType(42), - "_._"), + celtypes.IntType(42), + "_._", + ), # Must NOT match the mock_protobuf message - ('protobuf_message{field: 42}.not_the_name', - dedent("""\ + ( + "protobuf_message{field: 42}.not_the_name", + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: activation.protobuf_message([('field', celpy.celtypes.IntType(42))]).get('not_the_name'))"""), - CELEvalError, - "_._"), + CELEvalError, + "_._", + ), # Requires mock_activation with {"name1.name2": celtypes.IntType} - ('name1.name2', - dedent("""\ + ( + "name1.name2", + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: activation.name1.get('name2'))"""), - celtypes.IntType, - "_._"), - ('a.b.c', - dedent("""\ + celtypes.IntType, + "_._", + ), + ( + "a.b.c", + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: activation.a.get('b').get('c'))"""), - celtypes.StringType("yeah"), - "_._"), + celtypes.StringType("yeah"), + "_._", + ), ] member_item_params = [ - ('["hello", "world"][0]', - "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.IntType(0)))", - celtypes.StringType("hello"), - "_.[_]"), - ('["hello", "world"][42]', - "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.IntType(42)))", - CELEvalError, - "_.[_]"), - ('["hello", "world"][3.14]', - "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.DoubleType(3.14)))", - CELEvalError, - "_.[_]"), - ('{"hello": "world"}["hello"]', - "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.MapType([(celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world'))]), celpy.celtypes.StringType('hello')))", - celtypes.StringType("world"), - "_.[_]"), - ('{"hello": "world"}["world"]', - "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.MapType([(celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world'))]), celpy.celtypes.StringType('world')))", - CELEvalError, - "_.[_]"), + ( + '["hello", "world"][0]', + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.IntType(0)))", + celtypes.StringType("hello"), + "_.[_]", + ), + ( + '["hello", "world"][42]', + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.IntType(42)))", + CELEvalError, + "_.[_]", + ), + ( + '["hello", "world"][3.14]', + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.DoubleType(3.14)))", + CELEvalError, + "_.[_]", + ), + ( + '{"hello": "world"}["hello"]', + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.MapType([(celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world'))]), celpy.celtypes.StringType('hello')))", + celtypes.StringType("world"), + "_.[_]", + ), + ( + '{"hello": "world"}["world"]', + "CEL = celpy.evaluation.result(base_activation, lambda activation: operator.getitem(celpy.celtypes.MapType([(celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world'))]), celpy.celtypes.StringType('world')))", + CELEvalError, + "_.[_]", + ), ] # A protobuf message class, `protobuf_message`, is required in the activation. member_object_params = [ # Must match the mock_protobuf fixture - ('protobuf_message{field: 42}', - "CEL = celpy.evaluation.result(base_activation, lambda activation: activation.protobuf_message([('field', celpy.celtypes.IntType(42))]))", - sentinel.MESSAGE, - "_.{_}"), - ('protobuf_message{}', - "CEL = celpy.evaluation.result(base_activation, lambda activation: activation.protobuf_message([]))", - sentinel.MESSAGE, - "_.{_}"), + ( + "protobuf_message{field: 42}", + "CEL = celpy.evaluation.result(base_activation, lambda activation: activation.protobuf_message([('field', celpy.celtypes.IntType(42))]))", + sentinel.MESSAGE, + "_.{_}", + ), + ( + "protobuf_message{}", + "CEL = celpy.evaluation.result(base_activation, lambda activation: activation.protobuf_message([]))", + sentinel.MESSAGE, + "_.{_}", + ), ] member_dot_arg_method = [ - ('timestamp("2009-02-13T23:31:30Z").getMonth()', - dedent("""\ + ( + 'timestamp("2009-02-13T23:31:30Z").getMonth()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getMonth(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(1), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getDate()', - dedent("""\ + celtypes.IntType(1), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getDate()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getDate(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(13), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getDayOfMonth()', - dedent("""\ + celtypes.IntType(13), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getDayOfMonth()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getDayOfMonth(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(12), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getDayOfWeek()', - dedent("""\ + celtypes.IntType(12), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getDayOfWeek()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getDayOfWeek(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(5), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getDayOfYear()', - dedent("""\ + celtypes.IntType(5), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getDayOfYear()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getDayOfYear(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(43), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getFullYear()', - dedent("""\ + celtypes.IntType(43), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getFullYear()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getFullYear(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(2009), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getHours()', - dedent("""\ + celtypes.IntType(2009), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getHours()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getHours(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(23), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getMilliseconds()', - dedent("""\ + celtypes.IntType(23), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getMilliseconds()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getMilliseconds(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(0), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getMinutes()', - dedent("""\ + celtypes.IntType(0), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getMinutes()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getMinutes(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(31), - "_._(_)"), - ('timestamp("2009-02-13T23:31:30Z").getSeconds()', - dedent("""\ + celtypes.IntType(31), + "_._(_)", + ), + ( + 'timestamp("2009-02-13T23:31:30Z").getSeconds()', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getSeconds(celpy.celtypes.TimestampType(celpy.celtypes.StringType('2009-02-13T23:31:30Z'))))"""), - celtypes.IntType(30), - "_._(_)"), - ('["hello", "world"].contains("hello")', - dedent("""\ + celtypes.IntType(30), + "_._(_)", + ), + ( + '["hello", "world"].contains("hello")', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_contains(celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]), celpy.celtypes.StringType('hello')))"""), - celtypes.BoolType(True), - "_._(_)"), - ('"hello".startsWith("h")', - dedent("""\ + celtypes.BoolType(True), + "_._(_)", + ), + ( + '"hello".startsWith("h")', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_startsWith(celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('h')))"""), - celtypes.BoolType(True), - "_._(_)"), - ('"hello".endsWith("o")', - dedent("""\ + celtypes.BoolType(True), + "_._(_)", + ), + ( + '"hello".endsWith("o")', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_endsWith(celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('o')))"""), - celtypes.BoolType(True), - "_._(_)"), + celtypes.BoolType(True), + "_._(_)", + ), ] member_dot_arg_method_macro = [ - ('["hello", "world"].map(x, x) == ["hello", "world"]', - dedent("""\ + ( + '["hello", "world"].map(x, x) == ["hello", "world"]', + dedent("""\ # member_dot_arg map: ex_10_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')]) ex_10_x = lambda activation: activation.x ex_10 = lambda activation: celpy.evaluation.macro_map(activation, 'x', ex_10_x, ex_10_l) CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_eq(ex_10(activation), celpy.celtypes.ListType([celpy.celtypes.StringType('hello'), celpy.celtypes.StringType('world')])))"""), - celtypes.BoolType(True), - "_._(_)"), - ('[true, false].filter(x, x) == [true]', - dedent("""\ + celtypes.BoolType(True), + "_._(_)", + ), + ( + "[true, false].filter(x, x) == [true]", + dedent("""\ # member_dot_arg filter: ex_10_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.BoolType(True), celpy.celtypes.BoolType(False)]) ex_10_x = lambda activation: activation.x ex_10 = lambda activation: celpy.evaluation.macro_filter(activation, 'x', ex_10_x, ex_10_l) CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_eq(ex_10(activation), celpy.celtypes.ListType([celpy.celtypes.BoolType(True)])))"""), - celtypes.BoolType(True), - "_._(_)"), - ('[42, 0].filter(x, 2 / x > 0) == [42]', - dedent("""\ + celtypes.BoolType(True), + "_._(_)", + ), + ( + "[42, 0].filter(x, 2 / x > 0) == [42]", + dedent("""\ # member_dot_arg filter: ex_10_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.IntType(42), celpy.celtypes.IntType(0)]) ex_10_x = lambda activation: celpy.evaluation.bool_gt(operator.truediv(celpy.celtypes.IntType(2), activation.x), celpy.celtypes.IntType(0)) ex_10 = lambda activation: celpy.evaluation.macro_filter(activation, 'x', ex_10_x, ex_10_l) CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_eq(ex_10(activation), celpy.celtypes.ListType([celpy.celtypes.IntType(42)])))"""), - CELEvalError, - "_._(_)"), - ('[true, false].exists_one(x, x)', - dedent("""\ + CELEvalError, + "_._(_)", + ), + ( + "[true, false].exists_one(x, x)", + dedent("""\ # member_dot_arg exists_one: ex_8_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.BoolType(True), celpy.celtypes.BoolType(False)]) ex_8_x = lambda activation: activation.x ex_8 = lambda activation: celpy.evaluation.macro_exists_one(activation, 'x', ex_8_x, ex_8_l) CEL = celpy.evaluation.result(base_activation, ex_8)"""), - celtypes.BoolType(True), - "_._(_)"), - ('[42, 0].exists_one(x, 2 / x > 0) == true', - dedent("""\ + celtypes.BoolType(True), + "_._(_)", + ), + ( + "[42, 0].exists_one(x, 2 / x > 0) == true", + dedent("""\ # member_dot_arg exists_one: ex_10_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.IntType(42), celpy.celtypes.IntType(0)]) ex_10_x = lambda activation: celpy.evaluation.bool_gt(operator.truediv(celpy.celtypes.IntType(2), activation.x), celpy.celtypes.IntType(0)) ex_10 = lambda activation: celpy.evaluation.macro_exists_one(activation, 'x', ex_10_x, ex_10_l) CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.bool_eq(ex_10(activation), celpy.celtypes.BoolType(True)))"""), - CELEvalError, - "_._(_)"), - ('[true, false].exists(x, x)', - dedent("""\ + CELEvalError, + "_._(_)", + ), + ( + "[true, false].exists(x, x)", + dedent("""\ # member_dot_arg exists: ex_8_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.BoolType(True), celpy.celtypes.BoolType(False)]) ex_8_x = lambda activation: activation.x ex_8 = lambda activation: celpy.evaluation.macro_exists(activation, 'x', ex_8_x, ex_8_l) CEL = celpy.evaluation.result(base_activation, ex_8)"""), - celtypes.BoolType(True), - "_._(_)"), - ('[true, false].all(x, x)', - dedent("""\ + celtypes.BoolType(True), + "_._(_)", + ), + ( + "[true, false].all(x, x)", + dedent("""\ # member_dot_arg all: ex_8_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.BoolType(True), celpy.celtypes.BoolType(False)]) ex_8_x = lambda activation: activation.x ex_8 = lambda activation: celpy.evaluation.macro_all(activation, 'x', ex_8_x, ex_8_l) CEL = celpy.evaluation.result(base_activation, ex_8)"""), - celtypes.BoolType(False), - "_._(_)"), - + celtypes.BoolType(False), + "_._(_)", + ), # Some difficult cases from the acceptance test suite, repeated here to make debugging easier. - ("[1, 'foo', 3].exists(e, e != '1')", - dedent("""\ + ( + "[1, 'foo', 3].exists(e, e != '1')", + dedent("""\ # member_dot_arg exists: ex_8_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.IntType(1), celpy.celtypes.StringType('foo'), celpy.celtypes.IntType(3)]) ex_8_x = lambda activation: celpy.evaluation.bool_ne(activation.e, celpy.celtypes.StringType('1')) ex_8 = lambda activation: celpy.evaluation.macro_exists(activation, 'e', ex_8_x, ex_8_l) CEL = celpy.evaluation.result(base_activation, ex_8) """), - celtypes.BoolType(True), - "_._(_)"), - - ("['foal', 'foo', 'four'].exists_one(n, n.startsWith('fo'))", - dedent(""" + celtypes.BoolType(True), + "_._(_)", + ), + ( + "['foal', 'foo', 'four'].exists_one(n, n.startsWith('fo'))", + dedent(""" # member_dot_arg exists_one: ex_8_l = lambda activation: celpy.celtypes.ListType([celpy.celtypes.StringType('foal'), celpy.celtypes.StringType('foo'), celpy.celtypes.StringType('four')]) ex_8_x = lambda activation: celpy.evaluation.function_startsWith(activation.n, celpy.celtypes.StringType('fo')) ex_8 = lambda activation: celpy.evaluation.macro_exists_one(activation, 'n', ex_8_x, ex_8_l) CEL = celpy.evaluation.result(base_activation, ex_8)"""), - celtypes.BoolType(False), - "_._()"), + celtypes.BoolType(False), + "_._()", + ), ] # Requires variable `duration` amd type `protobuf_message` in activation. dot_ident_arg = [ - ("duration.getMilliseconds()", - dedent("""\ + ( + "duration.getMilliseconds()", + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: celpy.evaluation.function_getMilliseconds(activation.duration))"""), - celtypes.IntType(123123), - '._(_)'), - ('.duration', "CEL = celpy.evaluation.result(base_activation, lambda activation: activation.resolve_variable('duration'))", celtypes.DurationType(seconds=123, nanos=123456789), '_.IDENT'), - ('.protobuf_message().field', - dedent("""\ + celtypes.IntType(123123), + "._(_)", + ), + ( + ".duration", + "CEL = celpy.evaluation.result(base_activation, lambda activation: activation.resolve_variable('duration'))", + celtypes.DurationType(seconds=123, nanos=123456789), + "_.IDENT", + ), + ( + ".protobuf_message().field", + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: activation.resolve_variable('protobuf_message')().get('field'))"""), - celtypes.IntType(42), - '_.IDENT()'), - ('.protobuf_message({"field": 42}).field', - dedent("""\ + celtypes.IntType(42), + "_.IDENT()", + ), + ( + '.protobuf_message({"field": 42}).field', + dedent("""\ CEL = celpy.evaluation.result(base_activation, lambda activation: activation.resolve_variable('protobuf_message')(celpy.celtypes.MapType([(celpy.celtypes.StringType('field'), celpy.celtypes.IntType(42))])).get('field'))"""), - celtypes.IntType(42), - '_.IDENT(_)'), - ('no_arg_function()', - "CEL = celpy.evaluation.result(base_activation, lambda activation: test_transpilation.no_arg_function())", - celtypes.IntType(42), - 'IDENT()'), + celtypes.IntType(42), + "_.IDENT(_)", + ), + ( + "no_arg_function()", + "CEL = celpy.evaluation.result(base_activation, lambda activation: test_transpilation.no_arg_function())", + celtypes.IntType(42), + "IDENT()", + ), ] unbound_names = [ - ("unknown_function(42)", - dedent("""CEL = celpy.evaluation.result(base_activation, lambda activation: CELEvalError('unbound function', KeyError, ('unknown_function',))(celpy.celtypes.IntType(42)))"""), - CELEvalError, - 'IDENT()' - ) + ( + "unknown_function(42)", + dedent( + """CEL = celpy.evaluation.result(base_activation, lambda activation: CELEvalError('unbound function', KeyError, ('unknown_function',))(celpy.celtypes.IntType(42)))""" + ), + CELEvalError, + "IDENT()", + ) ] @@ -623,19 +886,29 @@ def mock_operation(a, b): params=sum( [ literals, - function_params, method_params, macro_has_params, - unary_operator_params, binary_operator_params, short_circuit_params, - member_dot_params, member_item_params, member_object_params, - member_dot_arg_method, member_dot_arg_method_macro, - dot_ident_arg, unbound_names, + function_params, + method_params, + macro_has_params, + unary_operator_params, + binary_operator_params, + short_circuit_params, + member_dot_params, + member_item_params, + member_object_params, + member_dot_arg_method, + member_dot_arg_method_macro, + dot_ident_arg, + unbound_names, ], - [] + [], ), - ids=lambda f: f"{f[3]} Using {f[0]!r} ==> {f[2]}") + ids=lambda f: f"{f[3]} Using {f[0]!r} ==> {f[2]}", +) def binop_example(request): source, expected, value, function_name = request.param return source, expected, value, function_name + @pytest.fixture(scope="module") def transpiling_parser(): # Reset the ClassVar CEL_PARSER. @@ -643,7 +916,10 @@ def transpiling_parser(): parser = celpy.CELParser(tree_class=celpy.evaluation.TranspilerTree) return parser -def test_core_transpile(binop_example, mock_protobuf, mock_activation, mock_functions, transpiling_parser): + +def test_core_transpile( + binop_example, mock_protobuf, mock_activation, mock_functions, transpiling_parser +): source, expected, expected_value, function_name = binop_example tree = transpiling_parser.parse(source) diff --git a/tools/gherkinize.py b/tools/gherkinize.py index 3ec124f..0364713 100644 --- a/tools/gherkinize.py +++ b/tools/gherkinize.py @@ -325,7 +325,7 @@ def from_proto(source: simple_pb2.SimpleTest) -> "Result": elif kind == "eval_error": return Result(kind, CELErrorSet(source.eval_error)) elif kind is None: - return Result("none", None) + return Result("value", CELBool(True)) else: raise NotImplementedError(f"Unable to interpret result kind {kind!r}") @@ -996,6 +996,7 @@ def __init__( source: simple_pb2.SimpleTest, ) -> None: logger.debug(f"Scenario {source.name}") + self.source = source self.name = source.name self.description = source.description self.tags = config.tags_for(feature.name, section.name, source.name) @@ -1018,8 +1019,8 @@ def __init__( self.when(f"CEL expression {source.expr!r} is evaluated") - result = Result.from_proto(source) - self.then(f"{result.kind} is {result}") + self.result = Result.from_proto(source) + self.then(f"{self.result.kind} is {self.result}") def given(self, precondition: str) -> Self: self.preconditions.append(precondition) diff --git a/tools/test_issue_141.py b/tools/test_issue_141.py new file mode 100644 index 0000000..2f63e08 --- /dev/null +++ b/tools/test_issue_141.py @@ -0,0 +1,19 @@ +""" +Tests for Issue #141. + +https://github.com/cloud-custodian/cel-python/issues/141 +""" + +from gherkinize import Result, CELBool + + +def test_assumed_value() -> None: + """ + 197 tests have a similar pattern: + there's no explicit `value` attribute, only 'name' and 'expr'. + + The kind attribute -- ``kind = source.WhichOneof("result_matcher")`` -- is None. + """ + assert Result.from_text_proto_str('expr: "math.greatest(1, 1u) == 1"') == Result( + "value", CELBool(True) + ) diff --git a/tools/test_survey.ipynb b/tools/test_survey.ipynb new file mode 100644 index 0000000..924f027 --- /dev/null +++ b/tools/test_survey.ipynb @@ -0,0 +1,1820 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "ca1b43d654b8d852", + "metadata": { + "collapsed": true + }, + "source": [ + "# Survey the protobuf files used to create unit test cases\n", + "\n", + "This uses parts of ``gherkinize`` to parse the file, so we can look for special cases, patterns, anomalies, and the like.\n", + "\n", + "In this specific notebook, we're looking for test cases where there's no \"value\" attribute.\n", + "This appears to mean the test result is a boolean True value." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "d11b9cdb8014db9b", + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-18T22:57:30.371770Z", + "start_time": "2026-05-18T22:57:30.351677Z" + } + }, + "outputs": [], + "source": [ + "import gherkinize" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "481d3644c5f4ffa1", + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-18T22:57:30.396063Z", + "start_time": "2026-05-18T22:57:30.373861Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{, , , , , }\n" + ] + } + ], + "source": [ + "from pathlib import Path\n", + "import logging\n", + "import contextlib\n", + "\n", + "logging.getLogger().setLevel(logging.ERROR)\n", + "logging.getLogger(\"parso\").setLevel(logging.ERROR)\n", + "print(logging.getLogger().getChildren())\n", + "\n", + "\n", + "config_path = Path.cwd() / \"wip.toml\"\n", + "config = gherkinize.Config(config_path)\n", + "# config.features" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "id": "fbf4d4e631327998", + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-18T23:06:57.426100Z", + "start_time": "2026-05-18T23:06:57.307536Z" + } + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "math_ext greatest_int_result binary_with_decimal\n", + " name: \"binary_with_decimal\"\n", + "expr: \"math.greatest(1, 1.0) == 1\"\n", + "\n", + " [\"name = 'binary_with_decimal'\", \"expr = 'math.greatest(1, 1.0) == 1'\"]\n", + "math_ext greatest_int_result binary_with_uint\n", + " name: \"binary_with_uint\"\n", + "expr: \"math.greatest(1, 1u) == 1\"\n", + "\n", + " [\"name = 'binary_with_uint'\", \"expr = 'math.greatest(1, 1u) == 1'\"]\n", + "math_ext greatest_int_result ternary_same_args\n", + " name: \"ternary_same_args\"\n", + "expr: \"math.greatest(1, 1, 1) == 1\"\n", + "\n", + " [\"name = 'ternary_same_args'\", \"expr = 'math.greatest(1, 1, 1) == 1'\"]\n", + "math_ext greatest_int_result ternary_with_decimal\n", + " name: \"ternary_with_decimal\"\n", + "expr: \"math.greatest(1, 1.0, 1.0) == 1\"\n", + "\n", + " [\"name = 'ternary_with_decimal'\", \"expr = 'math.greatest(1, 1.0, 1.0) == 1'\"]\n", + "math_ext greatest_int_result ternary_with_uint\n", + " name: \"ternary_with_uint\"\n", + "expr: \"math.greatest(1, 1u, 1u) == 1\"\n", + "\n", + " [\"name = 'ternary_with_uint'\", \"expr = 'math.greatest(1, 1u, 1u) == 1'\"]\n", + "math_ext greatest_int_result ternary_first_arg_greatest\n", + " name: \"ternary_first_arg_greatest\"\n", + "expr: \"math.greatest(10, 1, 3) == 10\"\n", + "\n", + " [\"name = 'ternary_first_arg_greatest'\", \"expr = 'math.greatest(10, 1, 3) == 10'\"]\n", + "math_ext greatest_int_result ternary_third_arg_greatest\n", + " name: \"ternary_third_arg_greatest\"\n", + "expr: \"math.greatest(1, 3, 10) == 10\"\n", + "\n", + " [\"name = 'ternary_third_arg_greatest'\", \"expr = 'math.greatest(1, 3, 10) == 10'\"]\n", + "math_ext greatest_int_result ternary_with_negatives\n", + " name: \"ternary_with_negatives\"\n", + "expr: \"math.greatest(-1, -2, -3) == -1\"\n", + "\n", + " [\"name = 'ternary_with_negatives'\", \"expr = 'math.greatest(-1, -2, -3) == -1'\"]\n", + "math_ext greatest_int_result ternary_int_max\n", + " name: \"ternary_int_max\"\n", + "expr: \"math.greatest(9223372036854775807, 1, 5) == 9223372036854775807\"\n", + "\n", + " [\"name = 'ternary_int_max'\", \"expr = 'math.greatest(9223372036854775807, 1, 5) == 9223372036854775807'\"]\n", + "math_ext greatest_int_result ternary_int_min\n", + " name: \"ternary_int_min\"\n", + "expr: \"math.greatest(-9223372036854775807, -1, -5) == -1\"\n", + "\n", + " [\"name = 'ternary_int_min'\", \"expr = 'math.greatest(-9223372036854775807, -1, -5) == -1'\"]\n", + "math_ext greatest_int_result quaternary_mixed\n", + " name: \"quaternary_mixed\"\n", + "expr: \"math.greatest(5.4, 10, 3u, -5.0, 9223372036854775807) == 9223372036854775807\"\n", + "\n", + " [\"name = 'quaternary_mixed'\", \"expr = 'math.greatest(5.4, 10, 3u, -5.0, 9223372036854775807) == 9223372036854775807'\"]\n", + "math_ext greatest_int_result quaternary_mixed_array\n", + " name: \"quaternary_mixed_array\"\n", + "expr: \"math.greatest([5.4, 10, 3u, -5.0, 3.5]) == 10\"\n", + "\n", + " [\"name = 'quaternary_mixed_array'\", \"expr = 'math.greatest([5.4, 10, 3u, -5.0, 3.5]) == 10'\"]\n", + "math_ext greatest_int_result quaternary_mixed_dyn_array\n", + " name: \"quaternary_mixed_dyn_array\"\n", + "expr: \"math.greatest([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10\"\n", + "\n", + " [\"name = 'quaternary_mixed_dyn_array'\", \"expr = 'math.greatest([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10'\"]\n", + "math_ext greatest_double_result binary_with_int\n", + " name: \"binary_with_int\"\n", + "expr: \"math.greatest(1.0, 1) == 1.0\"\n", + "\n", + " [\"name = 'binary_with_int'\", \"expr = 'math.greatest(1.0, 1) == 1.0'\"]\n", + "math_ext greatest_double_result binary_with_uint\n", + " name: \"binary_with_uint\"\n", + "expr: \"math.greatest(1.0, 1u) == 1.0\"\n", + "\n", + " [\"name = 'binary_with_uint'\", \"expr = 'math.greatest(1.0, 1u) == 1.0'\"]\n", + "math_ext greatest_double_result ternary_same_args\n", + " name: \"ternary_same_args\"\n", + "expr: \"math.greatest(1.0, 1.0, 1.0) == 1.0\"\n", + "\n", + " [\"name = 'ternary_same_args'\", \"expr = 'math.greatest(1.0, 1.0, 1.0) == 1.0'\"]\n", + "math_ext greatest_double_result ternary_with_int\n", + " name: \"ternary_with_int\"\n", + "expr: \"math.greatest(1.0, 1, 1) == 1.0\"\n", + "\n", + " [\"name = 'ternary_with_int'\", \"expr = 'math.greatest(1.0, 1, 1) == 1.0'\"]\n", + "math_ext greatest_double_result ternary_with_uint\n", + " name: \"ternary_with_uint\"\n", + "expr: \"math.greatest(1.0, 1u, 1u) == 1.0\"\n", + "\n", + " [\"name = 'ternary_with_uint'\", \"expr = 'math.greatest(1.0, 1u, 1u) == 1.0'\"]\n", + "math_ext greatest_double_result ternary_first_arg_greatest\n", + " name: \"ternary_first_arg_greatest\"\n", + "expr: \"math.greatest(10.5, 1.5, 3.5) == 10.5\"\n", + "\n", + " [\"name = 'ternary_first_arg_greatest'\", \"expr = 'math.greatest(10.5, 1.5, 3.5) == 10.5'\"]\n", + "math_ext greatest_double_result ternary_third_arg_greatest\n", + " name: \"ternary_third_arg_greatest\"\n", + "expr: \"math.greatest(1.5, 3.5, 10.5) == 10.5\"\n", + "\n", + " [\"name = 'ternary_third_arg_greatest'\", \"expr = 'math.greatest(1.5, 3.5, 10.5) == 10.5'\"]\n", + "math_ext greatest_double_result ternary_with_negatives\n", + " name: \"ternary_with_negatives\"\n", + "expr: \"math.greatest(-1.5, -2.5, -3.5) == -1.5\"\n", + "\n", + " [\"name = 'ternary_with_negatives'\", \"expr = 'math.greatest(-1.5, -2.5, -3.5) == -1.5'\"]\n", + "math_ext greatest_double_result ternary_double_max\n", + " name: \"ternary_double_max\"\n", + "expr: \"math.greatest(1.797693e308, 1, 5) == 1.797693e308\"\n", + "\n", + " [\"name = 'ternary_double_max'\", \"expr = 'math.greatest(1.797693e308, 1, 5) == 1.797693e308'\"]\n", + "math_ext greatest_double_result ternary_double_min\n", + " name: \"ternary_double_min\"\n", + "expr: \"math.greatest(-1.797693e308, -1, -5) == -1\"\n", + "\n", + " [\"name = 'ternary_double_min'\", \"expr = 'math.greatest(-1.797693e308, -1, -5) == -1'\"]\n", + "math_ext greatest_double_result quaternary_mixed\n", + " name: \"quaternary_mixed\"\n", + "expr: \"math.greatest(5.4, 10, 3u, -5.0, 1.797693e308) == 1.797693e308\"\n", + "\n", + " [\"name = 'quaternary_mixed'\", \"expr = 'math.greatest(5.4, 10, 3u, -5.0, 1.797693e308) == 1.797693e308'\"]\n", + "math_ext greatest_double_result quaternary_mixed_array\n", + " name: \"quaternary_mixed_array\"\n", + "expr: \"math.greatest([5.4, 10.5, 3u, -5.0, 3.5]) == 10.5\"\n", + "\n", + " [\"name = 'quaternary_mixed_array'\", \"expr = 'math.greatest([5.4, 10.5, 3u, -5.0, 3.5]) == 10.5'\"]\n", + "math_ext greatest_double_result quaternary_mixed_dyn_array\n", + " name: \"quaternary_mixed_dyn_array\"\n", + "expr: \"math.greatest([dyn(5.4), dyn(10.5), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10.5\"\n", + "\n", + " [\"name = 'quaternary_mixed_dyn_array'\", \"expr = 'math.greatest([dyn(5.4), dyn(10.5), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10.5'\"]\n", + "math_ext greatest_uint_result binary_with_decimal\n", + " name: \"binary_with_decimal\"\n", + "expr: \"math.greatest(1u, 1.0) == 1\"\n", + "\n", + " [\"name = 'binary_with_decimal'\", \"expr = 'math.greatest(1u, 1.0) == 1'\"]\n", + "math_ext greatest_uint_result binary_with_int\n", + " name: \"binary_with_int\"\n", + "expr: \"math.greatest(1u, 1) == 1u\"\n", + "\n", + " [\"name = 'binary_with_int'\", \"expr = 'math.greatest(1u, 1) == 1u'\"]\n", + "math_ext greatest_uint_result ternary_same_args\n", + " name: \"ternary_same_args\"\n", + "expr: \"math.greatest(1u, 1u, 1u) == 1u\"\n", + "\n", + " [\"name = 'ternary_same_args'\", \"expr = 'math.greatest(1u, 1u, 1u) == 1u'\"]\n", + "math_ext greatest_uint_result ternary_with_decimal\n", + " name: \"ternary_with_decimal\"\n", + "expr: \"math.greatest(1u, 1.0, 1.0) == 1u\"\n", + "\n", + " [\"name = 'ternary_with_decimal'\", \"expr = 'math.greatest(1u, 1.0, 1.0) == 1u'\"]\n", + "math_ext greatest_uint_result ternary_with_int\n", + " name: \"ternary_with_int\"\n", + "expr: \"math.greatest(1u, 1, 1) == 1u\"\n", + "\n", + " [\"name = 'ternary_with_int'\", \"expr = 'math.greatest(1u, 1, 1) == 1u'\"]\n", + "math_ext greatest_uint_result ternary_first_arg_greatest\n", + " name: \"ternary_first_arg_greatest\"\n", + "expr: \"math.greatest(10u, 1u, 3u) == 10u\"\n", + "\n", + " [\"name = 'ternary_first_arg_greatest'\", \"expr = 'math.greatest(10u, 1u, 3u) == 10u'\"]\n", + "math_ext greatest_uint_result ternary_third_arg_greatest\n", + " name: \"ternary_third_arg_greatest\"\n", + "expr: \"math.greatest(1u, 3u, 10u) == 10u\"\n", + "\n", + " [\"name = 'ternary_third_arg_greatest'\", \"expr = 'math.greatest(1u, 3u, 10u) == 10u'\"]\n", + "math_ext greatest_uint_result ternary_int_max\n", + " name: \"ternary_int_max\"\n", + "expr: \"math.greatest(18446744073709551615u, 1u, 5u) == 18446744073709551615u\"\n", + "\n", + " [\"name = 'ternary_int_max'\", \"expr = 'math.greatest(18446744073709551615u, 1u, 5u) == 18446744073709551615u'\"]\n", + "math_ext greatest_uint_result quaternary_mixed\n", + " name: \"quaternary_mixed\"\n", + "expr: \"math.greatest(5.4, 10, 3u, -5.0, 18446744073709551615u) == 18446744073709551615u\"\n", + "\n", + " [\"name = 'quaternary_mixed'\", \"expr = 'math.greatest(5.4, 10, 3u, -5.0, 18446744073709551615u) == 18446744073709551615u'\"]\n", + "math_ext greatest_uint_result quaternary_mixed_array\n", + " name: \"quaternary_mixed_array\"\n", + "expr: \"math.greatest([5.4, 10u, 3u, -5.0, 3.5]) == 10u\"\n", + "\n", + " [\"name = 'quaternary_mixed_array'\", \"expr = 'math.greatest([5.4, 10u, 3u, -5.0, 3.5]) == 10u'\"]\n", + "math_ext greatest_uint_result quaternary_mixed_dyn_array\n", + " name: \"quaternary_mixed_dyn_array\"\n", + "expr: \"math.greatest([dyn(5.4), dyn(10u), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10u\"\n", + "\n", + " [\"name = 'quaternary_mixed_dyn_array'\", \"expr = 'math.greatest([dyn(5.4), dyn(10u), dyn(3u), dyn(-5.0), dyn(3.5)]) == 10u'\"]\n", + "math_ext least_int_result binary_with_decimal\n", + " name: \"binary_with_decimal\"\n", + "expr: \"math.least(1, 1.0) == 1\"\n", + "\n", + " [\"name = 'binary_with_decimal'\", \"expr = 'math.least(1, 1.0) == 1'\"]\n", + "math_ext least_int_result binary_with_uint\n", + " name: \"binary_with_uint\"\n", + "expr: \"math.least(1, 1u) == 1\"\n", + "\n", + " [\"name = 'binary_with_uint'\", \"expr = 'math.least(1, 1u) == 1'\"]\n", + "math_ext least_int_result ternary_same_args\n", + " name: \"ternary_same_args\"\n", + "expr: \"math.least(1, 1, 1) == 1\"\n", + "\n", + " [\"name = 'ternary_same_args'\", \"expr = 'math.least(1, 1, 1) == 1'\"]\n", + "math_ext least_int_result ternary_with_decimal\n", + " name: \"ternary_with_decimal\"\n", + "expr: \"math.least(1, 1.0, 1.0) == 1\"\n", + "\n", + " [\"name = 'ternary_with_decimal'\", \"expr = 'math.least(1, 1.0, 1.0) == 1'\"]\n", + "math_ext least_int_result ternary_with_uint\n", + " name: \"ternary_with_uint\"\n", + "expr: \"math.least(1, 1u, 1u) == 1\"\n", + "\n", + " [\"name = 'ternary_with_uint'\", \"expr = 'math.least(1, 1u, 1u) == 1'\"]\n", + "math_ext least_int_result ternary_first_arg_least\n", + " name: \"ternary_first_arg_least\"\n", + "expr: \"math.least(0, 1, 3) == 0\"\n", + "\n", + " [\"name = 'ternary_first_arg_least'\", \"expr = 'math.least(0, 1, 3) == 0'\"]\n", + "math_ext least_int_result ternary_third_arg_least\n", + " name: \"ternary_third_arg_least\"\n", + "expr: \"math.least(1, 3, 0) == 0\"\n", + "\n", + " [\"name = 'ternary_third_arg_least'\", \"expr = 'math.least(1, 3, 0) == 0'\"]\n", + "math_ext least_int_result ternary_with_negatives\n", + " name: \"ternary_with_negatives\"\n", + "expr: \"math.least(-1, -2, -3) == -3\"\n", + "\n", + " [\"name = 'ternary_with_negatives'\", \"expr = 'math.least(-1, -2, -3) == -3'\"]\n", + "math_ext least_int_result ternary_int_max\n", + " name: \"ternary_int_max\"\n", + "expr: \"math.least(9223372036854775807, 1, 5) == 1\"\n", + "\n", + " [\"name = 'ternary_int_max'\", \"expr = 'math.least(9223372036854775807, 1, 5) == 1'\"]\n", + "math_ext least_int_result ternary_int_min\n", + " name: \"ternary_int_min\"\n", + "expr: \"math.least(-9223372036854775808, -1, -5) == -9223372036854775808\"\n", + "\n", + " [\"name = 'ternary_int_min'\", \"expr = 'math.least(-9223372036854775808, -1, -5) == -9223372036854775808'\"]\n", + "math_ext least_int_result quaternary_mixed\n", + " name: \"quaternary_mixed\"\n", + "expr: \"math.least(5.4, 10, 3u, -5.0, 9223372036854775807) == -5.0\"\n", + "\n", + " [\"name = 'quaternary_mixed'\", \"expr = 'math.least(5.4, 10, 3u, -5.0, 9223372036854775807) == -5.0'\"]\n", + "math_ext least_int_result quaternary_mixed_array\n", + " name: \"quaternary_mixed_array\"\n", + "expr: \"math.least([5.4, 10, 3u, -5.0, 3.5]) == -5.0\"\n", + "\n", + " [\"name = 'quaternary_mixed_array'\", \"expr = 'math.least([5.4, 10, 3u, -5.0, 3.5]) == -5.0'\"]\n", + "math_ext least_int_result quaternary_mixed_dyn_array\n", + " name: \"quaternary_mixed_dyn_array\"\n", + "expr: \"math.least([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)]) == -5.0\"\n", + "\n", + " [\"name = 'quaternary_mixed_dyn_array'\", \"expr = 'math.least([dyn(5.4), dyn(10), dyn(3u), dyn(-5.0), dyn(3.5)]) == -5.0'\"]\n", + "math_ext least_double_result binary_with_int\n", + " name: \"binary_with_int\"\n", + "expr: \"math.least(1.0, 1) == 1\"\n", + "\n", + " [\"name = 'binary_with_int'\", \"expr = 'math.least(1.0, 1) == 1'\"]\n", + "math_ext least_double_result binary_with_uint\n", + " name: \"binary_with_uint\"\n", + "expr: \"math.least(1, 1u) == 1\"\n", + "\n", + " [\"name = 'binary_with_uint'\", \"expr = 'math.least(1, 1u) == 1'\"]\n", + "math_ext least_double_result ternary_same_args\n", + " name: \"ternary_same_args\"\n", + "expr: \"math.least(1.5, 1.5, 1.5) == 1.5\"\n", + "\n", + " [\"name = 'ternary_same_args'\", \"expr = 'math.least(1.5, 1.5, 1.5) == 1.5'\"]\n", + "math_ext least_double_result ternary_with_int\n", + " name: \"ternary_with_int\"\n", + "expr: \"math.least(1.0, 1, 1) == 1.0\"\n", + "\n", + " [\"name = 'ternary_with_int'\", \"expr = 'math.least(1.0, 1, 1) == 1.0'\"]\n", + "math_ext least_double_result ternary_with_uint\n", + " name: \"ternary_with_uint\"\n", + "expr: \"math.least(1.0, 1u, 1u) == 1\"\n", + "\n", + " [\"name = 'ternary_with_uint'\", \"expr = 'math.least(1.0, 1u, 1u) == 1'\"]\n", + "math_ext least_double_result ternary_first_arg_least\n", + " name: \"ternary_first_arg_least\"\n", + "expr: \"math.least(0.5, 1.5, 3.5) == 0.5\"\n", + "\n", + " [\"name = 'ternary_first_arg_least'\", \"expr = 'math.least(0.5, 1.5, 3.5) == 0.5'\"]\n", + "math_ext least_double_result ternary_third_arg_least\n", + " name: \"ternary_third_arg_least\"\n", + "expr: \"math.least(1.5, 3.5, 0.5) == 0.5\"\n", + "\n", + " [\"name = 'ternary_third_arg_least'\", \"expr = 'math.least(1.5, 3.5, 0.5) == 0.5'\"]\n", + "math_ext least_double_result ternary_with_negatives\n", + " name: \"ternary_with_negatives\"\n", + "expr: \"math.least(-1.5, -2.5, -3.5) == -3.5\"\n", + "\n", + " [\"name = 'ternary_with_negatives'\", \"expr = 'math.least(-1.5, -2.5, -3.5) == -3.5'\"]\n", + "math_ext least_double_result ternary_double_max\n", + " name: \"ternary_double_max\"\n", + "expr: \"math.least(1.797693e308, 1, 5) == 1\"\n", + "\n", + " [\"name = 'ternary_double_max'\", \"expr = 'math.least(1.797693e308, 1, 5) == 1'\"]\n", + "math_ext least_double_result ternary_double_min\n", + " name: \"ternary_double_min\"\n", + "expr: \"math.least(-1.797693e308, -1, -5) == -1.797693e308\"\n", + "\n", + " [\"name = 'ternary_double_min'\", \"expr = 'math.least(-1.797693e308, -1, -5) == -1.797693e308'\"]\n", + "math_ext least_double_result quaternary_mixed\n", + " name: \"quaternary_mixed\"\n", + "expr: \"math.least(5.4, 10, 3u, -5.0, 1.797693e308) == -5.0\"\n", + "\n", + " [\"name = 'quaternary_mixed'\", \"expr = 'math.least(5.4, 10, 3u, -5.0, 1.797693e308) == -5.0'\"]\n", + "math_ext least_double_result quaternary_mixed_array\n", + " name: \"quaternary_mixed_array\"\n", + "expr: \"math.least([5.4, 10.5, 3u, -5.0, 3.5]) == -5.0\"\n", + "\n", + " [\"name = 'quaternary_mixed_array'\", \"expr = 'math.least([5.4, 10.5, 3u, -5.0, 3.5]) == -5.0'\"]\n", + "math_ext least_double_result quaternary_mixed_dyn_array\n", + " name: \"quaternary_mixed_dyn_array\"\n", + "expr: \"math.least([dyn(5.4), dyn(10.5), dyn(3u), dyn(-5.0), dyn(3.5)]) == -5.0\"\n", + "\n", + " [\"name = 'quaternary_mixed_dyn_array'\", \"expr = 'math.least([dyn(5.4), dyn(10.5), dyn(3u), dyn(-5.0), dyn(3.5)]) == -5.0'\"]\n", + "math_ext least_uint_result binary_with_decimal\n", + " name: \"binary_with_decimal\"\n", + "expr: \"math.least(1u, 1.0) == 1u\"\n", + "\n", + " [\"name = 'binary_with_decimal'\", \"expr = 'math.least(1u, 1.0) == 1u'\"]\n", + "math_ext least_uint_result binary_with_int\n", + " name: \"binary_with_int\"\n", + "expr: \"math.least(1u, 1) == 1u\"\n", + "\n", + " [\"name = 'binary_with_int'\", \"expr = 'math.least(1u, 1) == 1u'\"]\n", + "math_ext least_uint_result ternary_same_args\n", + " name: \"ternary_same_args\"\n", + "expr: \"math.least(1u, 1u, 1u) == 1u\"\n", + "\n", + " [\"name = 'ternary_same_args'\", \"expr = 'math.least(1u, 1u, 1u) == 1u'\"]\n", + "math_ext least_uint_result ternary_with_decimal\n", + " name: \"ternary_with_decimal\"\n", + "expr: \"math.least(1u, 1.0, 1.0) == 1u\"\n", + "\n", + " [\"name = 'ternary_with_decimal'\", \"expr = 'math.least(1u, 1.0, 1.0) == 1u'\"]\n", + "math_ext least_uint_result ternary_with_int\n", + " name: \"ternary_with_int\"\n", + "expr: \"math.least(1u, 1, 1) == 1u\"\n", + "\n", + " [\"name = 'ternary_with_int'\", \"expr = 'math.least(1u, 1, 1) == 1u'\"]\n", + "math_ext least_uint_result ternary_first_arg_least\n", + " name: \"ternary_first_arg_least\"\n", + "expr: \"math.least(1u, 10u, 3u) == 1u\"\n", + "\n", + " [\"name = 'ternary_first_arg_least'\", \"expr = 'math.least(1u, 10u, 3u) == 1u'\"]\n", + "math_ext least_uint_result ternary_third_arg_least\n", + " name: \"ternary_third_arg_least\"\n", + "expr: \"math.least(10u, 3u, 1u) == 1u\"\n", + "\n", + " [\"name = 'ternary_third_arg_least'\", \"expr = 'math.least(10u, 3u, 1u) == 1u'\"]\n", + "math_ext least_uint_result ternary_uint_max\n", + " name: \"ternary_uint_max\"\n", + "expr: \"math.least(18446744073709551615u, 1u, 5u) == 1u\"\n", + "\n", + " [\"name = 'ternary_uint_max'\", \"expr = 'math.least(18446744073709551615u, 1u, 5u) == 1u'\"]\n", + "math_ext least_uint_result quaternary_mixed\n", + " name: \"quaternary_mixed\"\n", + "expr: \"math.least(5.4, 10, 3u, 1u, 18446744073709551615u) == 1u\"\n", + "\n", + " [\"name = 'quaternary_mixed'\", \"expr = 'math.least(5.4, 10, 3u, 1u, 18446744073709551615u) == 1u'\"]\n", + "math_ext least_uint_result quaternary_mixed_array\n", + " name: \"quaternary_mixed_array\"\n", + "expr: \"math.least([5.4, 10u, 3u, 1u, 3.5]) == 1u\"\n", + "\n", + " [\"name = 'quaternary_mixed_array'\", \"expr = 'math.least([5.4, 10u, 3u, 1u, 3.5]) == 1u'\"]\n", + "math_ext least_uint_result quaternary_mixed_dyn_array\n", + " name: \"quaternary_mixed_dyn_array\"\n", + "expr: \"math.least([dyn(5.4), dyn(10u), dyn(3u), dyn(1u), dyn(3.5)]) == 1u\"\n", + "\n", + " [\"name = 'quaternary_mixed_dyn_array'\", \"expr = 'math.least([dyn(5.4), dyn(10u), dyn(3u), dyn(1u), dyn(3.5)]) == 1u'\"]\n", + "math_ext round nan\n", + " name: \"nan\"\n", + "expr: \"math.isNaN(math.round(0.0/0.0))\"\n", + "\n", + " [\"name = 'nan'\", \"expr = 'math.isNaN(math.round(0.0/0.0))'\"]\n", + "math_ext trunc nan\n", + " name: \"nan\"\n", + "expr: \"math.isNaN(math.trunc(0.0/0.0))\"\n", + "\n", + " [\"name = 'nan'\", \"expr = 'math.isNaN(math.trunc(0.0/0.0))'\"]\n", + "math_ext isNaN true\n", + " name: \"true\"\n", + "expr: \"math.isNaN(0.0/0.0)\"\n", + "\n", + " [\"name = 'true'\", \"expr = 'math.isNaN(0.0/0.0)'\"]\n", + "math_ext isNaN false\n", + " name: \"false\"\n", + "expr: \"!math.isNaN(1.0/0.0)\"\n", + "\n", + " [\"name = 'false'\", \"expr = '!math.isNaN(1.0/0.0)'\"]\n", + "math_ext isInf true\n", + " name: \"true\"\n", + "expr: \"math.isInf(1.0/0.0)\"\n", + "\n", + " [\"name = 'true'\", \"expr = 'math.isInf(1.0/0.0)'\"]\n", + "math_ext isInf false\n", + " name: \"false\"\n", + "expr: \"!math.isInf(0.0/0.0)\"\n", + "\n", + " [\"name = 'false'\", \"expr = '!math.isInf(0.0/0.0)'\"]\n", + "math_ext isFinite true\n", + " name: \"true\"\n", + "expr: \"math.isFinite(1.0/1.5)\"\n", + "\n", + " [\"name = 'true'\", \"expr = 'math.isFinite(1.0/1.5)'\"]\n", + "math_ext isFinite false_nan\n", + " name: \"false_nan\"\n", + "expr: \"!math.isFinite(0.0/0.0)\"\n", + "\n", + " [\"name = 'false_nan'\", \"expr = '!math.isFinite(0.0/0.0)'\"]\n", + "math_ext isFinite false_inf\n", + " name: \"false_inf\"\n", + "expr: \"!math.isFinite(-1.0/0.0)\"\n", + "\n", + " [\"name = 'false_inf'\", \"expr = '!math.isFinite(-1.0/0.0)'\"]\n", + "proto2 extensions_has package_scoped_int32\n", + " name: \"package_scoped_int32\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.int32_ext`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\300>*\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_int32'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.int32_ext`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\300>*\"\\n }\\n}\\n}']\n", + "proto2 extensions_has package_scoped_nested_ext\n", + " name: \"package_scoped_nested_ext\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.nested_ext`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\312>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_nested_ext'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.nested_ext`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\312>\\\\000\"\\n }\\n}\\n}']\n", + "proto2 extensions_has package_scoped_test_all_types_ext\n", + " name: \"package_scoped_test_all_types_ext\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.test_all_types_ext`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\322>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_test_all_types_ext'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.test_all_types_ext`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\322>\\\\000\"\\n }\\n}\\n}']\n", + "proto2 extensions_has package_scoped_test_all_types_nested_enum_ext\n", + " name: \"package_scoped_test_all_types_nested_enum_ext\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.nested_enum_ext`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\330>\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_test_all_types_nested_enum_ext'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.nested_enum_ext`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\330>\\\\001\"\\n }\\n}\\n}']\n", + "proto2 extensions_has package_scoped_repeated_test_all_types\n", + " name: \"package_scoped_repeated_test_all_types\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.repeated_test_all_types`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\342>\\002\\020\\001\\342>\\002h\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_repeated_test_all_types'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.repeated_test_all_types`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\342>\\\\002\\\\020\\\\001\\\\342>\\\\002h\\\\001\"\\n }\\n}\\n}']\n", + "proto2 extensions_has message_scoped_int64\n", + " name: \"message_scoped_int64\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\350>*\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_int64'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\350>*\"\\n }\\n}\\n}']\n", + "proto2 extensions_has message_scoped_nested_ext\n", + " name: \"message_scoped_nested_ext\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\362>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_nested_ext'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\362>\\\\000\"\\n }\\n}\\n}']\n", + "proto2 extensions_has message_scoped_nested_enum_ext\n", + " name: \"message_scoped_nested_enum_ext\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\370>\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_nested_enum_ext'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\370>\\\\001\"\\n }\\n}\\n}']\n", + "proto2 extensions_has message_scoped_repeated_test_all_types\n", + " name: \"message_scoped_repeated_test_all_types\"\n", + "expr: \"has(msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types`)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\202?\\002\\020\\001\\202?\\002h\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_repeated_test_all_types'\", \"expr = 'has(msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types`)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\202?\\\\002\\\\020\\\\001\\\\202?\\\\002h\\\\001\"\\n }\\n}\\n}']\n", + "proto2 extensions_get package_scoped_int32\n", + " name: \"package_scoped_int32\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.int32_ext` == 42\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\300>*\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_int32'\", \"expr = 'msg.`cel.expr.conformance.proto2.int32_ext` == 42'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\300>*\"\\n }\\n}\\n}']\n", + "proto2 extensions_get package_scoped_nested_ext\n", + " name: \"package_scoped_nested_ext\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.nested_ext` == cel.expr.conformance.proto2.TestAllTypes{}\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\312>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_nested_ext'\", \"expr = 'msg.`cel.expr.conformance.proto2.nested_ext` == cel.expr.conformance.proto2.TestAllTypes{}'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\312>\\\\000\"\\n }\\n}\\n}']\n", + "proto2 extensions_get package_scoped_test_all_types_ext\n", + " name: \"package_scoped_test_all_types_ext\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.test_all_types_ext` == cel.expr.conformance.proto2.TestAllTypes{}\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\322>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_test_all_types_ext'\", \"expr = 'msg.`cel.expr.conformance.proto2.test_all_types_ext` == cel.expr.conformance.proto2.TestAllTypes{}'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\322>\\\\000\"\\n }\\n}\\n}']\n", + "proto2 extensions_get package_scoped_test_all_types_nested_enum_ext\n", + " name: \"package_scoped_test_all_types_nested_enum_ext\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.nested_enum_ext` == cel.expr.conformance.proto2.TestAllTypes.NestedEnum.BAR\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\330>\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_test_all_types_nested_enum_ext'\", \"expr = 'msg.`cel.expr.conformance.proto2.nested_enum_ext` == cel.expr.conformance.proto2.TestAllTypes.NestedEnum.BAR'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\330>\\\\001\"\\n }\\n}\\n}']\n", + "proto2 extensions_get package_scoped_repeated_test_all_types\n", + " name: \"package_scoped_repeated_test_all_types\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.repeated_test_all_types` == [cel.expr.conformance.proto2.TestAllTypes{single_int64: 1}, cel.expr.conformance.proto2.TestAllTypes{single_bool: true}]\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\342>\\002\\020\\001\\342>\\002h\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_repeated_test_all_types'\", \"expr = 'msg.`cel.expr.conformance.proto2.repeated_test_all_types` == [cel.expr.conformance.proto2.TestAllTypes{single_int64: 1}, cel.expr.conformance.proto2.TestAllTypes{single_bool: true}]'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\342>\\\\002\\\\020\\\\001\\\\342>\\\\002h\\\\001\"\\n }\\n}\\n}']\n", + "proto2 extensions_get message_scoped_int64\n", + " name: \"message_scoped_int64\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext` == 42\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\350>*\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_int64'\", \"expr = 'msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext` == 42'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\350>*\"\\n }\\n}\\n}']\n", + "proto2 extensions_get message_scoped_nested_ext\n", + " name: \"message_scoped_nested_ext\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext` == cel.expr.conformance.proto2.TestAllTypes{}\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\362>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_nested_ext'\", \"expr = 'msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext` == cel.expr.conformance.proto2.TestAllTypes{}'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\362>\\\\000\"\\n }\\n}\\n}']\n", + "proto2 extensions_get message_scoped_nested_enum_ext\n", + " name: \"message_scoped_nested_enum_ext\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext` == cel.expr.conformance.proto2.TestAllTypes.NestedEnum.BAR\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\370>\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_nested_enum_ext'\", \"expr = 'msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext` == cel.expr.conformance.proto2.TestAllTypes.NestedEnum.BAR'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\370>\\\\001\"\\n }\\n}\\n}']\n", + "proto2 extensions_get message_scoped_repeated_test_all_types\n", + " name: \"message_scoped_repeated_test_all_types\"\n", + "expr: \"msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types` == [cel.expr.conformance.proto2.TestAllTypes{single_int64: 1}, cel.expr.conformance.proto2.TestAllTypes{single_bool: true}]\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\202?\\002\\020\\001\\202?\\002h\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_repeated_test_all_types'\", \"expr = 'msg.`cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types` == [cel.expr.conformance.proto2.TestAllTypes{single_int64: 1}, cel.expr.conformance.proto2.TestAllTypes{single_bool: true}]'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\202?\\\\002\\\\020\\\\001\\\\202?\\\\002h\\\\001\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext package_scoped_int32\n", + " name: \"package_scoped_int32\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.int32_ext)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\300>*\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_int32'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.int32_ext)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\300>*\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext package_scoped_nested_ext\n", + " name: \"package_scoped_nested_ext\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.nested_ext)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\312>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_nested_ext'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.nested_ext)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\312>\\\\000\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext package_scoped_test_all_types_ext\n", + " name: \"package_scoped_test_all_types_ext\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.test_all_types_ext)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\322>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_test_all_types_ext'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.test_all_types_ext)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\322>\\\\000\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext package_scoped_test_all_types_nested_enum_ext\n", + " name: \"package_scoped_test_all_types_nested_enum_ext\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.nested_enum_ext)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\330>\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_test_all_types_nested_enum_ext'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.nested_enum_ext)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\330>\\\\001\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext package_scoped_repeated_test_all_types\n", + " name: \"package_scoped_repeated_test_all_types\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.repeated_test_all_types)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\342>\\002\\020\\001\\342>\\002h\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_repeated_test_all_types'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.repeated_test_all_types)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\342>\\\\002\\\\020\\\\001\\\\342>\\\\002h\\\\001\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext message_scoped_int64\n", + " name: \"message_scoped_int64\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\350>*\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_int64'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\350>*\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext message_scoped_nested_ext\n", + " name: \"message_scoped_nested_ext\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\362>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_nested_ext'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\362>\\\\000\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext message_scoped_nested_enum_ext\n", + " name: \"message_scoped_nested_enum_ext\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\370>\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_nested_enum_ext'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\370>\\\\001\"\\n }\\n}\\n}']\n", + "proto2_ext has_ext message_scoped_repeated_test_all_types\n", + " name: \"message_scoped_repeated_test_all_types\"\n", + "expr: \"proto.hasExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types)\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\202?\\002\\020\\001\\202?\\002h\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_repeated_test_all_types'\", \"expr = 'proto.hasExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types)'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\202?\\\\002\\\\020\\\\001\\\\202?\\\\002h\\\\001\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext package_scoped_int32\n", + " name: \"package_scoped_int32\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.int32_ext) == 42\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\300>*\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_int32'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.int32_ext) == 42'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\300>*\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext package_scoped_nested_ext\n", + " name: \"package_scoped_nested_ext\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.nested_ext) == cel.expr.conformance.proto2.TestAllTypes{}\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\312>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_nested_ext'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.nested_ext) == cel.expr.conformance.proto2.TestAllTypes{}'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\312>\\\\000\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext package_scoped_test_all_types_ext\n", + " name: \"package_scoped_test_all_types_ext\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.test_all_types_ext) == cel.expr.conformance.proto2.TestAllTypes{}\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\322>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_test_all_types_ext'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.test_all_types_ext) == cel.expr.conformance.proto2.TestAllTypes{}'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\322>\\\\000\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext package_scoped_test_all_types_nested_enum_ext\n", + " name: \"package_scoped_test_all_types_nested_enum_ext\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.nested_enum_ext) == cel.expr.conformance.proto2.TestAllTypes.NestedEnum.BAR\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\330>\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_test_all_types_nested_enum_ext'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.nested_enum_ext) == cel.expr.conformance.proto2.TestAllTypes.NestedEnum.BAR'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\330>\\\\001\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext package_scoped_repeated_test_all_types\n", + " name: \"package_scoped_repeated_test_all_types\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.repeated_test_all_types) == [cel.expr.conformance.proto2.TestAllTypes{single_int64: 1}, cel.expr.conformance.proto2.TestAllTypes{single_bool: true}]\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\342>\\002\\020\\001\\342>\\002h\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'package_scoped_repeated_test_all_types'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.repeated_test_all_types) == [cel.expr.conformance.proto2.TestAllTypes{single_int64: 1}, cel.expr.conformance.proto2.TestAllTypes{single_bool: true}]'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\342>\\\\002\\\\020\\\\001\\\\342>\\\\002h\\\\001\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext message_scoped_int64\n", + " name: \"message_scoped_int64\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext) == 42\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\350>*\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_int64'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.int64_ext) == 42'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\350>*\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext message_scoped_nested_ext\n", + " name: \"message_scoped_nested_ext\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext) == cel.expr.conformance.proto2.TestAllTypes{}\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\362>\\000\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_nested_ext'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_nested_ext) == cel.expr.conformance.proto2.TestAllTypes{}'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\362>\\\\000\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext message_scoped_nested_enum_ext\n", + " name: \"message_scoped_nested_enum_ext\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext) == cel.expr.conformance.proto2.TestAllTypes.NestedEnum.BAR\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\370>\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_nested_enum_ext'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.nested_enum_ext) == cel.expr.conformance.proto2.TestAllTypes.NestedEnum.BAR'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\370>\\\\001\"\\n }\\n}\\n}']\n", + "proto2_ext get_ext message_scoped_repeated_test_all_types\n", + " name: \"message_scoped_repeated_test_all_types\"\n", + "expr: \"proto.getExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types) == [cel.expr.conformance.proto2.TestAllTypes{single_int64: 1}, cel.expr.conformance.proto2.TestAllTypes{single_bool: true}]\"\n", + "type_env {\n", + " name: \"msg\"\n", + " ident {\n", + " type {\n", + " message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\n", + " }\n", + " }\n", + "}\n", + "bindings {\n", + " key: \"msg\"\n", + " value {\n", + " value {\n", + " object_value {\n", + " type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\n", + " value: \"\\202?\\002\\020\\001\\202?\\002h\\001\"\n", + " }\n", + " }\n", + " }\n", + "}\n", + "\n", + " [\"name = 'message_scoped_repeated_test_all_types'\", \"expr = 'proto.getExt(msg, cel.expr.conformance.proto2.Proto2ExtensionScopedMessage.message_scoped_repeated_test_all_types) == [cel.expr.conformance.proto2.TestAllTypes{single_int64: 1}, cel.expr.conformance.proto2.TestAllTypes{single_bool: true}]'\", 'type_env = [name: \"msg\"\\nident {\\n type {\\n message_type: \"cel.expr.conformance.proto2.TestAllTypes\"\\n }\\n}\\n]', 'bindings = {\\'msg\\': value {\\n object_value {\\n type_url: \"type.googleapis.com/cel.expr.conformance.proto2.TestAllTypes\"\\n value: \"\\\\202?\\\\002\\\\020\\\\001\\\\202?\\\\002h\\\\001\"\\n }\\n}\\n}']\n", + "string_ext char_at multiple\n", + " name: \"multiple\"\n", + "expr: \"\\'©αT\\'.charAt(0) == \\'©\\' && \\'©αT\\'.charAt(1) == \\'α\\' && \\'©αT\\'.charAt(2) == \\'T\\'\"\n", + "\n", + " [\"name = 'multiple'\", 'expr = \"\\'©αT\\'.charAt(0) == \\'©\\' && \\'©αT\\'.charAt(1) == \\'α\\' && \\'©αT\\'.charAt(2) == \\'T\\'\"']\n", + "string_ext index_of nomatch\n", + " name: \"nomatch\"\n", + "expr: \"\\'tacocat\\'.indexOf(\\'none\\') == -1\"\n", + "\n", + " [\"name = 'nomatch'\", 'expr = \"\\'tacocat\\'.indexOf(\\'none\\') == -1\"']\n", + "string_ext index_of empty_index\n", + " name: \"empty_index\"\n", + "expr: \"\\'tacocat\\'.indexOf(\\'\\', 3) == 3\"\n", + "\n", + " [\"name = 'empty_index'\", 'expr = \"\\'tacocat\\'.indexOf(\\'\\', 3) == 3\"']\n", + "string_ext index_of char_index\n", + " name: \"char_index\"\n", + "expr: \"\\'tacocat\\'.indexOf(\\'a\\', 3) == 5\"\n", + "\n", + " [\"name = 'char_index'\", 'expr = \"\\'tacocat\\'.indexOf(\\'a\\', 3) == 5\"']\n", + "string_ext index_of string_index\n", + " name: \"string_index\"\n", + "expr: \"\\'tacocat\\'.indexOf(\\'at\\', 3) == 5\"\n", + "\n", + " [\"name = 'string_index'\", 'expr = \"\\'tacocat\\'.indexOf(\\'at\\', 3) == 5\"']\n", + "string_ext index_of unicode_char\n", + " name: \"unicode_char\"\n", + "expr: \"\\'ta©o©αT\\'.indexOf(\\'©\\') == 2\"\n", + "\n", + " [\"name = 'unicode_char'\", 'expr = \"\\'ta©o©αT\\'.indexOf(\\'©\\') == 2\"']\n", + "string_ext index_of unicode_char_index\n", + " name: \"unicode_char_index\"\n", + "expr: \"\\'ta©o©αT\\'.indexOf(\\'©\\', 3) == 4\"\n", + "\n", + " [\"name = 'unicode_char_index'\", 'expr = \"\\'ta©o©αT\\'.indexOf(\\'©\\', 3) == 4\"']\n", + "string_ext index_of unicode_string_index\n", + " name: \"unicode_string_index\"\n", + "expr: \"\\'ta©o©αT\\'.indexOf(\\'©αT\\', 3) == 4\"\n", + "\n", + " [\"name = 'unicode_string_index'\", 'expr = \"\\'ta©o©αT\\'.indexOf(\\'©αT\\', 3) == 4\"']\n", + "string_ext index_of unicode_string_nomatch_index\n", + " name: \"unicode_string_nomatch_index\"\n", + "expr: \"\\'ta©o©αT\\'.indexOf(\\'©α\\', 5) == -1\"\n", + "\n", + " [\"name = 'unicode_string_nomatch_index'\", 'expr = \"\\'ta©o©αT\\'.indexOf(\\'©α\\', 5) == -1\"']\n", + "string_ext index_of char_index\n", + " name: \"char_index\"\n", + "expr: \"\\'ijk\\'.indexOf(\\'k\\') == 2\"\n", + "\n", + " [\"name = 'char_index'\", 'expr = \"\\'ijk\\'.indexOf(\\'k\\') == 2\"']\n", + "string_ext index_of string_with_space_fullmatch\n", + " name: \"string_with_space_fullmatch\"\n", + "expr: \"\\'hello wello\\'.indexOf(\\'hello wello\\') == 0\"\n", + "\n", + " [\"name = 'string_with_space_fullmatch'\", 'expr = \"\\'hello wello\\'.indexOf(\\'hello wello\\') == 0\"']\n", + "string_ext index_of string_with_space_index\n", + " name: \"string_with_space_index\"\n", + "expr: \"\\'hello wello\\'.indexOf(\\'ello\\', 6) == 7\"\n", + "\n", + " [\"name = 'string_with_space_index'\", 'expr = \"\\'hello wello\\'.indexOf(\\'ello\\', 6) == 7\"']\n", + "string_ext index_of string_nomatch_index\n", + " name: \"string_nomatch_index\"\n", + "expr: \"\\'hello wello\\'.indexOf(\\'elbo room!!\\') == -1\"\n", + "\n", + " [\"name = 'string_nomatch_index'\", 'expr = \"\\'hello wello\\'.indexOf(\\'elbo room!!\\') == -1\"']\n", + "string_ext last_index_of empty_string\n", + " name: \"empty_string\"\n", + "expr: \"\\'\\'.lastIndexOf(\\'@@\\') == -1\"\n", + "\n", + " [\"name = 'empty_string'\", 'expr = \"\\'\\'.lastIndexOf(\\'@@\\') == -1\"']\n", + "string_ext last_index_of empty_argument\n", + " name: \"empty_argument\"\n", + "expr: \"\\'tacocat\\'.lastIndexOf(\\'\\') == 7\"\n", + "\n", + " [\"name = 'empty_argument'\", 'expr = \"\\'tacocat\\'.lastIndexOf(\\'\\') == 7\"']\n", + "string_ext last_index_of string\n", + " name: \"string\"\n", + "expr: \"\\'tacocat\\'.lastIndexOf(\\'at\\') == 5\"\n", + "\n", + " [\"name = 'string'\", 'expr = \"\\'tacocat\\'.lastIndexOf(\\'at\\') == 5\"']\n", + "string_ext last_index_of string_nomatch\n", + " name: \"string_nomatch\"\n", + "expr: \"\\'tacocat\\'.lastIndexOf(\\'none\\') == -1\"\n", + "\n", + " [\"name = 'string_nomatch'\", 'expr = \"\\'tacocat\\'.lastIndexOf(\\'none\\') == -1\"']\n", + "string_ext last_index_of empty_index\n", + " name: \"empty_index\"\n", + "expr: \"\\'tacocat\\'.lastIndexOf(\\'\\', 3) == 3\"\n", + "\n", + " [\"name = 'empty_index'\", 'expr = \"\\'tacocat\\'.lastIndexOf(\\'\\', 3) == 3\"']\n", + "string_ext last_index_of char_index\n", + " name: \"char_index\"\n", + "expr: \"\\'tacocat\\'.lastIndexOf(\\'a\\', 3) == 1\"\n", + "\n", + " [\"name = 'char_index'\", 'expr = \"\\'tacocat\\'.lastIndexOf(\\'a\\', 3) == 1\"']\n", + "string_ext last_index_of unicode_char\n", + " name: \"unicode_char\"\n", + "expr: \"\\'ta©o©αT\\'.lastIndexOf(\\'©\\') == 4\"\n", + "\n", + " [\"name = 'unicode_char'\", 'expr = \"\\'ta©o©αT\\'.lastIndexOf(\\'©\\') == 4\"']\n", + "string_ext last_index_of unicode_char_index\n", + " name: \"unicode_char_index\"\n", + "expr: \"\\'ta©o©αT\\'.lastIndexOf(\\'©\\', 3) == 2\"\n", + "\n", + " [\"name = 'unicode_char_index'\", 'expr = \"\\'ta©o©αT\\'.lastIndexOf(\\'©\\', 3) == 2\"']\n", + "string_ext last_index_of unicode_string_index\n", + " name: \"unicode_string_index\"\n", + "expr: \"\\'ta©o©αT\\'.lastIndexOf(\\'©α\\', 4) == 4\"\n", + "\n", + " [\"name = 'unicode_string_index'\", 'expr = \"\\'ta©o©αT\\'.lastIndexOf(\\'©α\\', 4) == 4\"']\n", + "string_ext last_index_of string_with_space_string_index\n", + " name: \"string_with_space_string_index\"\n", + "expr: \"\\'hello wello\\'.lastIndexOf(\\'ello\\', 6) == 1\"\n", + "\n", + " [\"name = 'string_with_space_string_index'\", 'expr = \"\\'hello wello\\'.lastIndexOf(\\'ello\\', 6) == 1\"']\n", + "string_ext last_index_of string_with_space_string_nomatch\n", + " name: \"string_with_space_string_nomatch\"\n", + "expr: \"\\'hello wello\\'.lastIndexOf(\\'low\\') == -1\"\n", + "\n", + " [\"name = 'string_with_space_string_nomatch'\", 'expr = \"\\'hello wello\\'.lastIndexOf(\\'low\\') == -1\"']\n", + "string_ext last_index_of string_with_space_string_with_space_nomatch\n", + " name: \"string_with_space_string_with_space_nomatch\"\n", + "expr: \"\\'hello wello\\'.lastIndexOf(\\'elbo room!!\\') == -1\"\n", + "\n", + " [\"name = 'string_with_space_string_with_space_nomatch'\", 'expr = \"\\'hello wello\\'.lastIndexOf(\\'elbo room!!\\') == -1\"']\n", + "string_ext last_index_of string_with_space_fullmatch\n", + " name: \"string_with_space_fullmatch\"\n", + "expr: \"\\'hello wello\\'.lastIndexOf(\\'hello wello\\') == 0\"\n", + "\n", + " [\"name = 'string_with_space_fullmatch'\", 'expr = \"\\'hello wello\\'.lastIndexOf(\\'hello wello\\') == 0\"']\n", + "string_ext last_index_of repeated_string\n", + " name: \"repeated_string\"\n", + "expr: \"\\'bananananana\\'.lastIndexOf(\\'nana\\', 7) == 6\"\n", + "\n", + " [\"name = 'repeated_string'\", 'expr = \"\\'bananananana\\'.lastIndexOf(\\'nana\\', 7) == 6\"']\n", + "string_ext ascii_casing lowerascii\n", + " name: \"lowerascii\"\n", + "expr: \"\\'TacoCat\\'.lowerAscii() == \\'tacocat\\'\"\n", + "\n", + " [\"name = 'lowerascii'\", 'expr = \"\\'TacoCat\\'.lowerAscii() == \\'tacocat\\'\"']\n", + "string_ext ascii_casing lowerascii_unicode\n", + " name: \"lowerascii_unicode\"\n", + "expr: \"\\'TacoCÆt\\'.lowerAscii() == \\'tacocÆt\\'\"\n", + "\n", + " [\"name = 'lowerascii_unicode'\", 'expr = \"\\'TacoCÆt\\'.lowerAscii() == \\'tacocÆt\\'\"']\n", + "string_ext ascii_casing lowerascii_unicode_with_space\n", + " name: \"lowerascii_unicode_with_space\"\n", + "expr: \"\\'TacoCÆt Xii\\'.lowerAscii() == \\'tacocÆt xii\\'\"\n", + "\n", + " [\"name = 'lowerascii_unicode_with_space'\", 'expr = \"\\'TacoCÆt Xii\\'.lowerAscii() == \\'tacocÆt xii\\'\"']\n", + "string_ext ascii_casing upperascii\n", + " name: \"upperascii\"\n", + "expr: \"\\'tacoCat\\'.upperAscii() == \\'TACOCAT\\'\"\n", + "\n", + " [\"name = 'upperascii'\", 'expr = \"\\'tacoCat\\'.upperAscii() == \\'TACOCAT\\'\"']\n", + "string_ext ascii_casing upperascii_unicode\n", + " name: \"upperascii_unicode\"\n", + "expr: \"\\'tacoCαt\\'.upperAscii() == \\'TACOCαT\\'\"\n", + "\n", + " [\"name = 'upperascii_unicode'\", 'expr = \"\\'tacoCαt\\'.upperAscii() == \\'TACOCαT\\'\"']\n", + "string_ext ascii_casing upperascii_unicode_with_space\n", + " name: \"upperascii_unicode_with_space\"\n", + "expr: \"\\'TacoCÆt Xii\\'.upperAscii() == \\'TACOCÆT XII\\'\"\n", + "\n", + " [\"name = 'upperascii_unicode_with_space'\", 'expr = \"\\'TacoCÆt Xii\\'.upperAscii() == \\'TACOCÆT XII\\'\"']\n", + "string_ext replace no_placeholder\n", + " name: \"no_placeholder\"\n", + "expr: \"\\'12 days 12 hours\\'.replace(\\'{0}\\', \\'2\\') == \\'12 days 12 hours\\'\"\n", + "\n", + " [\"name = 'no_placeholder'\", 'expr = \"\\'12 days 12 hours\\'.replace(\\'{0}\\', \\'2\\') == \\'12 days 12 hours\\'\"']\n", + "string_ext replace basic\n", + " name: \"basic\"\n", + "expr: \"\\'{0} days {0} hours\\'.replace(\\'{0}\\', \\'2\\') == \\'2 days 2 hours\\'\"\n", + "\n", + " [\"name = 'basic'\", 'expr = \"\\'{0} days {0} hours\\'.replace(\\'{0}\\', \\'2\\') == \\'2 days 2 hours\\'\"']\n", + "string_ext replace chained\n", + " name: \"chained\"\n", + "expr: \"\\'{0} days {0} hours\\'.replace(\\'{0}\\', \\'2\\', 1).replace(\\'{0}\\', \\'23\\') == \\'2 days 23 hours\\'\"\n", + "\n", + " [\"name = 'chained'\", 'expr = \"\\'{0} days {0} hours\\'.replace(\\'{0}\\', \\'2\\', 1).replace(\\'{0}\\', \\'23\\') == \\'2 days 23 hours\\'\"']\n", + "string_ext replace unicode\n", + " name: \"unicode\"\n", + "expr: \"\\'1 ©αT taco\\'.replace(\\'αT\\', \\'o©α\\') == \\'1 ©o©α taco\\'\"\n", + "\n", + " [\"name = 'unicode'\", 'expr = \"\\'1 ©αT taco\\'.replace(\\'αT\\', \\'o©α\\') == \\'1 ©o©α taco\\'\"']\n", + "string_ext split empty\n", + " name: \"empty\"\n", + "expr: \"\\'hello world\\'.split(\\' \\') == [\\'hello\\', \\'world\\']\"\n", + "\n", + " [\"name = 'empty'\", 'expr = \"\\'hello world\\'.split(\\' \\') == [\\'hello\\', \\'world\\']\"']\n", + "string_ext split zero_limit\n", + " name: \"zero_limit\"\n", + "expr: \"\\'hello world events!\\'.split(\\' \\', 0) == []\"\n", + "\n", + " [\"name = 'zero_limit'\", 'expr = \"\\'hello world events!\\'.split(\\' \\', 0) == []\"']\n", + "string_ext split one_limit\n", + " name: \"one_limit\"\n", + "expr: \"\\'hello world events!\\'.split(\\' \\', 1) == [\\'hello world events!\\']\"\n", + "\n", + " [\"name = 'one_limit'\", 'expr = \"\\'hello world events!\\'.split(\\' \\', 1) == [\\'hello world events!\\']\"']\n", + "string_ext split unicode_negative_limit\n", + " name: \"unicode_negative_limit\"\n", + "expr: \"\\'o©o©o©o\\'.split(\\'©\\', -1) == [\\'o\\', \\'o\\', \\'o\\', \\'o\\']\"\n", + "\n", + " [\"name = 'unicode_negative_limit'\", 'expr = \"\\'o©o©o©o\\'.split(\\'©\\', -1) == [\\'o\\', \\'o\\', \\'o\\', \\'o\\']\"']\n", + "string_ext substring start\n", + " name: \"start\"\n", + "expr: \"\\'tacocat\\'.substring(4) == \\'cat\\'\"\n", + "\n", + " [\"name = 'start'\", 'expr = \"\\'tacocat\\'.substring(4) == \\'cat\\'\"']\n", + "string_ext substring start_with_max_length\n", + " name: \"start_with_max_length\"\n", + "expr: \"\\'tacocat\\'.substring(7) == \\'\\'\"\n", + "\n", + " [\"name = 'start_with_max_length'\", 'expr = \"\\'tacocat\\'.substring(7) == \\'\\'\"']\n", + "string_ext substring start_and_end\n", + " name: \"start_and_end\"\n", + "expr: \"\\'tacocat\\'.substring(0, 4) == \\'taco\\'\"\n", + "\n", + " [\"name = 'start_and_end'\", 'expr = \"\\'tacocat\\'.substring(0, 4) == \\'taco\\'\"']\n", + "string_ext substring start_and_end_equal_value\n", + " name: \"start_and_end_equal_value\"\n", + "expr: \"\\'tacocat\\'.substring(4, 4) == \\'\\'\"\n", + "\n", + " [\"name = 'start_and_end_equal_value'\", 'expr = \"\\'tacocat\\'.substring(4, 4) == \\'\\'\"']\n", + "string_ext substring unicode_start_and_end\n", + " name: \"unicode_start_and_end\"\n", + "expr: \"\\'ta©o©αT\\'.substring(2, 6) == \\'©o©α\\'\"\n", + "\n", + " [\"name = 'unicode_start_and_end'\", 'expr = \"\\'ta©o©αT\\'.substring(2, 6) == \\'©o©α\\'\"']\n", + "string_ext substring unicode_start_and_end_equal_value\n", + " name: \"unicode_start_and_end_equal_value\"\n", + "expr: \"\\'ta©o©αT\\'.substring(7, 7) == \\'\\'\"\n", + "\n", + " [\"name = 'unicode_start_and_end_equal_value'\", 'expr = \"\\'ta©o©αT\\'.substring(7, 7) == \\'\\'\"']\n", + "string_ext trim blank_spaces_escaped_chars\n", + " name: \"blank_spaces_escaped_chars\"\n", + "expr: \"\\' \\\\f\\\\n\\\\r\\\\t\\\\vtext \\'.trim() == \\'text\\'\"\n", + "\n", + " [\"name = 'blank_spaces_escaped_chars'\", 'expr = \"\\' \\\\\\\\f\\\\\\\\n\\\\\\\\r\\\\\\\\t\\\\\\\\vtext \\'.trim() == \\'text\\'\"']\n", + "string_ext trim unicode_space_chars_1\n", + " name: \"unicode_space_chars_1\"\n", + "expr: \"\\'\\\\u0085\\\\u00a0\\\\u1680text\\'.trim() == \\'text\\'\"\n", + "\n", + " [\"name = 'unicode_space_chars_1'\", 'expr = \"\\'\\\\\\\\u0085\\\\\\\\u00a0\\\\\\\\u1680text\\'.trim() == \\'text\\'\"']\n", + "string_ext trim unicode_space_chars_2\n", + " name: \"unicode_space_chars_2\"\n", + "expr: \"\\'text\\\\u2000\\\\u2001\\\\u2002\\\\u2003\\\\u2004\\\\u2004\\\\u2006\\\\u2007\\\\u2008\\\\u2009\\'.trim() == \\'text\\'\"\n", + "\n", + " [\"name = 'unicode_space_chars_2'\", 'expr = \"\\'text\\\\\\\\u2000\\\\\\\\u2001\\\\\\\\u2002\\\\\\\\u2003\\\\\\\\u2004\\\\\\\\u2004\\\\\\\\u2006\\\\\\\\u2007\\\\\\\\u2008\\\\\\\\u2009\\'.trim() == \\'text\\'\"']\n", + "string_ext trim unicode_space_chars_3\n", + " name: \"unicode_space_chars_3\"\n", + "expr: \"\\'\\\\u200atext\\\\u2028\\\\u2029\\\\u202F\\\\u205F\\\\u3000\\'.trim() == \\'text\\'\"\n", + "\n", + " [\"name = 'unicode_space_chars_3'\", 'expr = \"\\'\\\\\\\\u200atext\\\\\\\\u2028\\\\\\\\u2029\\\\\\\\u202F\\\\\\\\u205F\\\\\\\\u3000\\'.trim() == \\'text\\'\"']\n", + "string_ext trim unicode_no_trim\n", + " name: \"unicode_no_trim\"\n", + "expr: \"\\'\\\\u180etext\\\\u200b\\\\u200c\\\\u200d\\\\u2060\\\\ufeff\\'.trim() == \\'\\\\u180etext\\\\u200b\\\\u200c\\\\u200d\\\\u2060\\\\ufeff\\'\"\n", + "\n", + " [\"name = 'unicode_no_trim'\", 'expr = \"\\'\\\\\\\\u180etext\\\\\\\\u200b\\\\\\\\u200c\\\\\\\\u200d\\\\\\\\u2060\\\\\\\\ufeff\\'.trim() == \\'\\\\\\\\u180etext\\\\\\\\u200b\\\\\\\\u200c\\\\\\\\u200d\\\\\\\\u2060\\\\\\\\ufeff\\'\"']\n", + "string_ext join empty_separator\n", + " name: \"empty_separator\"\n", + "expr: \"[\\'x\\', \\'y\\'].join() == \\'xy\\'\"\n", + "\n", + " [\"name = 'empty_separator'\", 'expr = \"[\\'x\\', \\'y\\'].join() == \\'xy\\'\"']\n", + "string_ext join dash_separator\n", + " name: \"dash_separator\"\n", + "expr: \"[\\'x\\', \\'y\\'].join(\\'-\\') == \\'x-y\\'\"\n", + "\n", + " [\"name = 'dash_separator'\", 'expr = \"[\\'x\\', \\'y\\'].join(\\'-\\') == \\'x-y\\'\"']\n", + "string_ext join empty_string_empty_separator\n", + " name: \"empty_string_empty_separator\"\n", + "expr: \"[].join() == \\'\\'\"\n", + "\n", + " [\"name = 'empty_string_empty_separator'\", 'expr = \"[].join() == \\'\\'\"']\n", + "string_ext join empty_string_dash_separator\n", + " name: \"empty_string_dash_separator\"\n", + "expr: \"[].join(\\'-\\') == \\'\\'\"\n", + "\n", + " [\"name = 'empty_string_dash_separator'\", 'expr = \"[].join(\\'-\\') == \\'\\'\"']\n", + "string_ext quote multiline\n", + " name: \"multiline\"\n", + "expr: \"strings.quote(\\\"first\\\\nsecond\\\") == \\\"\\\\\\\"first\\\\\\\\nsecond\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'multiline'\", 'expr = \\'strings.quote(\"first\\\\\\\\nsecond\") == \"\\\\\\\\\"first\\\\\\\\\\\\\\\\nsecond\\\\\\\\\"\"\\'']\n", + "string_ext quote escaped\n", + " name: \"escaped\"\n", + "expr: \"strings.quote(\\\"bell\\\\a\\\") == \\\"\\\\\\\"bell\\\\\\\\a\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'escaped'\", 'expr = \\'strings.quote(\"bell\\\\\\\\a\") == \"\\\\\\\\\"bell\\\\\\\\\\\\\\\\a\\\\\\\\\"\"\\'']\n", + "string_ext quote backspace\n", + " name: \"backspace\"\n", + "expr: \"strings.quote(\\\"\\\\bbackspace\\\") == \\\"\\\\\\\"\\\\\\\\bbackspace\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'backspace'\", 'expr = \\'strings.quote(\"\\\\\\\\bbackspace\") == \"\\\\\\\\\"\\\\\\\\\\\\\\\\bbackspace\\\\\\\\\"\"\\'']\n", + "string_ext quote form_feed\n", + " name: \"form_feed\"\n", + "expr: \"strings.quote(\\\"\\\\fform feed\\\") == \\\"\\\\\\\"\\\\\\\\fform feed\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'form_feed'\", 'expr = \\'strings.quote(\"\\\\\\\\fform feed\") == \"\\\\\\\\\"\\\\\\\\\\\\\\\\fform feed\\\\\\\\\"\"\\'']\n", + "string_ext quote carriage_return\n", + " name: \"carriage_return\"\n", + "expr: \"strings.quote(\\\"carriage \\\\r return\\\") == \\\"\\\\\\\"carriage \\\\\\\\r return\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'carriage_return'\", 'expr = \\'strings.quote(\"carriage \\\\\\\\r return\") == \"\\\\\\\\\"carriage \\\\\\\\\\\\\\\\r return\\\\\\\\\"\"\\'']\n", + "string_ext quote horizontal_tab\n", + " name: \"horizontal_tab\"\n", + "expr: \"strings.quote(\\\"horizontal tab\\\\t\\\") == \\\"\\\\\\\"horizontal tab\\\\\\\\t\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'horizontal_tab'\", 'expr = \\'strings.quote(\"horizontal tab\\\\\\\\t\") == \"\\\\\\\\\"horizontal tab\\\\\\\\\\\\\\\\t\\\\\\\\\"\"\\'']\n", + "string_ext quote vertical_tab\n", + " name: \"vertical_tab\"\n", + "expr: \"strings.quote(\\\"vertical \\\\v tab\\\") == \\\"\\\\\\\"vertical \\\\\\\\v tab\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'vertical_tab'\", 'expr = \\'strings.quote(\"vertical \\\\\\\\v tab\") == \"\\\\\\\\\"vertical \\\\\\\\\\\\\\\\v tab\\\\\\\\\"\"\\'']\n", + "string_ext quote double_slash\n", + " name: \"double_slash\"\n", + "expr: \"strings.quote(\\\"double \\\\\\\\\\\\\\\\ slash\\\") == \\\"\\\\\\\"double \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ slash\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'double_slash'\", 'expr = \\'strings.quote(\"double \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ slash\") == \"\\\\\\\\\"double \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ slash\\\\\\\\\"\"\\'']\n", + "string_ext quote two_escape_sequences\n", + " name: \"two_escape_sequences\"\n", + "expr: \"strings.quote(\\\"two escape sequences \\\\\\\\a\\\\\\\\n\\\") == \\\"\\\\\\\"two escape sequences \\\\\\\\\\\\\\\\a\\\\\\\\\\\\\\\\n\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'two_escape_sequences'\", 'expr = \\'strings.quote(\"two escape sequences \\\\\\\\\\\\\\\\a\\\\\\\\\\\\\\\\n\") == \"\\\\\\\\\"two escape sequences \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\a\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\n\\\\\\\\\"\"\\'']\n", + "string_ext quote verbatim\n", + " name: \"verbatim\"\n", + "expr: \"strings.quote(\\\"verbatim\\\") == \\\"\\\\\\\"verbatim\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'verbatim'\", 'expr = \\'strings.quote(\"verbatim\") == \"\\\\\\\\\"verbatim\\\\\\\\\"\"\\'']\n", + "string_ext quote ends_with\n", + " name: \"ends_with\"\n", + "expr: \"strings.quote(\\\"ends with \\\\\\\\\\\") == \\\"\\\\\\\"ends with \\\\\\\\\\\\\\\\\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'ends_with'\", 'expr = \\'strings.quote(\"ends with \\\\\\\\\\\\\\\\\") == \"\\\\\\\\\"ends with \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\"\"\\'']\n", + "string_ext quote starts_with\n", + " name: \"starts_with\"\n", + "expr: \"strings.quote(\\\"\\\\\\\\ starts with\\\") == \\\"\\\\\\\"\\\\\\\\\\\\\\\\ starts with\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'starts_with'\", 'expr = \\'strings.quote(\"\\\\\\\\\\\\\\\\ starts with\") == \"\\\\\\\\\"\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ starts with\\\\\\\\\"\"\\'']\n", + "string_ext quote printable_unicode\n", + " name: \"printable_unicode\"\n", + "expr: \"strings.quote(\\\"printable unicode😀\\\") == \\\"\\\\\\\"printable unicode😀\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'printable_unicode'\", 'expr = \\'strings.quote(\"printable unicode😀\") == \"\\\\\\\\\"printable unicode😀\\\\\\\\\"\"\\'']\n", + "string_ext quote mid_string_quote\n", + " name: \"mid_string_quote\"\n", + "expr: \"strings.quote(\\\"mid string \\\\\\\" quote\\\") == \\\"\\\\\\\"mid string \\\\\\\\\\\\\\\" quote\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'mid_string_quote'\", 'expr = \\'strings.quote(\"mid string \\\\\\\\\" quote\") == \"\\\\\\\\\"mid string \\\\\\\\\\\\\\\\\\\\\\\\\" quote\\\\\\\\\"\"\\'']\n", + "string_ext quote single_quote_with_double_quote\n", + " name: \"single_quote_with_double_quote\"\n", + "expr: \"strings.quote(\\'single-quote with \\\"double quote\\\"\\') == \\\"\\\\\\\"single-quote with \\\\\\\\\\\\\\\"double quote\\\\\\\\\\\\\\\"\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'single_quote_with_double_quote'\", 'expr = \\'strings.quote(\\\\\\'single-quote with \"double quote\"\\\\\\') == \"\\\\\\\\\"single-quote with \\\\\\\\\\\\\\\\\\\\\\\\\"double quote\\\\\\\\\\\\\\\\\\\\\\\\\"\\\\\\\\\"\"\\'']\n", + "string_ext quote size_unicode_char\n", + " name: \"size_unicode_char\"\n", + "expr: \"strings.quote(\\\"size(\\'ÿ\\')\\\") == \\\"\\\\\\\"size(\\'ÿ\\')\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'size_unicode_char'\", 'expr = \\'strings.quote(\"size(\\\\\\'ÿ\\\\\\')\") == \"\\\\\\\\\"size(\\\\\\'ÿ\\\\\\')\\\\\\\\\"\"\\'']\n", + "string_ext quote size_unicode_string\n", + " name: \"size_unicode_string\"\n", + "expr: \"strings.quote(\\\"size(\\'πέντε\\')\\\") == \\\"\\\\\\\"size(\\'πέντε\\')\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'size_unicode_string'\", 'expr = \\'strings.quote(\"size(\\\\\\'πέντε\\\\\\')\") == \"\\\\\\\\\"size(\\\\\\'πέντε\\\\\\')\\\\\\\\\"\"\\'']\n", + "string_ext quote unicode\n", + " name: \"unicode\"\n", + "expr: \"strings.quote(\\\"завтра\\\") == \\\"\\\\\\\"завтра\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'unicode'\", 'expr = \\'strings.quote(\"завтра\") == \"\\\\\\\\\"завтра\\\\\\\\\"\"\\'']\n", + "string_ext quote unicode_2\n", + " name: \"unicode_2\"\n", + "expr: \"strings.quote(\\\"ta©o©αT\\\") == \\\"\\\\\\\"ta©o©αT\\\\\\\"\\\"\"\n", + "\n", + " [\"name = 'unicode_2'\", 'expr = \\'strings.quote(\"ta©o©αT\") == \"\\\\\\\\\"ta©o©αT\\\\\\\\\"\"\\'']\n", + "string_ext reverse empty\n", + " name: \"empty\"\n", + "expr: \"\\'\\'.reverse() == \\'\\'\"\n", + "\n", + " [\"name = 'empty'\", 'expr = \"\\'\\'.reverse() == \\'\\'\"']\n", + "string_ext reverse single_character\n", + " name: \"single_character\"\n", + "expr: \"\\'☺\\'.reverse() == \\'☺\\'\"\n", + "\n", + " [\"name = 'single_character'\", 'expr = \"\\'☺\\'.reverse() == \\'☺\\'\"']\n", + "string_ext reverse multiple\n", + " name: \"multiple\"\n", + "expr: \"\\'Ta©oCαt\\'.reverse() == \\'tαCo©aT\\'\"\n", + "\n", + " [\"name = 'multiple'\", 'expr = \"\\'Ta©oCαt\\'.reverse() == \\'tαCo©aT\\'\"']\n", + "197 tests with where `value = True` is assumed, not stated.\n" + ] + } + ], + "source": [ + "count = 0\n", + "cel_spec_path = Path.cwd().parent.parent / \"cel-spec\" / \"tests\" / \"simple\" / \"testdata\"\n", + "for test_case in sorted(cel_spec_path.glob(\"*.textproto\")):\n", + " with contextlib.redirect_stderr(None):\n", + " feature = gherkinize.Feature.from_text_proto(config, test_case)\n", + " # print(feature.name)\n", + " for section in feature.sections:\n", + " # print(\" \", section.name)\n", + " for scenario in section.scenarios:\n", + " if scenario.result.value is None:\n", + " if scenario.steps[-1] != \"Then none is None\":\n", + " raise Exception(\"Not a 'none is None' case\")\n", + " print(\n", + " feature.name,\n", + " section.name,\n", + " scenario.name,\n", + " )\n", + " print(\" \", scenario.source)\n", + " print(\n", + " \" \",\n", + " [\n", + " f\"{desc.name} = {value!r}\"\n", + " for desc, value in scenario.source.ListFields()\n", + " ],\n", + " )\n", + " count += 1\n", + "print(f\"{count} tests with where `value = True` is assumed, not stated.\")" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "id": "dadf4d4f703083ba", + "metadata": { + "ExecuteTime": { + "end_time": "2026-05-18T22:57:30.530028Z", + "start_time": "2026-05-18T22:57:30.521917Z" + } + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 2 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython2", + "version": "2.7.6" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/type_check/lineprecision.txt b/type_check/lineprecision.txt index 68b41d1..c1b5a13 100644 --- a/type_check/lineprecision.txt +++ b/type_check/lineprecision.txt @@ -1,13 +1,14 @@ Name Lines Precise Imprecise Any Empty Unanalyzed ------------------------------------------------------------------- -celpy 353 79 12 4 258 0 +celpy 357 79 12 4 262 0 celpy.__main__ 551 243 14 61 233 0 celpy.adapter 163 34 3 9 111 6 celpy.c7nlib 1663 344 16 152 1151 0 celpy.celparser 411 137 68 23 183 0 celpy.celtypes 1500 396 15 238 813 38 celpy.evaluation 3876 1131 254 243 2230 18 -gherkinize 1142 544 12 85 481 20 +gherkinize 1143 545 12 85 481 20 test_gherkinize 5581 5018 135 0 428 0 +test_issue_141 19 4 0 0 15 0 xlate 0 0 0 0 0 0 xlate.c7n_to_cel 1736 393 103 136 1098 6 diff --git a/uv.lock b/uv.lock index 2800ec8..88bf211 100644 --- a/uv.lock +++ b/uv.lock @@ -17,6 +17,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7e/b3/6b4067be973ae96ba0d615946e314c5ae35f9f993eca561b356540bb0c2b/alabaster-1.0.0-py3-none-any.whl", hash = "sha256:fc6786402dc3fcb2de3cabd5fe455a2db534b371124f1f21de8731783dec828b", size = 13929, upload-time = "2024-07-26T18:15:02.05Z" }, ] +[[package]] +name = "appnope" +version = "0.1.4" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/35/5d/752690df9ef5b76e169e68d6a129fa6d08a7100ca7f754c89495db3c6019/appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", size = 4170, upload-time = "2024-02-06T09:43:11.258Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/81/29/5ecc3a15d5a33e31b26c11426c45c501e439cb865d0bff96315d86443b78/appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c", size = 4321, upload-time = "2024-02-06T09:43:09.663Z" }, +] + [[package]] name = "ast-serialize" version = "0.5.0" @@ -57,6 +66,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/45/19/cc8bd127d28a43da249aa955cfd164cf8fd534e79e42cea96c4854d72fd0/ast_serialize-0.5.0-cp39-abi3-win_arm64.whl", hash = "sha256:92a31c9c20d25a076edaeec76b128a3535d74a24f340b9a8a7e96c9b86dc9642", size = 1081181, upload-time = "2026-05-17T17:48:28.122Z" }, ] +[[package]] +name = "asttokens" +version = "3.0.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/be/a5/8e3f9b6771b0b408517c82d97aed8f2036509bc247d46114925e32fe33f0/asttokens-3.0.1.tar.gz", hash = "sha256:71a4ee5de0bde6a31d64f6b13f2293ac190344478f081c3d1bccfcf5eacb0cb7", size = 62308, upload-time = "2025-11-15T16:43:48.578Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d2/39/e7eaf1799466a4aef85b6a4fe7bd175ad2b1c6345066aa33f1f58d4b18d0/asttokens-3.0.1-py3-none-any.whl", hash = "sha256:15a3ebc0f43c2d0a50eeafea25e19046c68398e487b9f1f5b517f7c0f40f976a", size = 27047, upload-time = "2025-11-15T16:43:16.109Z" }, +] + [[package]] name = "babel" version = "2.17.0" @@ -77,7 +95,6 @@ dependencies = [ { name = "parse" }, { name = "parse-type" }, { name = "six" }, - { name = "tomli", version = "2.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '0'" }, { name = "tomli", version = "2.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/62/51/f37442fe648b3e35ecf69bee803fa6db3f74c5b46d6c882d0bc5654185a2/behave-1.3.3.tar.gz", hash = "sha256:2b8f4b64ed2ea756a5a2a73e23defc1c4631e9e724c499e46661778453ebaf51", size = 892639, upload-time = "2025-09-04T12:12:02.531Z" } @@ -104,7 +121,6 @@ dependencies = [ { name = "lark" }, { name = "pendulum" }, { name = "pyyaml" }, - { name = "tomli", version = "2.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '0'" }, { name = "tomli", version = "2.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, ] @@ -115,6 +131,7 @@ dev = [ { name = "google-cel-spec-protocolbuffers-pyi" }, { name = "google-cel-spec-protocolbuffers-python" }, { name = "google-re2-stubs" }, + { name = "ipykernel" }, { name = "jinja2" }, { name = "mypy" }, { name = "protobuf" }, @@ -151,6 +168,7 @@ dev = [ { name = "google-cel-spec-protocolbuffers-pyi" }, { name = "google-cel-spec-protocolbuffers-python" }, { name = "google-re2-stubs" }, + { name = "ipykernel", specifier = ">=7.2.0" }, { name = "jinja2", specifier = ">=3.1.6" }, { name = "mypy", specifier = ">=2.1.0" }, { name = "protobuf", specifier = ">=6.33.5" }, @@ -177,6 +195,88 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", hash = "sha256:30350364dfe371162649852c63336a15c70c6510c2ad5015b21c2345311805f3", size = 159618, upload-time = "2025-04-26T02:12:27.662Z" }, ] +[[package]] +name = "cffi" +version = "2.0.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pycparser", marker = "implementation_name != 'PyPy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/eb/56/b1ba7935a17738ae8453301356628e8147c79dbb825bcbc73dc7401f9846/cffi-2.0.0.tar.gz", hash = "sha256:44d1b5909021139fe36001ae048dbdde8214afa20200eda0f64c068cac5d5529", size = 523588, upload-time = "2025-09-08T23:24:04.541Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/93/d7/516d984057745a6cd96575eea814fe1edd6646ee6efd552fb7b0921dec83/cffi-2.0.0-cp310-cp310-macosx_10_13_x86_64.whl", hash = "sha256:0cf2d91ecc3fcc0625c2c530fe004f82c110405f101548512cce44322fa8ac44", size = 184283, upload-time = "2025-09-08T23:22:08.01Z" }, + { url = "https://files.pythonhosted.org/packages/9e/84/ad6a0b408daa859246f57c03efd28e5dd1b33c21737c2db84cae8c237aa5/cffi-2.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f73b96c41e3b2adedc34a7356e64c8eb96e03a3782b535e043a986276ce12a49", size = 180504, upload-time = "2025-09-08T23:22:10.637Z" }, + { url = "https://files.pythonhosted.org/packages/50/bd/b1a6362b80628111e6653c961f987faa55262b4002fcec42308cad1db680/cffi-2.0.0-cp310-cp310-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:53f77cbe57044e88bbd5ed26ac1d0514d2acf0591dd6bb02a3ae37f76811b80c", size = 208811, upload-time = "2025-09-08T23:22:12.267Z" }, + { url = "https://files.pythonhosted.org/packages/4f/27/6933a8b2562d7bd1fb595074cf99cc81fc3789f6a6c05cdabb46284a3188/cffi-2.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:3e837e369566884707ddaf85fc1744b47575005c0a229de3327f8f9a20f4efeb", size = 216402, upload-time = "2025-09-08T23:22:13.455Z" }, + { url = "https://files.pythonhosted.org/packages/05/eb/b86f2a2645b62adcfff53b0dd97e8dfafb5c8aa864bd0d9a2c2049a0d551/cffi-2.0.0-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:5eda85d6d1879e692d546a078b44251cdd08dd1cfb98dfb77b670c97cee49ea0", size = 203217, upload-time = "2025-09-08T23:22:14.596Z" }, + { url = "https://files.pythonhosted.org/packages/9f/e0/6cbe77a53acf5acc7c08cc186c9928864bd7c005f9efd0d126884858a5fe/cffi-2.0.0-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9332088d75dc3241c702d852d4671613136d90fa6881da7d770a483fd05248b4", size = 203079, upload-time = "2025-09-08T23:22:15.769Z" }, + { url = "https://files.pythonhosted.org/packages/98/29/9b366e70e243eb3d14a5cb488dfd3a0b6b2f1fb001a203f653b93ccfac88/cffi-2.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fc7de24befaeae77ba923797c7c87834c73648a05a4bde34b3b7e5588973a453", size = 216475, upload-time = "2025-09-08T23:22:17.427Z" }, + { url = "https://files.pythonhosted.org/packages/21/7a/13b24e70d2f90a322f2900c5d8e1f14fa7e2a6b3332b7309ba7b2ba51a5a/cffi-2.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:cf364028c016c03078a23b503f02058f1814320a56ad535686f90565636a9495", size = 218829, upload-time = "2025-09-08T23:22:19.069Z" }, + { url = "https://files.pythonhosted.org/packages/60/99/c9dc110974c59cc981b1f5b66e1d8af8af764e00f0293266824d9c4254bc/cffi-2.0.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e11e82b744887154b182fd3e7e8512418446501191994dbf9c9fc1f32cc8efd5", size = 211211, upload-time = "2025-09-08T23:22:20.588Z" }, + { url = "https://files.pythonhosted.org/packages/49/72/ff2d12dbf21aca1b32a40ed792ee6b40f6dc3a9cf1644bd7ef6e95e0ac5e/cffi-2.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:8ea985900c5c95ce9db1745f7933eeef5d314f0565b27625d9a10ec9881e1bfb", size = 218036, upload-time = "2025-09-08T23:22:22.143Z" }, + { url = "https://files.pythonhosted.org/packages/e2/cc/027d7fb82e58c48ea717149b03bcadcbdc293553edb283af792bd4bcbb3f/cffi-2.0.0-cp310-cp310-win32.whl", hash = "sha256:1f72fb8906754ac8a2cc3f9f5aaa298070652a0ffae577e0ea9bd480dc3c931a", size = 172184, upload-time = "2025-09-08T23:22:23.328Z" }, + { url = "https://files.pythonhosted.org/packages/33/fa/072dd15ae27fbb4e06b437eb6e944e75b068deb09e2a2826039e49ee2045/cffi-2.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:b18a3ed7d5b3bd8d9ef7a8cb226502c6bf8308df1525e1cc676c3680e7176739", size = 182790, upload-time = "2025-09-08T23:22:24.752Z" }, + { url = "https://files.pythonhosted.org/packages/12/4a/3dfd5f7850cbf0d06dc84ba9aa00db766b52ca38d8b86e3a38314d52498c/cffi-2.0.0-cp311-cp311-macosx_10_13_x86_64.whl", hash = "sha256:b4c854ef3adc177950a8dfc81a86f5115d2abd545751a304c5bcf2c2c7283cfe", size = 184344, upload-time = "2025-09-08T23:22:26.456Z" }, + { url = "https://files.pythonhosted.org/packages/4f/8b/f0e4c441227ba756aafbe78f117485b25bb26b1c059d01f137fa6d14896b/cffi-2.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:2de9a304e27f7596cd03d16f1b7c72219bd944e99cc52b84d0145aefb07cbd3c", size = 180560, upload-time = "2025-09-08T23:22:28.197Z" }, + { url = "https://files.pythonhosted.org/packages/b1/b7/1200d354378ef52ec227395d95c2576330fd22a869f7a70e88e1447eb234/cffi-2.0.0-cp311-cp311-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:baf5215e0ab74c16e2dd324e8ec067ef59e41125d3eade2b863d294fd5035c92", size = 209613, upload-time = "2025-09-08T23:22:29.475Z" }, + { url = "https://files.pythonhosted.org/packages/b8/56/6033f5e86e8cc9bb629f0077ba71679508bdf54a9a5e112a3c0b91870332/cffi-2.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:730cacb21e1bdff3ce90babf007d0a0917cc3e6492f336c2f0134101e0944f93", size = 216476, upload-time = "2025-09-08T23:22:31.063Z" }, + { url = "https://files.pythonhosted.org/packages/dc/7f/55fecd70f7ece178db2f26128ec41430d8720f2d12ca97bf8f0a628207d5/cffi-2.0.0-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:6824f87845e3396029f3820c206e459ccc91760e8fa24422f8b0c3d1731cbec5", size = 203374, upload-time = "2025-09-08T23:22:32.507Z" }, + { url = "https://files.pythonhosted.org/packages/84/ef/a7b77c8bdc0f77adc3b46888f1ad54be8f3b7821697a7b89126e829e676a/cffi-2.0.0-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:9de40a7b0323d889cf8d23d1ef214f565ab154443c42737dfe52ff82cf857664", size = 202597, upload-time = "2025-09-08T23:22:34.132Z" }, + { url = "https://files.pythonhosted.org/packages/d7/91/500d892b2bf36529a75b77958edfcd5ad8e2ce4064ce2ecfeab2125d72d1/cffi-2.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:8941aaadaf67246224cee8c3803777eed332a19d909b47e29c9842ef1e79ac26", size = 215574, upload-time = "2025-09-08T23:22:35.443Z" }, + { url = "https://files.pythonhosted.org/packages/44/64/58f6255b62b101093d5df22dcb752596066c7e89dd725e0afaed242a61be/cffi-2.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:a05d0c237b3349096d3981b727493e22147f934b20f6f125a3eba8f994bec4a9", size = 218971, upload-time = "2025-09-08T23:22:36.805Z" }, + { url = "https://files.pythonhosted.org/packages/ab/49/fa72cebe2fd8a55fbe14956f9970fe8eb1ac59e5df042f603ef7c8ba0adc/cffi-2.0.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:94698a9c5f91f9d138526b48fe26a199609544591f859c870d477351dc7b2414", size = 211972, upload-time = "2025-09-08T23:22:38.436Z" }, + { url = "https://files.pythonhosted.org/packages/0b/28/dd0967a76aab36731b6ebfe64dec4e981aff7e0608f60c2d46b46982607d/cffi-2.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:5fed36fccc0612a53f1d4d9a816b50a36702c28a2aa880cb8a122b3466638743", size = 217078, upload-time = "2025-09-08T23:22:39.776Z" }, + { url = "https://files.pythonhosted.org/packages/2b/c0/015b25184413d7ab0a410775fdb4a50fca20f5589b5dab1dbbfa3baad8ce/cffi-2.0.0-cp311-cp311-win32.whl", hash = "sha256:c649e3a33450ec82378822b3dad03cc228b8f5963c0c12fc3b1e0ab940f768a5", size = 172076, upload-time = "2025-09-08T23:22:40.95Z" }, + { url = "https://files.pythonhosted.org/packages/ae/8f/dc5531155e7070361eb1b7e4c1a9d896d0cb21c49f807a6c03fd63fc877e/cffi-2.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:66f011380d0e49ed280c789fbd08ff0d40968ee7b665575489afa95c98196ab5", size = 182820, upload-time = "2025-09-08T23:22:42.463Z" }, + { url = "https://files.pythonhosted.org/packages/95/5c/1b493356429f9aecfd56bc171285a4c4ac8697f76e9bbbbb105e537853a1/cffi-2.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:c6638687455baf640e37344fe26d37c404db8b80d037c3d29f58fe8d1c3b194d", size = 177635, upload-time = "2025-09-08T23:22:43.623Z" }, + { url = "https://files.pythonhosted.org/packages/ea/47/4f61023ea636104d4f16ab488e268b93008c3d0bb76893b1b31db1f96802/cffi-2.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6d02d6655b0e54f54c4ef0b94eb6be0607b70853c45ce98bd278dc7de718be5d", size = 185271, upload-time = "2025-09-08T23:22:44.795Z" }, + { url = "https://files.pythonhosted.org/packages/df/a2/781b623f57358e360d62cdd7a8c681f074a71d445418a776eef0aadb4ab4/cffi-2.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8eca2a813c1cb7ad4fb74d368c2ffbbb4789d377ee5bb8df98373c2cc0dee76c", size = 181048, upload-time = "2025-09-08T23:22:45.938Z" }, + { url = "https://files.pythonhosted.org/packages/ff/df/a4f0fbd47331ceeba3d37c2e51e9dfc9722498becbeec2bd8bc856c9538a/cffi-2.0.0-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:21d1152871b019407d8ac3985f6775c079416c282e431a4da6afe7aefd2bccbe", size = 212529, upload-time = "2025-09-08T23:22:47.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/72/12b5f8d3865bf0f87cf1404d8c374e7487dcf097a1c91c436e72e6badd83/cffi-2.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:b21e08af67b8a103c71a250401c78d5e0893beff75e28c53c98f4de42f774062", size = 220097, upload-time = "2025-09-08T23:22:48.677Z" }, + { url = "https://files.pythonhosted.org/packages/c2/95/7a135d52a50dfa7c882ab0ac17e8dc11cec9d55d2c18dda414c051c5e69e/cffi-2.0.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:1e3a615586f05fc4065a8b22b8152f0c1b00cdbc60596d187c2a74f9e3036e4e", size = 207983, upload-time = "2025-09-08T23:22:50.06Z" }, + { url = "https://files.pythonhosted.org/packages/3a/c8/15cb9ada8895957ea171c62dc78ff3e99159ee7adb13c0123c001a2546c1/cffi-2.0.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:81afed14892743bbe14dacb9e36d9e0e504cd204e0b165062c488942b9718037", size = 206519, upload-time = "2025-09-08T23:22:51.364Z" }, + { url = "https://files.pythonhosted.org/packages/78/2d/7fa73dfa841b5ac06c7b8855cfc18622132e365f5b81d02230333ff26e9e/cffi-2.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3e17ed538242334bf70832644a32a7aae3d83b57567f9fd60a26257e992b79ba", size = 219572, upload-time = "2025-09-08T23:22:52.902Z" }, + { url = "https://files.pythonhosted.org/packages/07/e0/267e57e387b4ca276b90f0434ff88b2c2241ad72b16d31836adddfd6031b/cffi-2.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3925dd22fa2b7699ed2617149842d2e6adde22b262fcbfada50e3d195e4b3a94", size = 222963, upload-time = "2025-09-08T23:22:54.518Z" }, + { url = "https://files.pythonhosted.org/packages/b6/75/1f2747525e06f53efbd878f4d03bac5b859cbc11c633d0fb81432d98a795/cffi-2.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2c8f814d84194c9ea681642fd164267891702542f028a15fc97d4674b6206187", size = 221361, upload-time = "2025-09-08T23:22:55.867Z" }, + { url = "https://files.pythonhosted.org/packages/7b/2b/2b6435f76bfeb6bbf055596976da087377ede68df465419d192acf00c437/cffi-2.0.0-cp312-cp312-win32.whl", hash = "sha256:da902562c3e9c550df360bfa53c035b2f241fed6d9aef119048073680ace4a18", size = 172932, upload-time = "2025-09-08T23:22:57.188Z" }, + { url = "https://files.pythonhosted.org/packages/f8/ed/13bd4418627013bec4ed6e54283b1959cf6db888048c7cf4b4c3b5b36002/cffi-2.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:da68248800ad6320861f129cd9c1bf96ca849a2771a59e0344e88681905916f5", size = 183557, upload-time = "2025-09-08T23:22:58.351Z" }, + { url = "https://files.pythonhosted.org/packages/95/31/9f7f93ad2f8eff1dbc1c3656d7ca5bfd8fb52c9d786b4dcf19b2d02217fa/cffi-2.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:4671d9dd5ec934cb9a73e7ee9676f9362aba54f7f34910956b84d727b0d73fb6", size = 177762, upload-time = "2025-09-08T23:22:59.668Z" }, + { url = "https://files.pythonhosted.org/packages/4b/8d/a0a47a0c9e413a658623d014e91e74a50cdd2c423f7ccfd44086ef767f90/cffi-2.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:00bdf7acc5f795150faa6957054fbbca2439db2f775ce831222b66f192f03beb", size = 185230, upload-time = "2025-09-08T23:23:00.879Z" }, + { url = "https://files.pythonhosted.org/packages/4a/d2/a6c0296814556c68ee32009d9c2ad4f85f2707cdecfd7727951ec228005d/cffi-2.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:45d5e886156860dc35862657e1494b9bae8dfa63bf56796f2fb56e1679fc0bca", size = 181043, upload-time = "2025-09-08T23:23:02.231Z" }, + { url = "https://files.pythonhosted.org/packages/b0/1e/d22cc63332bd59b06481ceaac49d6c507598642e2230f201649058a7e704/cffi-2.0.0-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:07b271772c100085dd28b74fa0cd81c8fb1a3ba18b21e03d7c27f3436a10606b", size = 212446, upload-time = "2025-09-08T23:23:03.472Z" }, + { url = "https://files.pythonhosted.org/packages/a9/f5/a2c23eb03b61a0b8747f211eb716446c826ad66818ddc7810cc2cc19b3f2/cffi-2.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d48a880098c96020b02d5a1f7d9251308510ce8858940e6fa99ece33f610838b", size = 220101, upload-time = "2025-09-08T23:23:04.792Z" }, + { url = "https://files.pythonhosted.org/packages/f2/7f/e6647792fc5850d634695bc0e6ab4111ae88e89981d35ac269956605feba/cffi-2.0.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f93fd8e5c8c0a4aa1f424d6173f14a892044054871c771f8566e4008eaa359d2", size = 207948, upload-time = "2025-09-08T23:23:06.127Z" }, + { url = "https://files.pythonhosted.org/packages/cb/1e/a5a1bd6f1fb30f22573f76533de12a00bf274abcdc55c8edab639078abb6/cffi-2.0.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:dd4f05f54a52fb558f1ba9f528228066954fee3ebe629fc1660d874d040ae5a3", size = 206422, upload-time = "2025-09-08T23:23:07.753Z" }, + { url = "https://files.pythonhosted.org/packages/98/df/0a1755e750013a2081e863e7cd37e0cdd02664372c754e5560099eb7aa44/cffi-2.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c8d3b5532fc71b7a77c09192b4a5a200ea992702734a2e9279a37f2478236f26", size = 219499, upload-time = "2025-09-08T23:23:09.648Z" }, + { url = "https://files.pythonhosted.org/packages/50/e1/a969e687fcf9ea58e6e2a928ad5e2dd88cc12f6f0ab477e9971f2309b57c/cffi-2.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:d9b29c1f0ae438d5ee9acb31cadee00a58c46cc9c0b2f9038c6b0b3470877a8c", size = 222928, upload-time = "2025-09-08T23:23:10.928Z" }, + { url = "https://files.pythonhosted.org/packages/36/54/0362578dd2c9e557a28ac77698ed67323ed5b9775ca9d3fe73fe191bb5d8/cffi-2.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6d50360be4546678fc1b79ffe7a66265e28667840010348dd69a314145807a1b", size = 221302, upload-time = "2025-09-08T23:23:12.42Z" }, + { url = "https://files.pythonhosted.org/packages/eb/6d/bf9bda840d5f1dfdbf0feca87fbdb64a918a69bca42cfa0ba7b137c48cb8/cffi-2.0.0-cp313-cp313-win32.whl", hash = "sha256:74a03b9698e198d47562765773b4a8309919089150a0bb17d829ad7b44b60d27", size = 172909, upload-time = "2025-09-08T23:23:14.32Z" }, + { url = "https://files.pythonhosted.org/packages/37/18/6519e1ee6f5a1e579e04b9ddb6f1676c17368a7aba48299c3759bbc3c8b3/cffi-2.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:19f705ada2530c1167abacb171925dd886168931e0a7b78f5bffcae5c6b5be75", size = 183402, upload-time = "2025-09-08T23:23:15.535Z" }, + { url = "https://files.pythonhosted.org/packages/cb/0e/02ceeec9a7d6ee63bb596121c2c8e9b3a9e150936f4fbef6ca1943e6137c/cffi-2.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:256f80b80ca3853f90c21b23ee78cd008713787b1b1e93eae9f3d6a7134abd91", size = 177780, upload-time = "2025-09-08T23:23:16.761Z" }, + { url = "https://files.pythonhosted.org/packages/92/c4/3ce07396253a83250ee98564f8d7e9789fab8e58858f35d07a9a2c78de9f/cffi-2.0.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:fc33c5141b55ed366cfaad382df24fe7dcbc686de5be719b207bb248e3053dc5", size = 185320, upload-time = "2025-09-08T23:23:18.087Z" }, + { url = "https://files.pythonhosted.org/packages/59/dd/27e9fa567a23931c838c6b02d0764611c62290062a6d4e8ff7863daf9730/cffi-2.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:c654de545946e0db659b3400168c9ad31b5d29593291482c43e3564effbcee13", size = 181487, upload-time = "2025-09-08T23:23:19.622Z" }, + { url = "https://files.pythonhosted.org/packages/d6/43/0e822876f87ea8a4ef95442c3d766a06a51fc5298823f884ef87aaad168c/cffi-2.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:24b6f81f1983e6df8db3adc38562c83f7d4a0c36162885ec7f7b77c7dcbec97b", size = 220049, upload-time = "2025-09-08T23:23:20.853Z" }, + { url = "https://files.pythonhosted.org/packages/b4/89/76799151d9c2d2d1ead63c2429da9ea9d7aac304603de0c6e8764e6e8e70/cffi-2.0.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:12873ca6cb9b0f0d3a0da705d6086fe911591737a59f28b7936bdfed27c0d47c", size = 207793, upload-time = "2025-09-08T23:23:22.08Z" }, + { url = "https://files.pythonhosted.org/packages/bb/dd/3465b14bb9e24ee24cb88c9e3730f6de63111fffe513492bf8c808a3547e/cffi-2.0.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:d9b97165e8aed9272a6bb17c01e3cc5871a594a446ebedc996e2397a1c1ea8ef", size = 206300, upload-time = "2025-09-08T23:23:23.314Z" }, + { url = "https://files.pythonhosted.org/packages/47/d9/d83e293854571c877a92da46fdec39158f8d7e68da75bf73581225d28e90/cffi-2.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:afb8db5439b81cf9c9d0c80404b60c3cc9c3add93e114dcae767f1477cb53775", size = 219244, upload-time = "2025-09-08T23:23:24.541Z" }, + { url = "https://files.pythonhosted.org/packages/2b/0f/1f177e3683aead2bb00f7679a16451d302c436b5cbf2505f0ea8146ef59e/cffi-2.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:737fe7d37e1a1bffe70bd5754ea763a62a066dc5913ca57e957824b72a85e205", size = 222828, upload-time = "2025-09-08T23:23:26.143Z" }, + { url = "https://files.pythonhosted.org/packages/c6/0f/cafacebd4b040e3119dcb32fed8bdef8dfe94da653155f9d0b9dc660166e/cffi-2.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:38100abb9d1b1435bc4cc340bb4489635dc2f0da7456590877030c9b3d40b0c1", size = 220926, upload-time = "2025-09-08T23:23:27.873Z" }, + { url = "https://files.pythonhosted.org/packages/3e/aa/df335faa45b395396fcbc03de2dfcab242cd61a9900e914fe682a59170b1/cffi-2.0.0-cp314-cp314-win32.whl", hash = "sha256:087067fa8953339c723661eda6b54bc98c5625757ea62e95eb4898ad5e776e9f", size = 175328, upload-time = "2025-09-08T23:23:44.61Z" }, + { url = "https://files.pythonhosted.org/packages/bb/92/882c2d30831744296ce713f0feb4c1cd30f346ef747b530b5318715cc367/cffi-2.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:203a48d1fb583fc7d78a4c6655692963b860a417c0528492a6bc21f1aaefab25", size = 185650, upload-time = "2025-09-08T23:23:45.848Z" }, + { url = "https://files.pythonhosted.org/packages/9f/2c/98ece204b9d35a7366b5b2c6539c350313ca13932143e79dc133ba757104/cffi-2.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:dbd5c7a25a7cb98f5ca55d258b103a2054f859a46ae11aaf23134f9cc0d356ad", size = 180687, upload-time = "2025-09-08T23:23:47.105Z" }, + { url = "https://files.pythonhosted.org/packages/3e/61/c768e4d548bfa607abcda77423448df8c471f25dbe64fb2ef6d555eae006/cffi-2.0.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9a67fc9e8eb39039280526379fb3a70023d77caec1852002b4da7e8b270c4dd9", size = 188773, upload-time = "2025-09-08T23:23:29.347Z" }, + { url = "https://files.pythonhosted.org/packages/2c/ea/5f76bce7cf6fcd0ab1a1058b5af899bfbef198bea4d5686da88471ea0336/cffi-2.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7a66c7204d8869299919db4d5069a82f1561581af12b11b3c9f48c584eb8743d", size = 185013, upload-time = "2025-09-08T23:23:30.63Z" }, + { url = "https://files.pythonhosted.org/packages/be/b4/c56878d0d1755cf9caa54ba71e5d049479c52f9e4afc230f06822162ab2f/cffi-2.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:7cc09976e8b56f8cebd752f7113ad07752461f48a58cbba644139015ac24954c", size = 221593, upload-time = "2025-09-08T23:23:31.91Z" }, + { url = "https://files.pythonhosted.org/packages/e0/0d/eb704606dfe8033e7128df5e90fee946bbcb64a04fcdaa97321309004000/cffi-2.0.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:92b68146a71df78564e4ef48af17551a5ddd142e5190cdf2c5624d0c3ff5b2e8", size = 209354, upload-time = "2025-09-08T23:23:33.214Z" }, + { url = "https://files.pythonhosted.org/packages/d8/19/3c435d727b368ca475fb8742ab97c9cb13a0de600ce86f62eab7fa3eea60/cffi-2.0.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b1e74d11748e7e98e2f426ab176d4ed720a64412b6a15054378afdb71e0f37dc", size = 208480, upload-time = "2025-09-08T23:23:34.495Z" }, + { url = "https://files.pythonhosted.org/packages/d0/44/681604464ed9541673e486521497406fadcc15b5217c3e326b061696899a/cffi-2.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:28a3a209b96630bca57cce802da70c266eb08c6e97e5afd61a75611ee6c64592", size = 221584, upload-time = "2025-09-08T23:23:36.096Z" }, + { url = "https://files.pythonhosted.org/packages/25/8e/342a504ff018a2825d395d44d63a767dd8ebc927ebda557fecdaca3ac33a/cffi-2.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:7553fb2090d71822f02c629afe6042c299edf91ba1bf94951165613553984512", size = 224443, upload-time = "2025-09-08T23:23:37.328Z" }, + { url = "https://files.pythonhosted.org/packages/e1/5e/b666bacbbc60fbf415ba9988324a132c9a7a0448a9a8f125074671c0f2c3/cffi-2.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c6c373cfc5c83a975506110d17457138c8c63016b563cc9ed6e056a82f13ce4", size = 223437, upload-time = "2025-09-08T23:23:38.945Z" }, + { url = "https://files.pythonhosted.org/packages/a0/1d/ec1a60bd1a10daa292d3cd6bb0b359a81607154fb8165f3ec95fe003b85c/cffi-2.0.0-cp314-cp314t-win32.whl", hash = "sha256:1fc9ea04857caf665289b7a75923f2c6ed559b8298a1b8c49e59f7dd95c8481e", size = 180487, upload-time = "2025-09-08T23:23:40.423Z" }, + { url = "https://files.pythonhosted.org/packages/bf/41/4c1168c74fac325c0c8156f04b6749c8b6a8f405bbf91413ba088359f60d/cffi-2.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:d68b6cef7827e8641e8ef16f4494edda8b36104d79773a334beaa1e3521430f6", size = 191726, upload-time = "2025-09-08T23:23:41.742Z" }, + { url = "https://files.pythonhosted.org/packages/ae/3a/dbeec9d1ee0844c679f6bb5d6ad4e9f198b1224f4e7a32825f47f6192b0c/cffi-2.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:0a1527a803f0a659de1af2e1fd700213caba79377e27e4693648c2923da066f9", size = 184195, upload-time = "2025-09-08T23:23:43.004Z" }, +] + [[package]] name = "charset-normalizer" version = "3.4.2" @@ -247,6 +347,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" }, ] +[[package]] +name = "comm" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/4c/13/7d740c5849255756bc17888787313b61fd38a0a8304fc4f073dfc46122aa/comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971", size = 6319, upload-time = "2025-07-25T14:02:04.452Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/60/97/891a0971e1e4a8c5d2b20bbe0e524dc04548d2307fee33cdeba148fd4fc7/comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417", size = 7294, upload-time = "2025-07-25T14:02:02.896Z" }, +] + [[package]] name = "coverage" version = "7.14.0" @@ -384,6 +493,44 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/6b/cf/8e8d034f7d55fceb2e4765bf9fab5da6d6a09204cd09de7bb5054f242cd0/cucumber_tag_expressions-9.1.0-py3-none-any.whl", hash = "sha256:cca145d677a942c1877e5a2cf13da8c6ec99260988877c817efd284d8455bb56", size = 9726, upload-time = "2026-02-17T21:59:04.755Z" }, ] +[[package]] +name = "debugpy" +version = "1.8.20" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/e0/b7/cd8080344452e4874aae67c40d8940e2b4d47b01601a8fd9f44786c757c7/debugpy-1.8.20.tar.gz", hash = "sha256:55bc8701714969f1ab89a6d5f2f3d40c36f91b2cbe2f65d98bf8196f6a6a2c33", size = 1645207, upload-time = "2026-01-29T23:03:28.199Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/71/be/8bd693a0b9d53d48c8978fa5d889e06f3b5b03e45fd1ea1e78267b4887cb/debugpy-1.8.20-cp310-cp310-macosx_15_0_x86_64.whl", hash = "sha256:157e96ffb7f80b3ad36d808646198c90acb46fdcfd8bb1999838f0b6f2b59c64", size = 2099192, upload-time = "2026-01-29T23:03:29.707Z" }, + { url = "https://files.pythonhosted.org/packages/77/1b/85326d07432086a06361d493d2743edd0c4fc2ef62162be7f8618441ac37/debugpy-1.8.20-cp310-cp310-manylinux_2_34_x86_64.whl", hash = "sha256:c1178ae571aff42e61801a38b007af504ec8e05fde1c5c12e5a7efef21009642", size = 3088568, upload-time = "2026-01-29T23:03:31.467Z" }, + { url = "https://files.pythonhosted.org/packages/e8/60/3e08462ee3eccd10998853eb35947c416e446bfe2bc37dbb886b9044586c/debugpy-1.8.20-cp310-cp310-win32.whl", hash = "sha256:c29dd9d656c0fbd77906a6e6a82ae4881514aa3294b94c903ff99303e789b4a2", size = 5284399, upload-time = "2026-01-29T23:03:33.678Z" }, + { url = "https://files.pythonhosted.org/packages/72/43/09d49106e770fe558ced5e80df2e3c2ebee10e576eda155dcc5670473663/debugpy-1.8.20-cp310-cp310-win_amd64.whl", hash = "sha256:3ca85463f63b5dd0aa7aaa933d97cbc47c174896dcae8431695872969f981893", size = 5316388, upload-time = "2026-01-29T23:03:35.095Z" }, + { url = "https://files.pythonhosted.org/packages/51/56/c3baf5cbe4dd77427fd9aef99fcdade259ad128feeb8a786c246adb838e5/debugpy-1.8.20-cp311-cp311-macosx_15_0_universal2.whl", hash = "sha256:eada6042ad88fa1571b74bd5402ee8b86eded7a8f7b827849761700aff171f1b", size = 2208318, upload-time = "2026-01-29T23:03:36.481Z" }, + { url = "https://files.pythonhosted.org/packages/9a/7d/4fa79a57a8e69fe0d9763e98d1110320f9ecd7f1f362572e3aafd7417c9d/debugpy-1.8.20-cp311-cp311-manylinux_2_34_x86_64.whl", hash = "sha256:7de0b7dfeedc504421032afba845ae2a7bcc32ddfb07dae2c3ca5442f821c344", size = 3171493, upload-time = "2026-01-29T23:03:37.775Z" }, + { url = "https://files.pythonhosted.org/packages/7d/f2/1e8f8affe51e12a26f3a8a8a4277d6e60aa89d0a66512f63b1e799d424a4/debugpy-1.8.20-cp311-cp311-win32.whl", hash = "sha256:773e839380cf459caf73cc533ea45ec2737a5cc184cf1b3b796cd4fd98504fec", size = 5209240, upload-time = "2026-01-29T23:03:39.109Z" }, + { url = "https://files.pythonhosted.org/packages/d5/92/1cb532e88560cbee973396254b21bece8c5d7c2ece958a67afa08c9f10dc/debugpy-1.8.20-cp311-cp311-win_amd64.whl", hash = "sha256:1f7650546e0eded1902d0f6af28f787fa1f1dbdbc97ddabaf1cd963a405930cb", size = 5233481, upload-time = "2026-01-29T23:03:40.659Z" }, + { url = "https://files.pythonhosted.org/packages/14/57/7f34f4736bfb6e00f2e4c96351b07805d83c9a7b33d28580ae01374430f7/debugpy-1.8.20-cp312-cp312-macosx_15_0_universal2.whl", hash = "sha256:4ae3135e2089905a916909ef31922b2d733d756f66d87345b3e5e52b7a55f13d", size = 2550686, upload-time = "2026-01-29T23:03:42.023Z" }, + { url = "https://files.pythonhosted.org/packages/ab/78/b193a3975ca34458f6f0e24aaf5c3e3da72f5401f6054c0dfd004b41726f/debugpy-1.8.20-cp312-cp312-manylinux_2_34_x86_64.whl", hash = "sha256:88f47850a4284b88bd2bfee1f26132147d5d504e4e86c22485dfa44b97e19b4b", size = 4310588, upload-time = "2026-01-29T23:03:43.314Z" }, + { url = "https://files.pythonhosted.org/packages/c1/55/f14deb95eaf4f30f07ef4b90a8590fc05d9e04df85ee379712f6fb6736d7/debugpy-1.8.20-cp312-cp312-win32.whl", hash = "sha256:4057ac68f892064e5f98209ab582abfee3b543fb55d2e87610ddc133a954d390", size = 5331372, upload-time = "2026-01-29T23:03:45.526Z" }, + { url = "https://files.pythonhosted.org/packages/a1/39/2bef246368bd42f9bd7cba99844542b74b84dacbdbea0833e610f384fee8/debugpy-1.8.20-cp312-cp312-win_amd64.whl", hash = "sha256:a1a8f851e7cf171330679ef6997e9c579ef6dd33c9098458bd9986a0f4ca52e3", size = 5372835, upload-time = "2026-01-29T23:03:47.245Z" }, + { url = "https://files.pythonhosted.org/packages/15/e2/fc500524cc6f104a9d049abc85a0a8b3f0d14c0a39b9c140511c61e5b40b/debugpy-1.8.20-cp313-cp313-macosx_15_0_universal2.whl", hash = "sha256:5dff4bb27027821fdfcc9e8f87309a28988231165147c31730128b1c983e282a", size = 2539560, upload-time = "2026-01-29T23:03:48.738Z" }, + { url = "https://files.pythonhosted.org/packages/90/83/fb33dcea789ed6018f8da20c5a9bc9d82adc65c0c990faed43f7c955da46/debugpy-1.8.20-cp313-cp313-manylinux_2_34_x86_64.whl", hash = "sha256:84562982dd7cf5ebebfdea667ca20a064e096099997b175fe204e86817f64eaf", size = 4293272, upload-time = "2026-01-29T23:03:50.169Z" }, + { url = "https://files.pythonhosted.org/packages/a6/25/b1e4a01bfb824d79a6af24b99ef291e24189080c93576dfd9b1a2815cd0f/debugpy-1.8.20-cp313-cp313-win32.whl", hash = "sha256:da11dea6447b2cadbf8ce2bec59ecea87cc18d2c574980f643f2d2dfe4862393", size = 5331208, upload-time = "2026-01-29T23:03:51.547Z" }, + { url = "https://files.pythonhosted.org/packages/13/f7/a0b368ce54ffff9e9028c098bd2d28cfc5b54f9f6c186929083d4c60ba58/debugpy-1.8.20-cp313-cp313-win_amd64.whl", hash = "sha256:eb506e45943cab2efb7c6eafdd65b842f3ae779f020c82221f55aca9de135ed7", size = 5372930, upload-time = "2026-01-29T23:03:53.585Z" }, + { url = "https://files.pythonhosted.org/packages/33/2e/f6cb9a8a13f5058f0a20fe09711a7b726232cd5a78c6a7c05b2ec726cff9/debugpy-1.8.20-cp314-cp314-macosx_15_0_universal2.whl", hash = "sha256:9c74df62fc064cd5e5eaca1353a3ef5a5d50da5eb8058fcef63106f7bebe6173", size = 2538066, upload-time = "2026-01-29T23:03:54.999Z" }, + { url = "https://files.pythonhosted.org/packages/c5/56/6ddca50b53624e1ca3ce1d1e49ff22db46c47ea5fb4c0cc5c9b90a616364/debugpy-1.8.20-cp314-cp314-manylinux_2_34_x86_64.whl", hash = "sha256:077a7447589ee9bc1ff0cdf443566d0ecf540ac8aa7333b775ebcb8ce9f4ecad", size = 4269425, upload-time = "2026-01-29T23:03:56.518Z" }, + { url = "https://files.pythonhosted.org/packages/c5/d9/d64199c14a0d4c476df46c82470a3ce45c8d183a6796cfb5e66533b3663c/debugpy-1.8.20-cp314-cp314-win32.whl", hash = "sha256:352036a99dd35053b37b7803f748efc456076f929c6a895556932eaf2d23b07f", size = 5331407, upload-time = "2026-01-29T23:03:58.481Z" }, + { url = "https://files.pythonhosted.org/packages/e0/d9/1f07395b54413432624d61524dfd98c1a7c7827d2abfdb8829ac92638205/debugpy-1.8.20-cp314-cp314-win_amd64.whl", hash = "sha256:a98eec61135465b062846112e5ecf2eebb855305acc1dfbae43b72903b8ab5be", size = 5372521, upload-time = "2026-01-29T23:03:59.864Z" }, + { url = "https://files.pythonhosted.org/packages/e0/c3/7f67dea8ccf8fdcb9c99033bbe3e90b9e7395415843accb81428c441be2d/debugpy-1.8.20-py2.py3-none-any.whl", hash = "sha256:5be9bed9ae3be00665a06acaa48f8329d2b9632f15fd09f6a9a8c8d9907e54d7", size = 5337658, upload-time = "2026-01-29T23:04:17.404Z" }, +] + +[[package]] +name = "decorator" +version = "5.3.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/60/8b/32f9823da46cde7df2087faa08cd98d01b908f8dcab982cdba9c84e85355/decorator-5.3.1.tar.gz", hash = "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82", size = 58084, upload-time = "2026-05-18T06:03:28.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/05/7f/798705f5296a58ca505d600456748d1be48078eac8a7050d8a98bc9edb89/decorator-5.3.1-py3-none-any.whl", hash = "sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c", size = 10365, upload-time = "2026-05-18T06:03:26.517Z" }, +] + [[package]] name = "distlib" version = "0.3.9" @@ -407,7 +554,6 @@ name = "exceptiongroup" version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ - { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '3.13'" }, { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/0b/9f/a65090624ecf468cdca03533906e7c69ed7588582240cfe7cc9e770b50eb/exceptiongroup-1.3.0.tar.gz", hash = "sha256:b241f5885f560bc56a59ee63ca4c6a8bfa46ae4ad651af316d4e81817bb9fd88", size = 29749, upload-time = "2025-05-10T17:42:51.123Z" } @@ -415,6 +561,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/36/f4/c6e662dade71f56cd2f3735141b265c3c79293c109549c1e6933b0651ffc/exceptiongroup-1.3.0-py3-none-any.whl", hash = "sha256:4d111e6e0c13d0644cad6ddaa7ed0261a0b36971f6d23e7ec9b4b9097da78a10", size = 16674, upload-time = "2025-05-10T17:42:49.33Z" }, ] +[[package]] +name = "executing" +version = "2.2.1" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cc/28/c14e053b6762b1044f34a13aab6859bbf40456d37d23aa286ac24cfd9a5d/executing-2.2.1.tar.gz", hash = "sha256:3632cc370565f6648cc328b32435bd120a1e4ebb20c77e3fdde9a13cd1e533c4", size = 1129488, upload-time = "2025-09-01T09:48:10.866Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c1/ea/53f2148663b321f21b5a606bd5f191517cf40b7072c0497d3c92c4a13b1e/executing-2.2.1-py2.py3-none-any.whl", hash = "sha256:760643d3452b4d777d295bb167ccc74c64a81df23fb5e08eff250c425a4b2017", size = 28317, upload-time = "2025-09-01T09:48:08.5Z" }, +] + [[package]] name = "filelock" version = "3.29.0" @@ -549,6 +704,108 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" }, ] +[[package]] +name = "ipykernel" +version = "7.2.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "appnope", marker = "sys_platform == 'darwin'" }, + { name = "comm" }, + { name = "debugpy" }, + { name = "ipython", version = "8.39.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, + { name = "ipython", version = "9.13.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11'" }, + { name = "jupyter-client" }, + { name = "jupyter-core" }, + { name = "matplotlib-inline" }, + { name = "nest-asyncio" }, + { name = "packaging" }, + { name = "psutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ca/8d/b68b728e2d06b9e0051019640a40a9eb7a88fcd82c2e1b5ce70bef5ff044/ipykernel-7.2.0.tar.gz", hash = "sha256:18ed160b6dee2cbb16e5f3575858bc19d8f1fe6046a9a680c708494ce31d909e", size = 176046, upload-time = "2026-02-06T16:43:27.403Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/82/b9/e73d5d9f405cba7706c539aa8b311b49d4c2f3d698d9c12f815231169c71/ipykernel-7.2.0-py3-none-any.whl", hash = "sha256:3bbd4420d2b3cc105cbdf3756bfc04500b1e52f090a90716851f3916c62e1661", size = 118788, upload-time = "2026-02-06T16:43:25.149Z" }, +] + +[[package]] +name = "ipython" +version = "8.39.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version < '3.11'", +] +dependencies = [ + { name = "colorama", marker = "python_full_version < '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version < '3.11'" }, + { name = "exceptiongroup", marker = "python_full_version < '3.11'" }, + { name = "jedi", marker = "python_full_version < '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version < '3.11'" }, + { name = "pexpect", marker = "python_full_version < '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version < '3.11'" }, + { name = "pygments", marker = "python_full_version < '3.11'" }, + { name = "stack-data", marker = "python_full_version < '3.11'" }, + { name = "traitlets", marker = "python_full_version < '3.11'" }, + { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/40/18/f8598d287006885e7136451fdea0755af4ebcbfe342836f24deefaed1164/ipython-8.39.0.tar.gz", hash = "sha256:4110ae96012c379b8b6db898a07e186c40a2a1ef5d57a7fa83166047d9da7624", size = 5513971, upload-time = "2026-03-27T10:02:13.94Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c0/56/4cc7fc9e9e3f38fd324f24f8afe0ad8bb5fa41283f37f1aaf9de0612c968/ipython-8.39.0-py3-none-any.whl", hash = "sha256:bb3c51c4fa8148ab1dea07a79584d1c854e234ea44aa1283bcb37bc75054651f", size = 831849, upload-time = "2026-03-27T10:02:07.846Z" }, +] + +[[package]] +name = "ipython" +version = "9.13.0" +source = { registry = "https://pypi.org/simple" } +resolution-markers = [ + "python_full_version == '3.13.*'", + "python_full_version >= '3.15'", + "python_full_version == '3.14.*' or (python_full_version >= '3.11' and python_full_version < '3.13')", +] +dependencies = [ + { name = "colorama", marker = "python_full_version >= '3.11' and sys_platform == 'win32'" }, + { name = "decorator", marker = "python_full_version >= '3.11'" }, + { name = "ipython-pygments-lexers", marker = "python_full_version >= '3.11'" }, + { name = "jedi", marker = "python_full_version >= '3.11'" }, + { name = "matplotlib-inline", marker = "python_full_version >= '3.11'" }, + { name = "pexpect", marker = "python_full_version >= '3.11' and sys_platform != 'emscripten' and sys_platform != 'win32'" }, + { name = "prompt-toolkit", marker = "python_full_version >= '3.11'" }, + { name = "psutil", marker = "python_full_version >= '3.11'" }, + { name = "pygments", marker = "python_full_version >= '3.11'" }, + { name = "stack-data", marker = "python_full_version >= '3.11'" }, + { name = "traitlets", marker = "python_full_version >= '3.11'" }, + { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.11.*'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/cd/c4/87cda5842cf5c31837c06ddb588e11c3c35d8ece89b7a0108c06b8c9b00a/ipython-9.13.0.tar.gz", hash = "sha256:7e834b6afc99f020e3f05966ced34792f40267d64cb1ea9043886dab0dde5967", size = 4430549, upload-time = "2026-04-24T12:24:55.221Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b9/86/3060e8029b7cc505cce9a0137431dda81d0a3fde93a8f0f50ee0bf37a795/ipython-9.13.0-py3-none-any.whl", hash = "sha256:57f9d4639e20818d328d287c7b549af3d05f12486ea8f2e7f73e52a36ec4d201", size = 627274, upload-time = "2026-04-24T12:24:53.038Z" }, +] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "pygments", marker = "python_full_version >= '3.11'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/ef/4c/5dd1d8af08107f88c7f741ead7a40854b8ac24ddf9ae850afbcf698aa552/ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", size = 8393, upload-time = "2025-01-17T11:24:34.505Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/d9/33/1f075bf72b0b747cb3288d011319aaf64083cf2efef8354174e3ed4540e2/ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c", size = 8074, upload-time = "2025-01-17T11:24:33.271Z" }, +] + +[[package]] +name = "jedi" +version = "0.20.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "parso" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/46/b7/a3635f6a2d7cf5b5dd98064fc1d5fbbafcb25477bcea204a3a92145d158b/jedi-0.20.0.tar.gz", hash = "sha256:c3f4ccbd276696f4b19c54618d4fb18f9fc24b0aef02acf704b23f487daa1011", size = 3119416, upload-time = "2026-05-01T23:38:47.814Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9a/93/242e2eab5fe682ffcb8b0084bde703a41d51e17ee0f3a31ff0d9d813620a/jedi-0.20.0-py2.py3-none-any.whl", hash = "sha256:7bdd9c2634f56713299976f4cbd59cb3fa92165cc5e05ea811fb253480728b67", size = 4884812, upload-time = "2026-05-01T23:38:43.919Z" }, +] + [[package]] name = "jinja2" version = "3.1.6" @@ -570,6 +827,35 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/14/2f/967ba146e6d58cf6a652da73885f52fc68001525b4197effc174321d70b4/jmespath-1.1.0-py3-none-any.whl", hash = "sha256:a5663118de4908c91729bea0acadca56526eb2698e83de10cd116ae0f4e97c64", size = 20419, upload-time = "2026-01-22T16:35:24.919Z" }, ] +[[package]] +name = "jupyter-client" +version = "8.8.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "jupyter-core" }, + { name = "python-dateutil" }, + { name = "pyzmq" }, + { name = "tornado" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/05/e4/ba649102a3bc3fbca54e7239fb924fd434c766f855693d86de0b1f2bec81/jupyter_client-8.8.0.tar.gz", hash = "sha256:d556811419a4f2d96c869af34e854e3f059b7cc2d6d01a9cd9c85c267691be3e", size = 348020, upload-time = "2026-01-08T13:55:47.938Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/2d/0b/ceb7694d864abc0a047649aec263878acb9f792e1fec3e676f22dc9015e3/jupyter_client-8.8.0-py3-none-any.whl", hash = "sha256:f93a5b99c5e23a507b773d3a1136bd6e16c67883ccdbd9a829b0bbdb98cd7d7a", size = 107371, upload-time = "2026-01-08T13:55:45.562Z" }, +] + +[[package]] +name = "jupyter-core" +version = "5.9.1" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "platformdirs" }, + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/02/49/9d1284d0dc65e2c757b74c6687b6d319b02f822ad039e5c512df9194d9dd/jupyter_core-5.9.1.tar.gz", hash = "sha256:4d09aaff303b9566c3ce657f580bd089ff5c91f5f89cf7d8846c3cdf465b5508", size = 89814, upload-time = "2025-10-16T19:19:18.444Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/e7/e7/80988e32bf6f73919a113473a604f5a8f09094de312b9d52b79c2df7612b/jupyter_core-5.9.1-py3-none-any.whl", hash = "sha256:ebf87fdc6073d142e114c72c9e29a9d7ca03fad818c5d300ce2adc1fb0743407", size = 29032, upload-time = "2025-10-16T19:19:16.783Z" }, +] + [[package]] name = "lark" version = "1.3.1" @@ -722,6 +1008,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/4f/65/6079a46068dfceaeabb5dcad6d674f5f5c61a6fa5673746f42a9f4c233b3/MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", size = 15739, upload-time = "2024-10-18T15:21:42.784Z" }, ] +[[package]] +name = "matplotlib-inline" +version = "0.2.2" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "traitlets" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/bd/c0/9f7c9a46090390368a4d7bcb76bb87a4a36c421e4c0792cdb53486ffac7a/matplotlib_inline-0.2.2.tar.gz", hash = "sha256:72f3fe8fce36b70d4a5b612f899090cd0401deddc4ea90e1572b9f4bfb058c79", size = 8150, upload-time = "2026-05-08T17:33:33.49Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/09/5b161152e2d90f7b87f781c2e1267494aef9c32498df793f73ad0a0a494a/matplotlib_inline-0.2.2-py3-none-any.whl", hash = "sha256:3c821cf1c209f59fb2d2d64abbf5b23b67bcb2210d663f9918dd851c6da1fcf6", size = 9534, upload-time = "2026-05-08T17:33:32.055Z" }, +] + [[package]] name = "mypy" version = "2.1.0" @@ -731,7 +1029,6 @@ dependencies = [ { name = "librt", marker = "platform_python_implementation != 'PyPy'" }, { name = "mypy-extensions" }, { name = "pathspec" }, - { name = "tomli", version = "2.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '0'" }, { name = "tomli", version = "2.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, { name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.11' and python_full_version < '3.15'" }, { name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11' or python_full_version >= '3.15'" }, @@ -792,6 +1089,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/79/7b/2c79738432f5c924bef5071f933bcc9efd0473bac3b4aa584a6f7c1c8df8/mypy_extensions-1.1.0-py3-none-any.whl", hash = "sha256:1be4cccdb0f2482337c4743e60421de3a356cd97508abadd57d47403e94f5505", size = 4963, upload-time = "2025-04-22T14:54:22.983Z" }, ] +[[package]] +name = "nest-asyncio" +version = "1.6.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/83/f8/51569ac65d696c8ecbee95938f89d4abf00f47d58d48f6fbabfe8f0baefe/nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", size = 7418, upload-time = "2024-01-21T14:25:19.227Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, +] + [[package]] name = "packaging" version = "26.2" @@ -823,6 +1129,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/d5/b3/f6cc950042bfdbe98672e7c834d930f85920fb7d3359f59096e8d2799617/parse_type-0.6.4-py2.py3-none-any.whl", hash = "sha256:83d41144a82d6b8541127bf212dd76c7f01baff680b498ce8a4d052a7a5bce4c", size = 27442, upload-time = "2024-10-03T11:50:58.519Z" }, ] +[[package]] +name = "parso" +version = "0.8.7" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/30/4b/90c937815137d43ce71ba043cd3566221e9df6b9c805f24b5d138c9d40a7/parso-0.8.7.tar.gz", hash = "sha256:eaaac4c9fdd5e9e8852dc778d2d7405897ec510f2a298071453e5e3a07914bb1", size = 401824, upload-time = "2026-05-01T23:13:02.138Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/99/5d/8268b644392ee874ee82a635cd0df1773de230bde356c38de28e298392cc/parso-0.8.7-py2.py3-none-any.whl", hash = "sha256:a8926eb2a1b915486941fdbd31e86a4baf88fe8c210f25f2f35ecec5b574ca1c", size = 107025, upload-time = "2026-05-01T23:12:58.867Z" }, +] + [[package]] name = "pathspec" version = "1.1.1" @@ -901,6 +1216,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/02/fb/d65db067a67df7252f18b0cb7420dda84078b9e8bfb375215469c14a50be/pendulum-3.2.0-py3-none-any.whl", hash = "sha256:f3a9c18a89b4d9ef39c5fa6a78722aaff8d5be2597c129a3b16b9f40a561acf3", size = 114111, upload-time = "2026-01-30T11:22:22.361Z" }, ] +[[package]] +name = "pexpect" +version = "4.9.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "ptyprocess" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/42/92/cc564bf6381ff43ce1f4d06852fc19a2f11d180f23dc32d9588bee2f149d/pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f", size = 166450, upload-time = "2023-11-25T09:07:26.339Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9e/c3/059298687310d527a58bb01f3b1965787ee3b40dce76752eda8b44e9a2c5/pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", size = 63772, upload-time = "2023-11-25T06:56:14.81Z" }, +] + [[package]] name = "platformdirs" version = "4.9.6" @@ -919,6 +1246,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" }, ] +[[package]] +name = "prompt-toolkit" +version = "3.0.52" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "wcwidth" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/a1/96/06e01a7b38dce6fe1db213e061a4602dd6032a8a97ef6c1a862537732421/prompt_toolkit-3.0.52.tar.gz", hash = "sha256:28cde192929c8e7321de85de1ddbe736f1375148b02f2e17edd840042b1be855", size = 434198, upload-time = "2025-08-27T15:24:02.057Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/84/03/0d3ce49e2505ae70cf43bc5bb3033955d2fc9f932163e84dc0779cc47f48/prompt_toolkit-3.0.52-py3-none-any.whl", hash = "sha256:9aac639a3bbd33284347de5ad8d68ecc044b91a762dc39b7c21095fcd6a19955", size = 391431, upload-time = "2025-08-27T15:23:59.498Z" }, +] + [[package]] name = "protobuf" version = "7.34.1" @@ -934,6 +1273,61 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/88/95/608f665226bca68b736b79e457fded9a2a38c4f4379a4a7614303d9db3bc/protobuf-7.34.1-py3-none-any.whl", hash = "sha256:bb3812cd53aefea2b028ef42bd780f5b96407247f20c6ef7c679807e9d188f11", size = 170715, upload-time = "2026-03-20T17:34:45.384Z" }, ] +[[package]] +name = "psutil" +version = "7.2.2" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/aa/c6/d1ddf4abb55e93cebc4f2ed8b5d6dbad109ecb8d63748dd2b20ab5e57ebe/psutil-7.2.2.tar.gz", hash = "sha256:0746f5f8d406af344fd547f1c8daa5f5c33dbc293bb8d6a16d80b4bb88f59372", size = 493740, upload-time = "2026-01-28T18:14:54.428Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/51/08/510cbdb69c25a96f4ae523f733cdc963ae654904e8db864c07585ef99875/psutil-7.2.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:2edccc433cbfa046b980b0df0171cd25bcaeb3a68fe9022db0979e7aa74a826b", size = 130595, upload-time = "2026-01-28T18:14:57.293Z" }, + { url = "https://files.pythonhosted.org/packages/d6/f5/97baea3fe7a5a9af7436301f85490905379b1c6f2dd51fe3ecf24b4c5fbf/psutil-7.2.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e78c8603dcd9a04c7364f1a3e670cea95d51ee865e4efb3556a3a63adef958ea", size = 131082, upload-time = "2026-01-28T18:14:59.732Z" }, + { url = "https://files.pythonhosted.org/packages/37/d6/246513fbf9fa174af531f28412297dd05241d97a75911ac8febefa1a53c6/psutil-7.2.2-cp313-cp313t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a571f2330c966c62aeda00dd24620425d4b0cc86881c89861fbc04549e5dc63", size = 181476, upload-time = "2026-01-28T18:15:01.884Z" }, + { url = "https://files.pythonhosted.org/packages/b8/b5/9182c9af3836cca61696dabe4fd1304e17bc56cb62f17439e1154f225dd3/psutil-7.2.2-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:917e891983ca3c1887b4ef36447b1e0873e70c933afc831c6b6da078ba474312", size = 184062, upload-time = "2026-01-28T18:15:04.436Z" }, + { url = "https://files.pythonhosted.org/packages/16/ba/0756dca669f5a9300d0cbcbfae9a4c30e446dfc7440ffe43ded5724bfd93/psutil-7.2.2-cp313-cp313t-win_amd64.whl", hash = "sha256:ab486563df44c17f5173621c7b198955bd6b613fb87c71c161f827d3fb149a9b", size = 139893, upload-time = "2026-01-28T18:15:06.378Z" }, + { url = "https://files.pythonhosted.org/packages/1c/61/8fa0e26f33623b49949346de05ec1ddaad02ed8ba64af45f40a147dbfa97/psutil-7.2.2-cp313-cp313t-win_arm64.whl", hash = "sha256:ae0aefdd8796a7737eccea863f80f81e468a1e4cf14d926bd9b6f5f2d5f90ca9", size = 135589, upload-time = "2026-01-28T18:15:08.03Z" }, + { url = "https://files.pythonhosted.org/packages/81/69/ef179ab5ca24f32acc1dac0c247fd6a13b501fd5534dbae0e05a1c48b66d/psutil-7.2.2-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:eed63d3b4d62449571547b60578c5b2c4bcccc5387148db46e0c2313dad0ee00", size = 130664, upload-time = "2026-01-28T18:15:09.469Z" }, + { url = "https://files.pythonhosted.org/packages/7b/64/665248b557a236d3fa9efc378d60d95ef56dd0a490c2cd37dafc7660d4a9/psutil-7.2.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:7b6d09433a10592ce39b13d7be5a54fbac1d1228ed29abc880fb23df7cb694c9", size = 131087, upload-time = "2026-01-28T18:15:11.724Z" }, + { url = "https://files.pythonhosted.org/packages/d5/2e/e6782744700d6759ebce3043dcfa661fb61e2fb752b91cdeae9af12c2178/psutil-7.2.2-cp314-cp314t-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fa4ecf83bcdf6e6c8f4449aff98eefb5d0604bf88cb883d7da3d8d2d909546a", size = 182383, upload-time = "2026-01-28T18:15:13.445Z" }, + { url = "https://files.pythonhosted.org/packages/57/49/0a41cefd10cb7505cdc04dab3eacf24c0c2cb158a998b8c7b1d27ee2c1f5/psutil-7.2.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e452c464a02e7dc7822a05d25db4cde564444a67e58539a00f929c51eddda0cf", size = 185210, upload-time = "2026-01-28T18:15:16.002Z" }, + { url = "https://files.pythonhosted.org/packages/dd/2c/ff9bfb544f283ba5f83ba725a3c5fec6d6b10b8f27ac1dc641c473dc390d/psutil-7.2.2-cp314-cp314t-win_amd64.whl", hash = "sha256:c7663d4e37f13e884d13994247449e9f8f574bc4655d509c3b95e9ec9e2b9dc1", size = 141228, upload-time = "2026-01-28T18:15:18.385Z" }, + { url = "https://files.pythonhosted.org/packages/f2/fc/f8d9c31db14fcec13748d373e668bc3bed94d9077dbc17fb0eebc073233c/psutil-7.2.2-cp314-cp314t-win_arm64.whl", hash = "sha256:11fe5a4f613759764e79c65cf11ebdf26e33d6dd34336f8a337aa2996d71c841", size = 136284, upload-time = "2026-01-28T18:15:19.912Z" }, + { url = "https://files.pythonhosted.org/packages/e7/36/5ee6e05c9bd427237b11b3937ad82bb8ad2752d72c6969314590dd0c2f6e/psutil-7.2.2-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ed0cace939114f62738d808fdcecd4c869222507e266e574799e9c0faa17d486", size = 129090, upload-time = "2026-01-28T18:15:22.168Z" }, + { url = "https://files.pythonhosted.org/packages/80/c4/f5af4c1ca8c1eeb2e92ccca14ce8effdeec651d5ab6053c589b074eda6e1/psutil-7.2.2-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:1a7b04c10f32cc88ab39cbf606e117fd74721c831c98a27dc04578deb0c16979", size = 129859, upload-time = "2026-01-28T18:15:23.795Z" }, + { url = "https://files.pythonhosted.org/packages/b5/70/5d8df3b09e25bce090399cf48e452d25c935ab72dad19406c77f4e828045/psutil-7.2.2-cp36-abi3-manylinux2010_x86_64.manylinux_2_12_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:076a2d2f923fd4821644f5ba89f059523da90dc9014e85f8e45a5774ca5bc6f9", size = 155560, upload-time = "2026-01-28T18:15:25.976Z" }, + { url = "https://files.pythonhosted.org/packages/63/65/37648c0c158dc222aba51c089eb3bdfa238e621674dc42d48706e639204f/psutil-7.2.2-cp36-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b0726cecd84f9474419d67252add4ac0cd9811b04d61123054b9fb6f57df6e9e", size = 156997, upload-time = "2026-01-28T18:15:27.794Z" }, + { url = "https://files.pythonhosted.org/packages/8e/13/125093eadae863ce03c6ffdbae9929430d116a246ef69866dad94da3bfbc/psutil-7.2.2-cp36-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:fd04ef36b4a6d599bbdb225dd1d3f51e00105f6d48a28f006da7f9822f2606d8", size = 148972, upload-time = "2026-01-28T18:15:29.342Z" }, + { url = "https://files.pythonhosted.org/packages/04/78/0acd37ca84ce3ddffaa92ef0f571e073faa6d8ff1f0559ab1272188ea2be/psutil-7.2.2-cp36-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b58fabe35e80b264a4e3bb23e6b96f9e45a3df7fb7eed419ac0e5947c61e47cc", size = 148266, upload-time = "2026-01-28T18:15:31.597Z" }, + { url = "https://files.pythonhosted.org/packages/b4/90/e2159492b5426be0c1fef7acba807a03511f97c5f86b3caeda6ad92351a7/psutil-7.2.2-cp37-abi3-win_amd64.whl", hash = "sha256:eb7e81434c8d223ec4a219b5fc1c47d0417b12be7ea866e24fb5ad6e84b3d988", size = 137737, upload-time = "2026-01-28T18:15:33.849Z" }, + { url = "https://files.pythonhosted.org/packages/8c/c7/7bb2e321574b10df20cbde462a94e2b71d05f9bbda251ef27d104668306a/psutil-7.2.2-cp37-abi3-win_arm64.whl", hash = "sha256:8c233660f575a5a89e6d4cb65d9f938126312bca76d8fe087b947b3a1aaac9ee", size = 134617, upload-time = "2026-01-28T18:15:36.514Z" }, +] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/20/e5/16ff212c1e452235a90aeb09066144d0c5a6a8c0834397e03f5224495c4e/ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220", size = 70762, upload-time = "2020-12-28T15:15:30.155Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/22/a6/858897256d0deac81a172289110f31629fc4cee19b6f01283303e18c8db3/ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", size = 13993, upload-time = "2020-12-28T15:15:28.35Z" }, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/cd/05/0a34433a064256a578f1783a10da6df098ceaa4a57bbeaa96a6c0352786b/pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42", size = 19752, upload-time = "2024-07-21T12:58:21.801Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/8e/37/efad0257dc6e593a18957422533ff0f87ede7c9c6ea010a2177d738fb82f/pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", size = 11842, upload-time = "2024-07-21T12:58:20.04Z" }, +] + +[[package]] +name = "pycparser" +version = "3.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/7d/92392ff7815c21062bea51aa7b87d45576f649f16458d78b7cf94b9ab2e6/pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29", size = 103492, upload-time = "2026-01-21T14:26:51.89Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/0c/c3/44f3fbbfa403ea2a7c779186dc20772604442dde72947e7d01069cbe98e3/pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992", size = 48172, upload-time = "2026-01-21T14:26:50.693Z" }, +] + [[package]] name = "pygments" version = "2.19.1" @@ -967,7 +1361,6 @@ dependencies = [ { name = "packaging" }, { name = "pluggy" }, { name = "pygments" }, - { name = "tomli", version = "2.2.1", source = { registry = "https://pypi.org/simple" }, marker = "python_version < '0'" }, { name = "tomli", version = "2.4.1", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.11'" }, ] sdist = { url = "https://files.pythonhosted.org/packages/7d/0d/549bd94f1a0a402dc8cf64563a117c0f3765662e2e668477624baeec44d5/pytest-9.0.3.tar.gz", hash = "sha256:b86ada508af81d19edeb213c681b1d48246c1a91d304c6c81a427674c17eb91c", size = 1572165, upload-time = "2026-04-07T17:16:18.027Z" } @@ -1078,6 +1471,79 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/f1/12/de94a39c2ef588c7e6455cfbe7343d3b2dc9d6b6b2f40c4c6565744c873d/pyyaml-6.0.3-cp314-cp314t-win_arm64.whl", hash = "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", size = 149341, upload-time = "2025-09-25T21:32:56.828Z" }, ] +[[package]] +name = "pyzmq" +version = "27.1.0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "cffi", marker = "implementation_name == 'pypy'" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/04/0b/3c9baedbdf613ecaa7aa07027780b8867f57b6293b6ee50de316c9f3222b/pyzmq-27.1.0.tar.gz", hash = "sha256:ac0765e3d44455adb6ddbf4417dcce460fc40a05978c08efdf2948072f6db540", size = 281750, upload-time = "2025-09-08T23:10:18.157Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/67/b9/52aa9ec2867528b54f1e60846728d8b4d84726630874fee3a91e66c7df81/pyzmq-27.1.0-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:508e23ec9bc44c0005c4946ea013d9317ae00ac67778bd47519fdf5a0e930ff4", size = 1329850, upload-time = "2025-09-08T23:07:26.274Z" }, + { url = "https://files.pythonhosted.org/packages/99/64/5653e7b7425b169f994835a2b2abf9486264401fdef18df91ddae47ce2cc/pyzmq-27.1.0-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:507b6f430bdcf0ee48c0d30e734ea89ce5567fd7b8a0f0044a369c176aa44556", size = 906380, upload-time = "2025-09-08T23:07:29.78Z" }, + { url = "https://files.pythonhosted.org/packages/73/78/7d713284dbe022f6440e391bd1f3c48d9185673878034cfb3939cdf333b2/pyzmq-27.1.0-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bf7b38f9fd7b81cb6d9391b2946382c8237fd814075c6aa9c3b746d53076023b", size = 666421, upload-time = "2025-09-08T23:07:31.263Z" }, + { url = "https://files.pythonhosted.org/packages/30/76/8f099f9d6482450428b17c4d6b241281af7ce6a9de8149ca8c1c649f6792/pyzmq-27.1.0-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03ff0b279b40d687691a6217c12242ee71f0fba28bf8626ff50e3ef0f4410e1e", size = 854149, upload-time = "2025-09-08T23:07:33.17Z" }, + { url = "https://files.pythonhosted.org/packages/59/f0/37fbfff06c68016019043897e4c969ceab18bde46cd2aca89821fcf4fb2e/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:677e744fee605753eac48198b15a2124016c009a11056f93807000ab11ce6526", size = 1655070, upload-time = "2025-09-08T23:07:35.205Z" }, + { url = "https://files.pythonhosted.org/packages/47/14/7254be73f7a8edc3587609554fcaa7bfd30649bf89cd260e4487ca70fdaa/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dd2fec2b13137416a1c5648b7009499bcc8fea78154cd888855fa32514f3dad1", size = 2033441, upload-time = "2025-09-08T23:07:37.432Z" }, + { url = "https://files.pythonhosted.org/packages/22/dc/49f2be26c6f86f347e796a4d99b19167fc94503f0af3fd010ad262158822/pyzmq-27.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:08e90bb4b57603b84eab1d0ca05b3bbb10f60c1839dc471fc1c9e1507bef3386", size = 1891529, upload-time = "2025-09-08T23:07:39.047Z" }, + { url = "https://files.pythonhosted.org/packages/a3/3e/154fb963ae25be70c0064ce97776c937ecc7d8b0259f22858154a9999769/pyzmq-27.1.0-cp310-cp310-win32.whl", hash = "sha256:a5b42d7a0658b515319148875fcb782bbf118dd41c671b62dae33666c2213bda", size = 567276, upload-time = "2025-09-08T23:07:40.695Z" }, + { url = "https://files.pythonhosted.org/packages/62/b2/f4ab56c8c595abcb26b2be5fd9fa9e6899c1e5ad54964e93ae8bb35482be/pyzmq-27.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:c0bb87227430ee3aefcc0ade2088100e528d5d3298a0a715a64f3d04c60ba02f", size = 632208, upload-time = "2025-09-08T23:07:42.298Z" }, + { url = "https://files.pythonhosted.org/packages/3b/e3/be2cc7ab8332bdac0522fdb64c17b1b6241a795bee02e0196636ec5beb79/pyzmq-27.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:9a916f76c2ab8d045b19f2286851a38e9ac94ea91faf65bd64735924522a8b32", size = 559766, upload-time = "2025-09-08T23:07:43.869Z" }, + { url = "https://files.pythonhosted.org/packages/06/5d/305323ba86b284e6fcb0d842d6adaa2999035f70f8c38a9b6d21ad28c3d4/pyzmq-27.1.0-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:226b091818d461a3bef763805e75685e478ac17e9008f49fce2d3e52b3d58b86", size = 1333328, upload-time = "2025-09-08T23:07:45.946Z" }, + { url = "https://files.pythonhosted.org/packages/bd/a0/fc7e78a23748ad5443ac3275943457e8452da67fda347e05260261108cbc/pyzmq-27.1.0-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0790a0161c281ca9723f804871b4027f2e8b5a528d357c8952d08cd1a9c15581", size = 908803, upload-time = "2025-09-08T23:07:47.551Z" }, + { url = "https://files.pythonhosted.org/packages/7e/22/37d15eb05f3bdfa4abea6f6d96eb3bb58585fbd3e4e0ded4e743bc650c97/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c895a6f35476b0c3a54e3eb6ccf41bf3018de937016e6e18748317f25d4e925f", size = 668836, upload-time = "2025-09-08T23:07:49.436Z" }, + { url = "https://files.pythonhosted.org/packages/b1/c4/2a6fe5111a01005fc7af3878259ce17684fabb8852815eda6225620f3c59/pyzmq-27.1.0-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5bbf8d3630bf96550b3be8e1fc0fea5cbdc8d5466c1192887bd94869da17a63e", size = 857038, upload-time = "2025-09-08T23:07:51.234Z" }, + { url = "https://files.pythonhosted.org/packages/cb/eb/bfdcb41d0db9cd233d6fb22dc131583774135505ada800ebf14dfb0a7c40/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:15c8bd0fe0dabf808e2d7a681398c4e5ded70a551ab47482067a572c054c8e2e", size = 1657531, upload-time = "2025-09-08T23:07:52.795Z" }, + { url = "https://files.pythonhosted.org/packages/ab/21/e3180ca269ed4a0de5c34417dfe71a8ae80421198be83ee619a8a485b0c7/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:bafcb3dd171b4ae9f19ee6380dfc71ce0390fefaf26b504c0e5f628d7c8c54f2", size = 2034786, upload-time = "2025-09-08T23:07:55.047Z" }, + { url = "https://files.pythonhosted.org/packages/3b/b1/5e21d0b517434b7f33588ff76c177c5a167858cc38ef740608898cd329f2/pyzmq-27.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e829529fcaa09937189178115c49c504e69289abd39967cd8a4c215761373394", size = 1894220, upload-time = "2025-09-08T23:07:57.172Z" }, + { url = "https://files.pythonhosted.org/packages/03/f2/44913a6ff6941905efc24a1acf3d3cb6146b636c546c7406c38c49c403d4/pyzmq-27.1.0-cp311-cp311-win32.whl", hash = "sha256:6df079c47d5902af6db298ec92151db82ecb557af663098b92f2508c398bb54f", size = 567155, upload-time = "2025-09-08T23:07:59.05Z" }, + { url = "https://files.pythonhosted.org/packages/23/6d/d8d92a0eb270a925c9b4dd039c0b4dc10abc2fcbc48331788824ef113935/pyzmq-27.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:190cbf120fbc0fc4957b56866830def56628934a9d112aec0e2507aa6a032b97", size = 633428, upload-time = "2025-09-08T23:08:00.663Z" }, + { url = "https://files.pythonhosted.org/packages/ae/14/01afebc96c5abbbd713ecfc7469cfb1bc801c819a74ed5c9fad9a48801cb/pyzmq-27.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:eca6b47df11a132d1745eb3b5b5e557a7dae2c303277aa0e69c6ba91b8736e07", size = 559497, upload-time = "2025-09-08T23:08:02.15Z" }, + { url = "https://files.pythonhosted.org/packages/92/e7/038aab64a946d535901103da16b953c8c9cc9c961dadcbf3609ed6428d23/pyzmq-27.1.0-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:452631b640340c928fa343801b0d07eb0c3789a5ffa843f6e1a9cee0ba4eb4fc", size = 1306279, upload-time = "2025-09-08T23:08:03.807Z" }, + { url = "https://files.pythonhosted.org/packages/e8/5e/c3c49fdd0f535ef45eefcc16934648e9e59dace4a37ee88fc53f6cd8e641/pyzmq-27.1.0-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1c179799b118e554b66da67d88ed66cd37a169f1f23b5d9f0a231b4e8d44a113", size = 895645, upload-time = "2025-09-08T23:08:05.301Z" }, + { url = "https://files.pythonhosted.org/packages/f8/e5/b0b2504cb4e903a74dcf1ebae157f9e20ebb6ea76095f6cfffea28c42ecd/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3837439b7f99e60312f0c926a6ad437b067356dc2bc2ec96eb395fd0fe804233", size = 652574, upload-time = "2025-09-08T23:08:06.828Z" }, + { url = "https://files.pythonhosted.org/packages/f8/9b/c108cdb55560eaf253f0cbdb61b29971e9fb34d9c3499b0e96e4e60ed8a5/pyzmq-27.1.0-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:43ad9a73e3da1fab5b0e7e13402f0b2fb934ae1c876c51d0afff0e7c052eca31", size = 840995, upload-time = "2025-09-08T23:08:08.396Z" }, + { url = "https://files.pythonhosted.org/packages/c2/bb/b79798ca177b9eb0825b4c9998c6af8cd2a7f15a6a1a4272c1d1a21d382f/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:0de3028d69d4cdc475bfe47a6128eb38d8bc0e8f4d69646adfbcd840facbac28", size = 1642070, upload-time = "2025-09-08T23:08:09.989Z" }, + { url = "https://files.pythonhosted.org/packages/9c/80/2df2e7977c4ede24c79ae39dcef3899bfc5f34d1ca7a5b24f182c9b7a9ca/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:cf44a7763aea9298c0aa7dbf859f87ed7012de8bda0f3977b6fb1d96745df856", size = 2021121, upload-time = "2025-09-08T23:08:11.907Z" }, + { url = "https://files.pythonhosted.org/packages/46/bd/2d45ad24f5f5ae7e8d01525eb76786fa7557136555cac7d929880519e33a/pyzmq-27.1.0-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:f30f395a9e6fbca195400ce833c731e7b64c3919aa481af4d88c3759e0cb7496", size = 1878550, upload-time = "2025-09-08T23:08:13.513Z" }, + { url = "https://files.pythonhosted.org/packages/e6/2f/104c0a3c778d7c2ab8190e9db4f62f0b6957b53c9d87db77c284b69f33ea/pyzmq-27.1.0-cp312-abi3-win32.whl", hash = "sha256:250e5436a4ba13885494412b3da5d518cd0d3a278a1ae640e113c073a5f88edd", size = 559184, upload-time = "2025-09-08T23:08:15.163Z" }, + { url = "https://files.pythonhosted.org/packages/fc/7f/a21b20d577e4100c6a41795842028235998a643b1ad406a6d4163ea8f53e/pyzmq-27.1.0-cp312-abi3-win_amd64.whl", hash = "sha256:9ce490cf1d2ca2ad84733aa1d69ce6855372cb5ce9223802450c9b2a7cba0ccf", size = 619480, upload-time = "2025-09-08T23:08:17.192Z" }, + { url = "https://files.pythonhosted.org/packages/78/c2/c012beae5f76b72f007a9e91ee9401cb88c51d0f83c6257a03e785c81cc2/pyzmq-27.1.0-cp312-abi3-win_arm64.whl", hash = "sha256:75a2f36223f0d535a0c919e23615fc85a1e23b71f40c7eb43d7b1dedb4d8f15f", size = 552993, upload-time = "2025-09-08T23:08:18.926Z" }, + { url = "https://files.pythonhosted.org/packages/60/cb/84a13459c51da6cec1b7b1dc1a47e6db6da50b77ad7fd9c145842750a011/pyzmq-27.1.0-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:93ad4b0855a664229559e45c8d23797ceac03183c7b6f5b4428152a6b06684a5", size = 1122436, upload-time = "2025-09-08T23:08:20.801Z" }, + { url = "https://files.pythonhosted.org/packages/dc/b6/94414759a69a26c3dd674570a81813c46a078767d931a6c70ad29fc585cb/pyzmq-27.1.0-cp313-cp313-android_24_x86_64.whl", hash = "sha256:fbb4f2400bfda24f12f009cba62ad5734148569ff4949b1b6ec3b519444342e6", size = 1156301, upload-time = "2025-09-08T23:08:22.47Z" }, + { url = "https://files.pythonhosted.org/packages/a5/ad/15906493fd40c316377fd8a8f6b1f93104f97a752667763c9b9c1b71d42d/pyzmq-27.1.0-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:e343d067f7b151cfe4eb3bb796a7752c9d369eed007b91231e817071d2c2fec7", size = 1341197, upload-time = "2025-09-08T23:08:24.286Z" }, + { url = "https://files.pythonhosted.org/packages/14/1d/d343f3ce13db53a54cb8946594e567410b2125394dafcc0268d8dda027e0/pyzmq-27.1.0-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:08363b2011dec81c354d694bdecaef4770e0ae96b9afea70b3f47b973655cc05", size = 897275, upload-time = "2025-09-08T23:08:26.063Z" }, + { url = "https://files.pythonhosted.org/packages/69/2d/d83dd6d7ca929a2fc67d2c3005415cdf322af7751d773524809f9e585129/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d54530c8c8b5b8ddb3318f481297441af102517602b569146185fa10b63f4fa9", size = 660469, upload-time = "2025-09-08T23:08:27.623Z" }, + { url = "https://files.pythonhosted.org/packages/3e/cd/9822a7af117f4bc0f1952dbe9ef8358eb50a24928efd5edf54210b850259/pyzmq-27.1.0-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6f3afa12c392f0a44a2414056d730eebc33ec0926aae92b5ad5cf26ebb6cc128", size = 847961, upload-time = "2025-09-08T23:08:29.672Z" }, + { url = "https://files.pythonhosted.org/packages/9a/12/f003e824a19ed73be15542f172fd0ec4ad0b60cf37436652c93b9df7c585/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:c65047adafe573ff023b3187bb93faa583151627bc9c51fc4fb2c561ed689d39", size = 1650282, upload-time = "2025-09-08T23:08:31.349Z" }, + { url = "https://files.pythonhosted.org/packages/d5/4a/e82d788ed58e9a23995cee70dbc20c9aded3d13a92d30d57ec2291f1e8a3/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:90e6e9441c946a8b0a667356f7078d96411391a3b8f80980315455574177ec97", size = 2024468, upload-time = "2025-09-08T23:08:33.543Z" }, + { url = "https://files.pythonhosted.org/packages/d9/94/2da0a60841f757481e402b34bf4c8bf57fa54a5466b965de791b1e6f747d/pyzmq-27.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:add071b2d25f84e8189aaf0882d39a285b42fa3853016ebab234a5e78c7a43db", size = 1885394, upload-time = "2025-09-08T23:08:35.51Z" }, + { url = "https://files.pythonhosted.org/packages/4f/6f/55c10e2e49ad52d080dc24e37adb215e5b0d64990b57598abc2e3f01725b/pyzmq-27.1.0-cp313-cp313t-win32.whl", hash = "sha256:7ccc0700cfdf7bd487bea8d850ec38f204478681ea02a582a8da8171b7f90a1c", size = 574964, upload-time = "2025-09-08T23:08:37.178Z" }, + { url = "https://files.pythonhosted.org/packages/87/4d/2534970ba63dd7c522d8ca80fb92777f362c0f321900667c615e2067cb29/pyzmq-27.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:8085a9fba668216b9b4323be338ee5437a235fe275b9d1610e422ccc279733e2", size = 641029, upload-time = "2025-09-08T23:08:40.595Z" }, + { url = "https://files.pythonhosted.org/packages/f6/fa/f8aea7a28b0641f31d40dea42d7ef003fded31e184ef47db696bc74cd610/pyzmq-27.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:6bb54ca21bcfe361e445256c15eedf083f153811c37be87e0514934d6913061e", size = 561541, upload-time = "2025-09-08T23:08:42.668Z" }, + { url = "https://files.pythonhosted.org/packages/87/45/19efbb3000956e82d0331bafca5d9ac19ea2857722fa2caacefb6042f39d/pyzmq-27.1.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:ce980af330231615756acd5154f29813d553ea555485ae712c491cd483df6b7a", size = 1341197, upload-time = "2025-09-08T23:08:44.973Z" }, + { url = "https://files.pythonhosted.org/packages/48/43/d72ccdbf0d73d1343936296665826350cb1e825f92f2db9db3e61c2162a2/pyzmq-27.1.0-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:1779be8c549e54a1c38f805e56d2a2e5c009d26de10921d7d51cfd1c8d4632ea", size = 897175, upload-time = "2025-09-08T23:08:46.601Z" }, + { url = "https://files.pythonhosted.org/packages/2f/2e/a483f73a10b65a9ef0161e817321d39a770b2acf8bcf3004a28d90d14a94/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7200bb0f03345515df50d99d3db206a0a6bee1955fbb8c453c76f5bf0e08fb96", size = 660427, upload-time = "2025-09-08T23:08:48.187Z" }, + { url = "https://files.pythonhosted.org/packages/f5/d2/5f36552c2d3e5685abe60dfa56f91169f7a2d99bbaf67c5271022ab40863/pyzmq-27.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:01c0e07d558b06a60773744ea6251f769cd79a41a97d11b8bf4ab8f034b0424d", size = 847929, upload-time = "2025-09-08T23:08:49.76Z" }, + { url = "https://files.pythonhosted.org/packages/c4/2a/404b331f2b7bf3198e9945f75c4c521f0c6a3a23b51f7a4a401b94a13833/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:80d834abee71f65253c91540445d37c4c561e293ba6e741b992f20a105d69146", size = 1650193, upload-time = "2025-09-08T23:08:51.7Z" }, + { url = "https://files.pythonhosted.org/packages/1c/0b/f4107e33f62a5acf60e3ded67ed33d79b4ce18de432625ce2fc5093d6388/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:544b4e3b7198dde4a62b8ff6685e9802a9a1ebf47e77478a5eb88eca2a82f2fd", size = 2024388, upload-time = "2025-09-08T23:08:53.393Z" }, + { url = "https://files.pythonhosted.org/packages/0d/01/add31fe76512642fd6e40e3a3bd21f4b47e242c8ba33efb6809e37076d9b/pyzmq-27.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cedc4c68178e59a4046f97eca31b148ddcf51e88677de1ef4e78cf06c5376c9a", size = 1885316, upload-time = "2025-09-08T23:08:55.702Z" }, + { url = "https://files.pythonhosted.org/packages/c4/59/a5f38970f9bf07cee96128de79590bb354917914a9be11272cfc7ff26af0/pyzmq-27.1.0-cp314-cp314t-win32.whl", hash = "sha256:1f0b2a577fd770aa6f053211a55d1c47901f4d537389a034c690291485e5fe92", size = 587472, upload-time = "2025-09-08T23:08:58.18Z" }, + { url = "https://files.pythonhosted.org/packages/70/d8/78b1bad170f93fcf5e3536e70e8fadac55030002275c9a29e8f5719185de/pyzmq-27.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:19c9468ae0437f8074af379e986c5d3d7d7bfe033506af442e8c879732bedbe0", size = 661401, upload-time = "2025-09-08T23:08:59.802Z" }, + { url = "https://files.pythonhosted.org/packages/81/d6/4bfbb40c9a0b42fc53c7cf442f6385db70b40f74a783130c5d0a5aa62228/pyzmq-27.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:dc5dbf68a7857b59473f7df42650c621d7e8923fb03fa74a526890f4d33cc4d7", size = 575170, upload-time = "2025-09-08T23:09:01.418Z" }, + { url = "https://files.pythonhosted.org/packages/f3/81/a65e71c1552f74dec9dff91d95bafb6e0d33338a8dfefbc88aa562a20c92/pyzmq-27.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:c17e03cbc9312bee223864f1a2b13a99522e0dc9f7c5df0177cd45210ac286e6", size = 836266, upload-time = "2025-09-08T23:09:40.048Z" }, + { url = "https://files.pythonhosted.org/packages/58/ed/0202ca350f4f2b69faa95c6d931e3c05c3a397c184cacb84cb4f8f42f287/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f328d01128373cb6763823b2b4e7f73bdf767834268c565151eacb3b7a392f90", size = 800206, upload-time = "2025-09-08T23:09:41.902Z" }, + { url = "https://files.pythonhosted.org/packages/47/42/1ff831fa87fe8f0a840ddb399054ca0009605d820e2b44ea43114f5459f4/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c1790386614232e1b3a40a958454bdd42c6d1811837b15ddbb052a032a43f62", size = 567747, upload-time = "2025-09-08T23:09:43.741Z" }, + { url = "https://files.pythonhosted.org/packages/d1/db/5c4d6807434751e3f21231bee98109aa57b9b9b55e058e450d0aef59b70f/pyzmq-27.1.0-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:448f9cb54eb0cee4732b46584f2710c8bc178b0e5371d9e4fc8125201e413a74", size = 747371, upload-time = "2025-09-08T23:09:45.575Z" }, + { url = "https://files.pythonhosted.org/packages/26/af/78ce193dbf03567eb8c0dc30e3df2b9e56f12a670bf7eb20f9fb532c7e8a/pyzmq-27.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:05b12f2d32112bf8c95ef2e74ec4f1d4beb01f8b5e703b38537f8849f92cb9ba", size = 544862, upload-time = "2025-09-08T23:09:47.448Z" }, + { url = "https://files.pythonhosted.org/packages/4c/c6/c4dcdecdbaa70969ee1fdced6d7b8f60cfabe64d25361f27ac4665a70620/pyzmq-27.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:18770c8d3563715387139060d37859c02ce40718d1faf299abddcdcc6a649066", size = 836265, upload-time = "2025-09-08T23:09:49.376Z" }, + { url = "https://files.pythonhosted.org/packages/3e/79/f38c92eeaeb03a2ccc2ba9866f0439593bb08c5e3b714ac1d553e5c96e25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:ac25465d42f92e990f8d8b0546b01c391ad431c3bf447683fdc40565941d0604", size = 800208, upload-time = "2025-09-08T23:09:51.073Z" }, + { url = "https://files.pythonhosted.org/packages/49/0e/3f0d0d335c6b3abb9b7b723776d0b21fa7f3a6c819a0db6097059aada160/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53b40f8ae006f2734ee7608d59ed661419f087521edbfc2149c3932e9c14808c", size = 567747, upload-time = "2025-09-08T23:09:52.698Z" }, + { url = "https://files.pythonhosted.org/packages/a1/cf/f2b3784d536250ffd4be70e049f3b60981235d70c6e8ce7e3ef21e1adb25/pyzmq-27.1.0-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f605d884e7c8be8fe1aa94e0a783bf3f591b84c24e4bc4f3e7564c82ac25e271", size = 747371, upload-time = "2025-09-08T23:09:54.563Z" }, + { url = "https://files.pythonhosted.org/packages/01/1b/5dbe84eefc86f48473947e2f41711aded97eecef1231f4558f1f02713c12/pyzmq-27.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:c9f7f6e13dff2e44a6afeaf2cf54cee5929ad64afaf4d40b50f93c58fc687355", size = 544862, upload-time = "2025-09-08T23:09:56.509Z" }, +] + [[package]] name = "requests" version = "2.32.4" @@ -1286,6 +1752,20 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/52/a7/d2782e4e3f77c8450f727ba74a8f12756d5ba823d81b941f1b04da9d033a/sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331", size = 92072, upload-time = "2024-07-29T01:10:08.203Z" }, ] +[[package]] +name = "stack-data" +version = "0.6.3" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "asttokens" }, + { name = "executing" }, + { name = "pure-eval" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/28/e3/55dcc2cfbc3ca9c29519eb6884dd1415ecb53b0e934862d3559ddcb7e20b/stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", size = 44707, upload-time = "2023-09-30T13:58:05.479Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/f1/7b/ce1eafaf1a76852e2ec9b22edecf1daa58175c090266e9f6c64afcd81d91/stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695", size = 24521, upload-time = "2023-09-30T13:58:03.53Z" }, +] + [[package]] name = "toml" version = "0.10.2" @@ -1403,6 +1883,23 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/18/c86eb8e0202e32dd3df50d43d7ff9854f8e0603945ff398974c1d91ac1ef/tomli_w-1.2.0-py3-none-any.whl", hash = "sha256:188306098d013b691fcadc011abd66727d3c414c571bb01b1a174ba8c983cf90", size = 6675, upload-time = "2025-01-15T12:07:22.074Z" }, ] +[[package]] +name = "tornado" +version = "6.5.5" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f8/f1/3173dfa4a18db4a9b03e5d55325559dab51ee653763bb8745a75af491286/tornado-6.5.5.tar.gz", hash = "sha256:192b8f3ea91bd7f1f50c06955416ed76c6b72f96779b962f07f911b91e8d30e9", size = 516006, upload-time = "2026-03-10T21:31:02.067Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/59/8c/77f5097695f4dd8255ecbd08b2a1ed8ba8b953d337804dd7080f199e12bf/tornado-6.5.5-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:487dc9cc380e29f58c7ab88f9e27cdeef04b2140862e5076a66fb6bb68bb1bfa", size = 445983, upload-time = "2026-03-10T21:30:44.28Z" }, + { url = "https://files.pythonhosted.org/packages/ab/5e/7625b76cd10f98f1516c36ce0346de62061156352353ef2da44e5c21523c/tornado-6.5.5-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:65a7f1d46d4bb41df1ac99f5fcb685fb25c7e61613742d5108b010975a9a6521", size = 444246, upload-time = "2026-03-10T21:30:46.571Z" }, + { url = "https://files.pythonhosted.org/packages/b2/04/7b5705d5b3c0fab088f434f9c83edac1573830ca49ccf29fb83bf7178eec/tornado-6.5.5-cp39-abi3-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e74c92e8e65086b338fd56333fb9a68b9f6f2fe7ad532645a290a464bcf46be5", size = 447229, upload-time = "2026-03-10T21:30:48.273Z" }, + { url = "https://files.pythonhosted.org/packages/34/01/74e034a30ef59afb4097ef8659515e96a39d910b712a89af76f5e4e1f93c/tornado-6.5.5-cp39-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:435319e9e340276428bbdb4e7fa732c2d399386d1de5686cb331ec8eee754f07", size = 448192, upload-time = "2026-03-10T21:30:51.22Z" }, + { url = "https://files.pythonhosted.org/packages/be/00/fe9e02c5a96429fce1a1d15a517f5d8444f9c412e0bb9eadfbe3b0fc55bf/tornado-6.5.5-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:3f54aa540bdbfee7b9eb268ead60e7d199de5021facd276819c193c0fb28ea4e", size = 448039, upload-time = "2026-03-10T21:30:53.52Z" }, + { url = "https://files.pythonhosted.org/packages/82/9e/656ee4cec0398b1d18d0f1eb6372c41c6b889722641d84948351ae19556d/tornado-6.5.5-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:36abed1754faeb80fbd6e64db2758091e1320f6bba74a4cf8c09cd18ccce8aca", size = 447445, upload-time = "2026-03-10T21:30:55.541Z" }, + { url = "https://files.pythonhosted.org/packages/5a/76/4921c00511f88af86a33de770d64141170f1cfd9c00311aea689949e274e/tornado-6.5.5-cp39-abi3-win32.whl", hash = "sha256:dd3eafaaeec1c7f2f8fdcd5f964e8907ad788fe8a5a32c4426fbbdda621223b7", size = 448582, upload-time = "2026-03-10T21:30:57.142Z" }, + { url = "https://files.pythonhosted.org/packages/2c/23/f6c6112a04d28eed765e374435fb1a9198f73e1ec4b4024184f21faeb1ad/tornado-6.5.5-cp39-abi3-win_amd64.whl", hash = "sha256:6443a794ba961a9f619b1ae926a2e900ac20c34483eea67be4ed8f1e58d3ef7b", size = 448990, upload-time = "2026-03-10T21:30:58.857Z" }, + { url = "https://files.pythonhosted.org/packages/b7/c8/876602cbc96469911f0939f703453c1157b0c826ecb05bdd32e023397d4e/tornado-6.5.5-cp39-abi3-win_arm64.whl", hash = "sha256:2c9a876e094109333f888539ddb2de4361743e5d21eece20688e3e351e4990a6", size = 448016, upload-time = "2026-03-10T21:31:00.43Z" }, +] + [[package]] name = "tox" version = "4.54.0" @@ -1452,6 +1949,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/5f/53/4a33dc81da39db7b31e5622333df361e8fe055b7ec636bd5fea762c9182d/tox_uv_bare-1.35.2-py3-none-any.whl", hash = "sha256:c0d590a41d1054a1ad0874e9e5943ff52402786e3d4599d8f8d37a65b566ef53", size = 22307, upload-time = "2026-05-05T01:34:17.681Z" }, ] +[[package]] +name = "traitlets" +version = "5.15.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/1b/22/40f55b26baeab80c2d7b3f1db0682f8954e4617fee7d90ce634022ef05c6/traitlets-5.15.0.tar.gz", hash = "sha256:4fead733f81cf1c4c938e06f8ca4633896833c9d89eff878159457f4d4392971", size = 163197, upload-time = "2026-05-06T08:05:58.016Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/da/98/a9937a969d018a23badfea0b381f66783649d48e0ea6c41923265c3cbeb3/traitlets-5.15.0-py3-none-any.whl", hash = "sha256:fb36a18867a6803deab09f3c5e0fa81bb7b26a5c9e82501c9933f759166eff40", size = 85877, upload-time = "2026-05-06T08:05:55.853Z" }, +] + [[package]] name = "types-protobuf" version = "7.34.1.20260518" @@ -1564,3 +2070,12 @@ sdist = { url = "https://files.pythonhosted.org/packages/15/ba/1f6e8c957e4932be0 wheels = [ { url = "https://files.pythonhosted.org/packages/f4/34/a9dbe051de88a63eb7408ea66630bac38e72f7f6077d4be58737106860d9/virtualenv-21.3.3-py3-none-any.whl", hash = "sha256:7d5987d8369e098e41406efb780a3d4ca79280097293899e351a6407ee153ab3", size = 7594554, upload-time = "2026-05-13T18:01:27.815Z" }, ] + +[[package]] +name = "wcwidth" +version = "0.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/2c/ee/afaf0f85a9a18fe47a67f1e4422ed6cf1fe642f0ae0a2f81166231303c52/wcwidth-0.7.0.tar.gz", hash = "sha256:90e3a7ea092341c44b99562e75d09e4d5160fe7a3974c6fb842a101a95e7eed0", size = 182132, upload-time = "2026-05-02T16:04:12.653Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/41/52/e465037f5375f43533d1a80b6923955201596a99142ed524d77b571a1418/wcwidth-0.7.0-py3-none-any.whl", hash = "sha256:5d69154c429a82910e241c738cd0e2976fac8a2dd47a1a805f4afed1c0f136f2", size = 110825, upload-time = "2026-05-02T16:04:11.033Z" }, +]