Skip to content

Commit aaaaabb

Browse files
committed
adapt to new EvaluationResult schema
1 parent e650ecf commit aaaaabb

5 files changed

Lines changed: 45 additions & 58 deletions

File tree

flag_engine/result/types.py

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,18 @@
11
# generated by datamodel-codegen:
2-
# filename: result.json
3-
# timestamp: 2025-08-11T11:47:46+00:00
2+
# filename: https://raw.githubusercontent.com/Flagsmith/flagsmith/refs/heads/chore/improve-evaluation-result/sdk/evaluation-result.json # noqa: E501
3+
# timestamp: 2025-10-01T11:31:34+00:00
44

55
from __future__ import annotations
66

7-
from typing import Any, List, Optional, TypedDict
8-
9-
from typing_extensions import NotRequired
10-
11-
from flag_engine.context.types import EvaluationContext
7+
from typing import Any, Dict, List, TypedDict
128

139

1410
class FlagResult(TypedDict):
15-
name: str
1611
feature_key: str
12+
name: str
1713
enabled: bool
18-
value: NotRequired[Optional[Any]]
19-
reason: NotRequired[str]
14+
value: Any
15+
reason: str
2016

2117

2218
class SegmentResult(TypedDict):
@@ -25,6 +21,5 @@ class SegmentResult(TypedDict):
2521

2622

2723
class EvaluationResult(TypedDict):
28-
context: EvaluationContext
29-
flags: List[FlagResult]
24+
flags: Dict[str, FlagResult]
3025
segments: List[SegmentResult]

flag_engine/segments/constants.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@
2121
IS_NOT_SET: ConditionOperator = "IS_NOT_SET"
2222
IN: ConditionOperator = "IN"
2323

24-
# Lowest possible priority for segment overrides
24+
# Weakest possible priority for segment overrides
2525
DEFAULT_PRIORITY = float("inf")

flag_engine/segments/evaluator.py

