Skip to content

Commit bdc9a1a

Browse files
committed
avoid mutating input
1 parent 327631b commit bdc9a1a

File tree

2 files changed

+12
-9
lines changed

2 files changed

+12
-9
lines changed

flag_engine/segments/evaluator.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
import typing
77
import warnings
88
from contextlib import suppress
9+
from copy import deepcopy
910
from functools import lru_cache, partial, wraps
1011

1112
import jsonpath_rfc9535
@@ -57,7 +58,7 @@ def get_evaluation_result(
5758
:param context: the evaluation context
5859
:return: EvaluationResult containing the context, flags, and segments
5960
"""
60-
enrich_context(context)
61+
context = enrich_context(context)
6162
segments, segment_overrides = evaluate_segments(context)
6263
flags = evaluate_features(context, segment_overrides)
6364

@@ -68,19 +69,21 @@ def get_evaluation_result(
6869

6970

7071
def enrich_context(
71-
context: _EvaluationContextAnyMeta,
72-
) -> None:
72+
context: EvaluationContext[SegmentMetadataT, FeatureMetadataT],
73+
) -> EvaluationContext[SegmentMetadataT, FeatureMetadataT]:
7374
"""
7475
Enrich the evaluation context in-place by ensuring that:
7576
- `$.identity.key` is set
7677
7778
:param context: the evaluation context to enrich
7879
"""
80+
context = deepcopy(context)
7981
if identity_context := context.get("identity"):
8082
if not identity_context.get("key"):
8183
identity_context["key"] = (
8284
f"{context['environment']['key']}_{identity_context['identifier']}"
8385
)
86+
return context
8487

8588

8689
def evaluate_segments(

tests/unit/test_engine.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -377,13 +377,13 @@ class CustomSegmentMetadata(TypedDict):
377377
result = get_evaluation_result(evaluation_context)
378378

379379
# Then
380-
assert result["segments"][0]["metadata"] is segment_metadata
380+
assert result["segments"][0]["metadata"] == segment_metadata
381381
reveal_type(result["segments"][0]["metadata"]) # CustomSegmentMetadata
382382

383383

384384
def test_segment_metadata_generic_type__default__returns_expected() -> None:
385385
# Given
386-
segment_metadata = {"hello": object()}
386+
segment_metadata = {"hello": [{"nested": True}]}
387387

388388
# we don't specify generic type, but mypy is happy with this
389389
evaluation_context: EvaluationContext = {
@@ -414,7 +414,7 @@ def test_segment_metadata_generic_type__default__returns_expected() -> None:
414414
result = get_evaluation_result(evaluation_context)
415415

416416
# Then
417-
assert result["segments"][0]["metadata"] is segment_metadata
417+
assert result["segments"][0]["metadata"] == segment_metadata
418418
reveal_type(result["segments"][0]["metadata"]) # Mapping[str, object]
419419

420420

@@ -471,13 +471,13 @@ class CustomFeatureMetadata(TypedDict):
471471
result = get_evaluation_result(evaluation_context)
472472

473473
# Then
474-
assert result["flags"]["feature_1"]["metadata"] is feature_metadata
474+
assert result["flags"]["feature_1"]["metadata"] == feature_metadata
475475
reveal_type(result["flags"]["feature_1"]["metadata"]) # CustomFeatureMetadata
476476

477477

478478
def test_feature_metadata_generic_type__default__returns_expected() -> None:
479479
# Given
480-
feature_metadata = {"hello": object()}
480+
feature_metadata = {"hello": [{"nested": True}]}
481481

482482
# we don't specify generic type, but mypy is happy with this
483483
evaluation_context: EvaluationContext = {
@@ -525,5 +525,5 @@ def test_feature_metadata_generic_type__default__returns_expected() -> None:
525525
result = get_evaluation_result(evaluation_context)
526526

527527
# Then
528-
assert result["flags"]["feature_1"]["metadata"] is feature_metadata
528+
assert result["flags"]["feature_1"]["metadata"] == feature_metadata
529529
reveal_type(result["flags"]["feature_1"]["metadata"]) # Mapping[str, object]

0 commit comments

Comments
 (0)