From 50369fb46d3c1a11a81b9e36579349a8c59d588c Mon Sep 17 00:00:00 2001 From: wadii Date: Mon, 4 May 2026 10:47:26 +0200 Subject: [PATCH 1/2] feat: apply rules based on type instead of hardcoded all --- flag_engine/segments/evaluator.py | 19 +++++--- tests/engine_tests/engine-test-data | 2 +- tests/unit/segments/fixtures.py | 42 ++++++++++++++++++ .../unit/segments/test_segments_evaluator.py | 44 +++++++++++++++++++ 4 files changed, 100 insertions(+), 7 deletions(-) diff --git a/flag_engine/segments/evaluator.py b/flag_engine/segments/evaluator.py index 0b8f8fc..53a4b44 100644 --- a/flag_engine/segments/evaluator.py +++ b/flag_engine/segments/evaluator.py @@ -249,14 +249,21 @@ def context_matches_rule( else True ) - return matches_conditions and all( - context_matches_rule( - context=context, - rule=rule, - segment_key=segment_key, + matches_rules = ( + get_matching_function(rule["type"])( + [ + context_matches_rule( + context=context, + rule=sub_rule, + segment_key=segment_key, + ) + for sub_rule in rules + ] ) - for rule in rule.get("rules") or [] + if (rules := rule.get("rules")) + else True ) + return matches_conditions and matches_rules def context_matches_condition( diff --git a/tests/engine_tests/engine-test-data b/tests/engine_tests/engine-test-data index 9307930..6c381cc 160000 --- a/tests/engine_tests/engine-test-data +++ b/tests/engine_tests/engine-test-data @@ -1 +1 @@ -Subproject commit 9307930e9e64482a35e7d6b254225addb6e44687 +Subproject commit 6c381ccadf6da73dedf6aff35e96d24546359a1e diff --git a/tests/unit/segments/fixtures.py b/tests/unit/segments/fixtures.py index 934311c..1f0d909 100644 --- a/tests/unit/segments/fixtures.py +++ b/tests/unit/segments/fixtures.py @@ -110,6 +110,48 @@ ], } +segment_any_with_nested_all_groups: SegmentContext = { + "key": "7", + "name": "segment_any_with_nested_all_groups", + "rules": [ + { + "type": constants.ALL_RULE, + "rules": [ + { + "type": constants.ANY_RULE, + "rules": [ + { + "type": constants.ALL_RULE, + "conditions": [ + { + "operator": constants.EQUAL, + "property": trait_key_1, + "value": trait_value_1, + }, + { + "operator": constants.EQUAL, + "property": trait_key_2, + "value": trait_value_2, + }, + ], + }, + { + "type": constants.ALL_RULE, + "conditions": [ + { + "operator": constants.EQUAL, + "property": trait_key_3, + "value": trait_value_3, + }, + ], + }, + ], + } + ], + } + ], +} + segment_conditions_and_nested_rules: SegmentContext = { "key": "6", "name": "segment_multiple_conditions_all_and_nested_rules", diff --git a/tests/unit/segments/test_segments_evaluator.py b/tests/unit/segments/test_segments_evaluator.py index 844d4fa..8e55e90 100644 --- a/tests/unit/segments/test_segments_evaluator.py +++ b/tests/unit/segments/test_segments_evaluator.py @@ -23,6 +23,7 @@ from flag_engine.segments.types import ConditionOperator from tests.unit.segments.fixtures import ( empty_segment, + segment_any_with_nested_all_groups, segment_conditions_and_nested_rules, segment_multiple_conditions_all, segment_multiple_conditions_any, @@ -212,6 +213,49 @@ }, True, ), + ( + segment_any_with_nested_all_groups, + { + "environment": {"key": "key", "name": "Environment"}, + "identity": { + "identifier": "foo", + "key": "key_foo", + "traits": { + trait_key_1: trait_value_1, + trait_key_2: trait_value_2, + }, + }, + }, + True, + ), + ( + segment_any_with_nested_all_groups, + { + "environment": {"key": "key", "name": "Environment"}, + "identity": { + "identifier": "foo", + "key": "key_foo", + "traits": { + trait_key_3: trait_value_3, + }, + }, + }, + True, + ), + ( + segment_any_with_nested_all_groups, + { + "environment": {"key": "key", "name": "Environment"}, + "identity": { + "identifier": "foo", + "key": "key_foo", + "traits": { + trait_key_1: trait_value_1, + }, + }, + }, + False, + ), ), ) def test_context_in_segment( From 8cb614c45209c638f90d727f9f9750840759545a Mon Sep 17 00:00:00 2001 From: wadii Date: Mon, 4 May 2026 17:45:33 +0200 Subject: [PATCH 2/2] feat: use generator and removed tests --- flag_engine/segments/evaluator.py | 28 +++++------- tests/unit/segments/fixtures.py | 41 ----------------- .../unit/segments/test_segments_evaluator.py | 44 ------------------- 3 files changed, 12 insertions(+), 101 deletions(-) diff --git a/flag_engine/segments/evaluator.py b/flag_engine/segments/evaluator.py index 53a4b44..65a380b 100644 --- a/flag_engine/segments/evaluator.py +++ b/flag_engine/segments/evaluator.py @@ -236,14 +236,12 @@ def context_matches_rule( ) -> bool: matches_conditions = ( get_matching_function(rule["type"])( - [ - context_matches_condition( - context=context, - condition=condition, - segment_key=segment_key, - ) - for condition in conditions - ] + context_matches_condition( + context=context, + condition=condition, + segment_key=segment_key, + ) + for condition in conditions ) if (conditions := rule.get("conditions")) else True @@ -251,14 +249,12 @@ def context_matches_rule( matches_rules = ( get_matching_function(rule["type"])( - [ - context_matches_rule( - context=context, - rule=sub_rule, - segment_key=segment_key, - ) - for sub_rule in rules - ] + context_matches_rule( + context=context, + rule=sub_rule, + segment_key=segment_key, + ) + for sub_rule in rules ) if (rules := rule.get("rules")) else True diff --git a/tests/unit/segments/fixtures.py b/tests/unit/segments/fixtures.py index 1f0d909..5ea6698 100644 --- a/tests/unit/segments/fixtures.py +++ b/tests/unit/segments/fixtures.py @@ -110,47 +110,6 @@ ], } -segment_any_with_nested_all_groups: SegmentContext = { - "key": "7", - "name": "segment_any_with_nested_all_groups", - "rules": [ - { - "type": constants.ALL_RULE, - "rules": [ - { - "type": constants.ANY_RULE, - "rules": [ - { - "type": constants.ALL_RULE, - "conditions": [ - { - "operator": constants.EQUAL, - "property": trait_key_1, - "value": trait_value_1, - }, - { - "operator": constants.EQUAL, - "property": trait_key_2, - "value": trait_value_2, - }, - ], - }, - { - "type": constants.ALL_RULE, - "conditions": [ - { - "operator": constants.EQUAL, - "property": trait_key_3, - "value": trait_value_3, - }, - ], - }, - ], - } - ], - } - ], -} segment_conditions_and_nested_rules: SegmentContext = { "key": "6", diff --git a/tests/unit/segments/test_segments_evaluator.py b/tests/unit/segments/test_segments_evaluator.py index 8e55e90..844d4fa 100644 --- a/tests/unit/segments/test_segments_evaluator.py +++ b/tests/unit/segments/test_segments_evaluator.py @@ -23,7 +23,6 @@ from flag_engine.segments.types import ConditionOperator from tests.unit.segments.fixtures import ( empty_segment, - segment_any_with_nested_all_groups, segment_conditions_and_nested_rules, segment_multiple_conditions_all, segment_multiple_conditions_any, @@ -213,49 +212,6 @@ }, True, ), - ( - segment_any_with_nested_all_groups, - { - "environment": {"key": "key", "name": "Environment"}, - "identity": { - "identifier": "foo", - "key": "key_foo", - "traits": { - trait_key_1: trait_value_1, - trait_key_2: trait_value_2, - }, - }, - }, - True, - ), - ( - segment_any_with_nested_all_groups, - { - "environment": {"key": "key", "name": "Environment"}, - "identity": { - "identifier": "foo", - "key": "key_foo", - "traits": { - trait_key_3: trait_value_3, - }, - }, - }, - True, - ), - ( - segment_any_with_nested_all_groups, - { - "environment": {"key": "key", "name": "Environment"}, - "identity": { - "identifier": "foo", - "key": "key_foo", - "traits": { - trait_key_1: trait_value_1, - }, - }, - }, - False, - ), ), ) def test_context_in_segment(