Skip to content

Commit f00647c

Browse files
committed
feat: extracted-resolve-trait-values
1 parent f8cdca5 commit f00647c

File tree

4 files changed

+46
-32
lines changed

4 files changed

+46
-32
lines changed

flagsmith/analytics.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ def _handle_flush_result(
193193
response = future.result()
194194
response.raise_for_status()
195195
except Exception:
196-
logger.warning("Failed to flush pipeline analytics, re-queuing events")
196+
logger.warning("Failed to flush pipeline analytics, re-queuing events", exc_info=True)
197197
with self._lock:
198198
self._buffer = events + self._buffer
199199
self._buffer = self._buffer[: self._max_buffer]

flagsmith/flagsmith.py

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
map_environment_document_to_context,
2020
map_environment_document_to_environment_updated_at,
2121
map_segment_results_to_identity_segments,
22+
resolve_trait_values,
2223
)
2324
from flagsmith.models import DefaultFlag, Flags, Segment
2425
from flagsmith.offline_handlers import OfflineHandler
@@ -318,21 +319,10 @@ def track_event(
318319
self._pipeline_analytics_processor.record_custom_event(
319320
event_name=event_name,
320321
identity_identifier=identity_identifier,
321-
traits=self._resolve_traits(traits),
322+
traits=resolve_trait_values(traits),
322323
metadata=metadata,
323324
)
324325

325-
@staticmethod
326-
def _resolve_traits(
327-
traits: typing.Optional[TraitMapping],
328-
) -> typing.Optional[typing.Dict[str, typing.Any]]:
329-
if not traits:
330-
return None
331-
return {
332-
key: (val["value"] if isinstance(val, dict) else val)
333-
for key, val in traits.items()
334-
}
335-
336326
def update_environment(self) -> None:
337327
try:
338328
environment_data = self._get_json_response(
@@ -414,7 +404,7 @@ def _get_identity_flags_from_document(
414404
default_flag_handler=self.default_flag_handler,
415405
pipeline_analytics_processor=self._pipeline_analytics_processor,
416406
identity_identifier=identifier,
417-
traits=self._resolve_traits(traits),
407+
traits=resolve_trait_values(traits),
418408
)
419409

420410
def _get_environment_flags_from_api(self) -> Flags:
@@ -461,7 +451,7 @@ def _get_identity_flags_from_api(
461451
default_flag_handler=self.default_flag_handler,
462452
pipeline_analytics_processor=self._pipeline_analytics_processor,
463453
identity_identifier=identifier,
464-
traits=self._resolve_traits(traits),
454+
traits=resolve_trait_values(traits),
465455
)
466456
except FlagsmithAPIError:
467457
if self.offline_handler:

flagsmith/mappers.py

Lines changed: 14 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
SegmentMetadata,
2828
StreamEvent,
2929
TraitConfig,
30+
TraitMapping,
3031
)
3132
from flagsmith.utils.datetime import fromisoformat
3233

@@ -75,31 +76,27 @@ def map_environment_document_to_environment_updated_at(
7576
return updated_at.astimezone(tz=timezone.utc)
7677

7778

79+
def resolve_trait_values(
80+
traits: typing.Optional[TraitMapping],
81+
) -> typing.Optional[typing.Dict[str, typing.Any]]:
82+
if not traits:
83+
return None
84+
return {
85+
key: (val["value"] if isinstance(val, dict) else val)
86+
for key, val in traits.items()
87+
}
88+
89+
7890
def map_context_and_identity_data_to_context(
7991
context: SDKEvaluationContext,
8092
identifier: str,
81-
traits: typing.Optional[
82-
typing.Mapping[
83-
str,
84-
typing.Union[
85-
ContextValue,
86-
TraitConfig,
87-
],
88-
]
89-
],
93+
traits: typing.Optional[TraitMapping] = None,
9094
) -> SDKEvaluationContext:
9195
return {
9296
**context,
9397
"identity": {
9498
"identifier": identifier,
95-
"traits": {
96-
trait_key: (
97-
trait_value_or_config["value"]
98-
if isinstance(trait_value_or_config, dict)
99-
else trait_value_or_config
100-
)
101-
for trait_key, trait_value_or_config in (traits or {}).items()
102-
},
99+
"traits": resolve_trait_values(traits) or {},
103100
},
104101
}
105102

tests/test_flagsmith.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -997,3 +997,30 @@ def test_get_identity_flags_passes_identity_and_traits(
997997
identity_identifier="user123",
998998
traits={"plan": "premium"},
999999
)
1000+
1001+
1002+
@responses.activate()
1003+
def test_get_identity_flags_resolves_trait_config_values(
1004+
mocker: MockerFixture, api_key: str, identities_json: str
1005+
) -> None:
1006+
config = PipelineAnalyticsConfig(analytics_server_url="http://test/")
1007+
flagsmith = Flagsmith(environment_key=api_key, pipeline_analytics_config=config)
1008+
1009+
mock_record = mocker.patch.object(
1010+
flagsmith._pipeline_analytics_processor, "record_evaluation_event"
1011+
)
1012+
1013+
responses.add(method="POST", url=flagsmith.identities_url, body=identities_json)
1014+
flags = flagsmith.get_identity_flags(
1015+
"user123",
1016+
traits={"plan": {"value": "premium", "transient": True}},
1017+
)
1018+
flags.get_flag("some_feature")
1019+
1020+
mock_record.assert_called_once_with(
1021+
flag_key="some_feature",
1022+
enabled=True,
1023+
value="some-value",
1024+
identity_identifier="user123",
1025+
traits={"plan": "premium"},
1026+
)

0 commit comments

Comments
 (0)