Lines changed: 12 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ def get_evaluation_result(context: EvaluationContext) -> EvaluationResult:
4040
:return: EvaluationResult containing the context, flags, and segments
4141
"""
4242
segments: list[SegmentResult] = []
43-
flags: list[FlagResult] = []
43+
flags: dict[str, FlagResult] = {}
4444

4545
segment_feature_contexts: dict[SupportsStr, FeatureContextWithSegmentName] = {}
4646

@@ -82,29 +82,25 @@ def get_evaluation_result(context: EvaluationContext) -> EvaluationResult:
8282
else None
8383
)
8484
for feature_context in (context.get("features") or {}).values():
85+
feature_name = feature_context["name"]
8586
if feature_context_with_segment_name := segment_feature_contexts.get(
8687
feature_context["feature_key"],
8788
):
8889
feature_context = feature_context_with_segment_name["feature_context"]
89-
flags.append(
90-
{
91-
"enabled": feature_context["enabled"],
92-
"feature_key": feature_context["feature_key"],
93-
"name": feature_context["name"],
94-
"reason": f"TARGETING_MATCH; segment={feature_context_with_segment_name['segment_name']}",
95-
"value": feature_context.get("value"),
96-
}
97-
)
90+
flags[feature_name] = {
91+
"enabled": feature_context["enabled"],
92+
"feature_key": feature_context["feature_key"],
93+
"name": feature_context["name"],
94+
"reason": f"TARGETING_MATCH; segment={feature_context_with_segment_name['segment_name']}",
95+
"value": feature_context.get("value"),
96+
}
9897
continue
99-
flags.append(
100-
get_flag_result_from_feature_context(
101-
feature_context=feature_context,
102-
key=identity_key,
103-
)
98+
flags[feature_name] = get_flag_result_from_feature_context(
99+
feature_context=feature_context,
100+
key=identity_key,
104101
)
105102

106103
return {
107-
"context": context,
108104
"flags": flags,
109105
"segments": segments,
110106
}

tests/unit/test_engine.py

Lines changed: 24 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
from flag_engine.context.types import EvaluationContext, IdentityContext, SegmentContext
44
from flag_engine.engine import get_evaluation_result
5+
from flag_engine.result.types import EvaluationResult
56

67

78
def test_get_evaluation_result__no_overrides__returns_expected(
@@ -11,26 +12,25 @@ def test_get_evaluation_result__no_overrides__returns_expected(
1112
result = get_evaluation_result(context)
1213

1314
# Then
14-
assert result == {
15-
"context": context,
16-
"flags": [
17-
{
15+
assert result == EvaluationResult(
16+
flags={
17+
"feature_1": {
1818
"enabled": True,
1919
"feature_key": "1",
2020
"name": "feature_1",
2121
"reason": "DEFAULT",
2222
"value": None,
2323
},
24-
{
24+
"feature_2": {
2525
"enabled": False,
2626
"feature_key": "2",
2727
"name": "feature_2",
2828
"reason": "DEFAULT",
2929
"value": None,
3030
},
31-
],
32-
"segments": [],
33-
}
31+
},
32+
segments=[],
33+
)
3434

3535

3636
def test_get_evaluation_result__segment_override__returns_expected(
@@ -41,23 +41,22 @@ def test_get_evaluation_result__segment_override__returns_expected(
4141

4242
# Then
4343
assert result == {
44-
"context": context_in_segment,
45-
"flags": [
46-
{
44+
"flags": {
45+
"feature_1": {
4746
"enabled": False,
4847
"feature_key": "1",
4948
"name": "feature_1",
5049
"reason": "TARGETING_MATCH; segment=my_segment",
5150
"value": "segment_override",
5251
},
53-
{
52+
"feature_2": {
5453
"enabled": False,
5554
"feature_key": "2",
5655
"name": "feature_2",
5756
"reason": "DEFAULT",
5857
"value": None,
5958
},
60-
],
59+
},
6160
"segments": [{"key": "1", "name": "my_segment"}],
6261
}
6362

@@ -99,23 +98,22 @@ def test_get_evaluation_result__identity_override__returns_expected(
9998

10099
# Then
101100
assert result == {
102-
"context": context,
103-
"flags": [
104-
{
101+
"flags": {
102+
"feature_1": {
105103
"enabled": True,
106104
"feature_key": "1",
107105
"name": "feature_1",
108106
"reason": "TARGETING_MATCH; segment=identity_overrides",
109107
"value": "overridden_for_identity",
110108
},
111-
{
109+
"feature_2": {
112110
"enabled": False,
113111
"feature_key": "2",
114112
"name": "feature_2",
115113
"reason": "DEFAULT",
116114
"value": None,
117115
},
118-
],
116+
},
119117
"segments": [
120118
{
121119
"key": "",
@@ -207,23 +205,22 @@ def test_get_evaluation_result__two_segments_override_same_feature__returns_expe
207205

208206
# Then
209207
assert result == {
210-
"context": context_in_segments,
211-
"flags": [
212-
{
208+
"flags": {
209+
"feature_1": {
213210
"enabled": True,
214211
"feature_key": "1",
215212
"name": "feature_1",
216213
"reason": "TARGETING_MATCH; segment=higher_priority_segment",
217214
"value": "segment_override_other",
218215
},
219-
{
216+
"feature_2": {
220217
"enabled": False,
221218
"feature_key": "2",
222219
"name": "feature_2",
223220
"reason": "DEFAULT",
224221
"value": None,
225222
},
226-
],
223+
},
227224
"segments": [
228225
{"key": "1", "name": "my_segment"},
229226
{"key": "3", "name": "higher_priority_segment"},
@@ -338,23 +335,22 @@ def test_get_evaluation_result__segment_override__no_priority__returns_expected(
338335

339336
# Then
340337
assert result == {
341-
"context": context,
342-
"flags": [
343-
{
338+
"flags": {
339+
"feature_1": {
344340
"enabled": True,
345341
"feature_key": "1",
346342
"name": "feature_1",
347343
"reason": "TARGETING_MATCH; segment=segment_with_override_priority",
348344
"value": "overridden_with_priority",
349345
},
350-
{
346+
"feature_2": {
351347
"enabled": False,
352348
"feature_key": "2",
353349
"name": "feature_2",
354350
"reason": "TARGETING_MATCH; segment=another_segment",
355351
"value": "moose",
356352
},
357-
],
353+
},
358354
"segments": [
359355
{"key": "1", "name": "segment_without_override_priority"},
360356
{"key": "2", "name": "segment_with_override_priority"},

0 commit comments

Comments
 (0)