Skip to content

Commit a016d8e

Browse files
committed
feat: improved-type
1 parent bcf65af commit a016d8e

5 files changed

Lines changed: 99 additions & 8 deletions

File tree

src/edge_proxy/environments.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,8 +77,8 @@ async def refresh_environment_caches(self):
7777
self.last_updated_at = datetime.now()
7878

7979
def get_flags_response_data(
80-
self, environment_key: str, feature: str = None
81-
) -> dict[str, Any]:
80+
self, environment_key: str, feature: str = ""
81+
) -> dict[str, Any] | list[dict[str, Any]]:
8282
environment_document = self.get_environment(environment_key=environment_key)
8383
is_server_key = environment_key.startswith(SERVER_API_KEY_PREFIX)
8484
server_key_only_feature_ids = environment_document.get("project", {}).get(
@@ -92,6 +92,7 @@ def get_flags_response_data(
9292

9393
context = map_environment_document_to_context(environment_document)
9494
evaluation_result = get_evaluation_result(context)
95+
data: dict[str, Any] | list[dict[str, Any]]
9596

9697
if feature:
9798
if feature not in evaluation_result["flags"]:

src/edge_proxy/feature_utils.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
from typing import Any
2+
from flag_engine.result.types import FlagResult
23

34

45
def build_feature_types_lookup(
@@ -11,9 +12,9 @@ def build_feature_types_lookup(
1112

1213

1314
def filter_out_server_key_only_flags(
14-
flags: list[dict[str, Any]],
15+
flags: list[FlagResult[Any]],
1516
server_key_only_feature_ids: list[int],
16-
) -> list[dict[str, Any]]:
17+
) -> list[FlagResult[Any]]:
1718
return [
1819
flag
1920
for flag in flags
@@ -22,8 +23,8 @@ def filter_out_server_key_only_flags(
2223

2324

2425
def filter_disabled_flags(
25-
flags: list[dict[str, Any]], hide_disabled: bool
26-
) -> list[dict[str, Any]]:
26+
flags: list[FlagResult[Any]], hide_disabled: bool
27+
) -> list[FlagResult[Any]]:
2728
if not hide_disabled:
2829
return flags
2930
return [flag for flag in flags if flag.get("enabled", False)]

src/edge_proxy/mappers.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
11
from typing import Any
22
from flag_engine.engine import ContextValue
3+
from flag_engine.result.types import FlagResult
34

45
from edge_proxy.schemas import APIFeatureStateSchema
56

67
_api_feature_state_schema = APIFeatureStateSchema()
78

89

910
def map_flag_result_to_response_data(
10-
flag_result: dict[str, Any],
11+
flag_result: FlagResult[Any],
1112
feature_types: dict[int, str] | None = None,
1213
) -> dict[str, Any]:
1314
feature_id = flag_result.get("metadata", {}).get("id")
@@ -24,7 +25,7 @@ def map_flag_result_to_response_data(
2425

2526

2627
def map_flag_results_to_response_data(
27-
flag_results: list[dict[str, Any]],
28+
flag_results: list[FlagResult[Any]],
2829
feature_types: dict[int, str] | None = None,
2930
) -> list[dict[str, Any]]:
3031
return [

tests/fixtures/response_data.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,30 @@
5050
}
5151

5252

53+
_multivariate_feature_state = {
54+
"multivariate_feature_state_values": [
55+
{
56+
"id": 1,
57+
"multivariate_feature_option": {"id": 1, "value": "variant_a"},
58+
"percentage_allocation": 50,
59+
},
60+
{
61+
"id": 2,
62+
"multivariate_feature_option": {"id": 2, "value": "variant_b"},
63+
"percentage_allocation": 50,
64+
},
65+
],
66+
"feature_state_value": "control",
67+
"featurestate_uuid": "e4g9c5d3-8b52-6g79-1hfd-cg8g54f51i0g",
68+
"feature": {
69+
"name": "mv_feature",
70+
"type": "MULTIVARIATE",
71+
"id": 4,
72+
},
73+
"enabled": True,
74+
}
75+
76+
5377
_segment_1 = {
5478
"name": "segment_1",
5579
"rules": [
@@ -157,3 +181,33 @@
157181
"project": _project_with_hide_disabled_flags,
158182
"id": 2,
159183
}
184+
185+
186+
_project_with_multivariate = {
187+
"name": "project-with-multivariate",
188+
"organisation": {
189+
"feature_analytics": False,
190+
"name": "org-1",
191+
"id": 1,
192+
"persist_trait_data": True,
193+
"stop_serving_flags": False,
194+
},
195+
"id": 3,
196+
"hide_disabled_flags": False,
197+
"segments": [],
198+
"server_key_only_feature_ids": [],
199+
}
200+
201+
202+
environment_with_multivariate_feature = {
203+
"updated_at": "1969-07-20T20:17:40Z",
204+
"name": "environment_with_multivariate",
205+
"feature_states": [
206+
_environment_feature_state_1,
207+
_multivariate_feature_state,
208+
],
209+
"identity_overrides": [],
210+
"api_key": "env_with_multivariate_key",
211+
"project": _project_with_multivariate,
212+
"id": 3,
213+
}

tests/test_server.py

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
from tests.fixtures.response_data import (
1010
environment_1,
1111
environment_with_hide_disabled_flags,
12+
environment_with_multivariate_feature,
1213
)
1314

1415
if typing.TYPE_CHECKING:
@@ -449,3 +450,36 @@ def test_post_identity__client_key__hide_disabled_flags_disabled__returns_all_fl
449450
response_data = response.json()
450451
flags = response_data["flags"]
451452
assert len(flags) == 2
453+
454+
455+
def test_get_flags__multivariate_feature__returns_correct_type(
456+
mocker: MockerFixture,
457+
client: TestClient,
458+
) -> None:
459+
# Given
460+
environment_key = "test_environment_key"
461+
mocked_environment_cache = mocker.patch(
462+
"edge_proxy.server.environment_service.cache"
463+
)
464+
mocked_environment_cache.get_environment.return_value = (
465+
environment_with_multivariate_feature
466+
)
467+
mocked_environment_cache.get_feature_types.return_value = None
468+
469+
# When
470+
response = client.get(
471+
"/api/v1/flags", headers={"X-Environment-Key": environment_key}
472+
)
473+
474+
# Then
475+
assert response.status_code == 200
476+
flags = response.json()
477+
assert len(flags) == 2
478+
479+
mv_flag = next(f for f in flags if f["feature"]["name"] == "mv_feature")
480+
assert mv_flag["feature"]["type"] == "MULTIVARIATE"
481+
assert mv_flag["feature"]["id"] == 4
482+
assert mv_flag["enabled"] is True
483+
484+
standard_flag = next(f for f in flags if f["feature"]["name"] == "feature_1")
485+
assert standard_flag["feature"]["type"] == "STANDARD"

0 commit comments

Comments
 (0)