Skip to content

Commit cf4b2b3

Browse files
committed
fix typing, add type guard
1 parent e32c04d commit cf4b2b3

File tree

3 files changed

+32
-3
lines changed

3 files changed

+32
-3
lines changed

flag_engine/identities/traits/types.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@
1111
_UnconstrainedContextValue = Union[None, int, float, bool, str]
1212

1313

14+
def is_trait_value(value: Any) -> TypeGuard[_UnconstrainedContextValue]:
15+
"""
16+
Check if the value is a valid trait value type.
17+
This function is used to determine if a value can be treated as a trait value.
18+
"""
19+
return isinstance(value, get_args(_UnconstrainedContextValue))
20+
21+
1422
def map_any_value_to_trait_value(value: Any) -> _UnconstrainedContextValue:
1523
"""
1624
Try to coerce a value of arbitrary type to a trait value type.

flag_engine/segments/evaluator.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
from contextlib import suppress
77
from functools import lru_cache, wraps
88

9-
import jsonpath_rfc9535 # type: ignore[import-untyped]
9+
import jsonpath_rfc9535 # type: ignore[import]
1010
import semver
1111

1212
from flag_engine.context.mappers import map_environment_identity_to_context
@@ -19,7 +19,7 @@
1919
)
2020
from flag_engine.environments.models import EnvironmentModel
2121
from flag_engine.identities.models import IdentityModel
22-
from flag_engine.identities.traits.types import ContextValue
22+
from flag_engine.identities.traits.types import ContextValue, is_trait_value
2323
from flag_engine.result.types import EvaluationResult, FlagResult, SegmentResult
2424
from flag_engine.segments import constants
2525
from flag_engine.segments.models import SegmentModel
@@ -392,7 +392,8 @@ def _get_context_value_getter(
392392
def getter(context: EvaluationContext) -> ContextValue:
393393
try:
394394
if result := compiled_query.find_one(context):
395-
return result.value
395+
if is_trait_value(value := result.value):
396+
return value
396397
return None
397398
except jsonpath_rfc9535.JSONPathError: # pragma: no cover
398399
# This is supposed to be unreachable, but if it happens,

tests/unit/segments/test_segments_evaluator.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
_matches_context_value,
2222
context_matches_condition,
2323
get_context_segments,
24+
get_context_value,
2425
get_evaluation_result,
2526
get_flag_result_from_feature_context,
2627
get_identity_segments,
@@ -1028,3 +1029,22 @@ def test_get_flag_result_from_feature_context__call_return_expected(
10281029
expected_key,
10291030
]
10301031
)
1032+
1033+
1034+
@pytest.mark.parametrize(
1035+
"property",
1036+
[
1037+
pytest.param("$.identity", id="jsonpath returns an object"),
1038+
'trait key "with quotes"',
1039+
"$.leads.to.nowhere",
1040+
],
1041+
)
1042+
def test_get_context_value__invalid_jsonpath__returns_expected(
1043+
context: EvaluationContext,
1044+
property: str,
1045+
) -> None:
1046+
# Given & When
1047+
result = get_context_value(context, property)
1048+
1049+
# Then
1050+
assert result is None

0 commit comments

Comments
 (0)