Skip to content

Commit 649d987

Browse files
committed
refactor: rename get_feature_toggle to evaluate
1 parent a70bcd8 commit 649d987

File tree

3 files changed

+35
-46
lines changed

3 files changed

+35
-46
lines changed

aws_lambda_powertools/utilities/feature_toggles/feature_flags.py

+9-12
Original file line numberDiff line numberDiff line change
@@ -103,9 +103,7 @@ def get_configuration(self) -> Dict[str, Any]:
103103
self._schema_validator.validate_json_schema(config)
104104
return config
105105

106-
def get_feature_toggle(
107-
self, *, feature_name: str, context: Optional[Dict[str, Any]] = None, value_if_missing: bool
108-
) -> bool:
106+
def evaluate(self, *, feature_name: str, context: Optional[Dict[str, Any]] = None, default: bool) -> bool:
109107
"""Get a feature toggle boolean value. Value is calculated according to a set of rules and conditions.
110108
111109
See below for explanation.
@@ -117,10 +115,9 @@ def get_feature_toggle(
117115
context: Optional[Dict[str, Any]]
118116
dict of attributes that you would like to match the rules
119117
against, can be {'tenant_id: 'X', 'username':' 'Y', 'region': 'Z'} etc.
120-
value_if_missing: bool
121-
this will be the returned value in case the feature toggle doesn't exist in
122-
the schema or there has been an error while fetching the
123-
configuration from appconfig
118+
default: bool
119+
default value if feature flag doesn't exist in the schema,
120+
or there has been an error while fetching the configuration from appconfig
124121
125122
Returns
126123
------
@@ -138,16 +135,16 @@ def get_feature_toggle(
138135
try:
139136
toggles_dict: Dict[str, Any] = self.get_configuration()
140137
except ConfigurationError:
141-
logger.error("unable to get feature toggles JSON, returning provided value_if_missing value")
142-
return value_if_missing
138+
logger.error("unable to get feature toggles JSON, returning provided default value")
139+
return default
143140

144141
feature: Dict[str, Dict] = toggles_dict.get(schema.FEATURES_KEY, {}).get(feature_name, None)
145142
if feature is None:
146143
logger.warning(
147-
f"feature does not appear in configuration, using provided value_if_missing, "
148-
f"feature_name={feature_name}, value_if_missing={value_if_missing}"
144+
f"feature does not appear in configuration, using provided default, "
145+
f"feature_name={feature_name}, default={default}"
149146
)
150-
return value_if_missing
147+
return default
151148

152149
rules_list = feature.get(schema.RULES_KEY)
153150
feature_default_value = feature.get(schema.FEATURE_DEFAULT_VAL_KEY)

docs/utilities/feature_flags.md

+5-3
Original file line numberDiff line numberDiff line change
@@ -63,9 +63,11 @@ Potential changes to be validated when docs are in a better shape
6363
- [x] ~~`rules_context` to `context`~~
6464
- [x] `ConfigurationStore` to `FeatureFlags`
6565
- [x] `StoreProvider` to `StoreProvider`
66-
- [ ] Use `base.py` for interfaces for consistency (e.g. Metrics, Tracer, etc.)
66+
- [x] ~~Use `base.py` for interfaces for consistency (e.g. Metrics, Tracer, etc.)~~
67+
- [x] ~~AppConfig construct parameter names for consistency (e.g. `configuration_name` -> `name`, `service` -> `application`)~~
68+
- [x] ~~Rename `value_if_missing` param to `default` to match Python consistency (e.g. `os.getenv("VAR", default=False)`)~~
69+
- [x] ~~Review `get_feature` in favour of `evaluate`~~
6770
- [ ] Some docstrings and logger refer to AWS AppConfig only (outdated given StoreProvider)
6871
- [ ] Review why we're testing a private method(`is_rule_matched`)
69-
- [x] AppConfig construct parameter names for consistency (e.g. `configuration_name` -> `name`, `service` -> `application`)
7072
- [ ] Review `get_configuration`, `get_json_configuration`
71-
- [ ] Review `get_feature` in favour of `get_feature_toggle`
73+
- [ ] Review potentially redundant logging

tests/functional/feature_toggles/test_feature_toggles.py

+21-31
Original file line numberDiff line numberDiff line change
@@ -68,18 +68,18 @@ def test_toggles_rule_does_not_match(mocker, config):
6868
}
6969

7070
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
71-
toggle = conf_store.get_feature_toggle(feature_name="my_feature", context={}, value_if_missing=False)
71+
toggle = conf_store.evaluate(feature_name="my_feature", context={}, default=False)
7272
assert toggle == expected_value
7373

7474

7575
# this test checks that if you try to get a feature that doesn't exist in the schema,
76-
# you get the default value of False that was sent to the get_feature_toggle API
76+
# you get the default value of False that was sent to the evaluate API
7777
def test_toggles_no_conditions_feature_does_not_exist(mocker, config):
7878
expected_value = False
7979
mocked_app_config_schema = {"features": {"my_fake_feature": {"feature_default_value": True}}}
8080

8181
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
82-
toggle = conf_store.get_feature_toggle(feature_name="my_feature", context={}, value_if_missing=expected_value)
82+
toggle = conf_store.evaluate(feature_name="my_feature", context={}, default=expected_value)
8383
assert toggle == expected_value
8484

8585

@@ -89,9 +89,7 @@ def test_toggles_no_rules(mocker, config):
8989
expected_value = True
9090
mocked_app_config_schema = {"features": {"my_feature": {"feature_default_value": expected_value}}}
9191
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
92-
toggle = conf_store.get_feature_toggle(
93-
feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, value_if_missing=False
94-
)
92+
toggle = conf_store.evaluate(feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False)
9593
assert toggle == expected_value
9694

9795

@@ -119,9 +117,7 @@ def test_toggles_conditions_no_match(mocker, config):
119117
},
120118
}
121119
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
122-
toggle = conf_store.get_feature_toggle(
123-
feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, value_if_missing=False
124-
)
120+
toggle = conf_store.evaluate(feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False)
125121
assert toggle == expected_value
126122

127123

@@ -156,13 +152,13 @@ def test_toggles_conditions_rule_match_equal_multiple_conditions(mocker, config)
156152
},
157153
}
158154
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
159-
toggle = conf_store.get_feature_toggle(
155+
toggle = conf_store.evaluate(
160156
feature_name="my_feature",
161157
context={
162158
"tenant_id": tenant_id_val,
163159
"username": username_val,
164160
},
165-
value_if_missing=True,
161+
default=True,
166162
)
167163
assert toggle == expected_value
168164

@@ -198,9 +194,7 @@ def test_toggles_conditions_no_rule_match_equal_multiple_conditions(mocker, conf
198194
},
199195
}
200196
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
201-
toggle = conf_store.get_feature_toggle(
202-
feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, value_if_missing=False
203-
)
197+
toggle = conf_store.evaluate(feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False)
204198
assert toggle == expected_val
205199

206200

@@ -259,25 +253,25 @@ def test_toggles_conditions_rule_match_multiple_actions_multiple_rules_multiple_
259253

260254
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
261255
# match first rule
262-
toggle = conf_store.get_feature_toggle(
263-
feature_name="my_feature", context={"tenant_id": "6", "username": "abcd"}, value_if_missing=False
256+
toggle = conf_store.evaluate(
257+
feature_name="my_feature", context={"tenant_id": "6", "username": "abcd"}, default=False
264258
)
265259
assert toggle == expected_value_first_check
266260
# match second rule
267-
toggle = conf_store.get_feature_toggle(
268-
feature_name="my_feature", context={"tenant_id": "4446", "username": "az"}, value_if_missing=False
261+
toggle = conf_store.evaluate(
262+
feature_name="my_feature", context={"tenant_id": "4446", "username": "az"}, default=False
269263
)
270264
assert toggle == expected_value_second_check
271265
# match no rule
272-
toggle = conf_store.get_feature_toggle(
273-
feature_name="my_feature", context={"tenant_id": "11114446", "username": "ab"}, value_if_missing=False
266+
toggle = conf_store.evaluate(
267+
feature_name="my_feature", context={"tenant_id": "11114446", "username": "ab"}, default=False
274268
)
275269
assert toggle == expected_value_third_check
276270
# feature doesn't exist
277-
toggle = conf_store.get_feature_toggle(
271+
toggle = conf_store.evaluate(
278272
feature_name="my_fake_feature",
279273
context={"tenant_id": "11114446", "username": "ab"},
280-
value_if_missing=expected_value_fourth_case,
274+
default=expected_value_fourth_case,
281275
)
282276
assert toggle == expected_value_fourth_case
283277

@@ -306,9 +300,7 @@ def test_toggles_match_rule_with_contains_action(mocker, config):
306300
},
307301
}
308302
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
309-
toggle = conf_store.get_feature_toggle(
310-
feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, value_if_missing=False
311-
)
303+
toggle = conf_store.evaluate(feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False)
312304
assert toggle == expected_value
313305

314306

@@ -335,9 +327,7 @@ def test_toggles_no_match_rule_with_contains_action(mocker, config):
335327
},
336328
}
337329
conf_store = init_configuration_store(mocker, mocked_app_config_schema, config)
338-
toggle = conf_store.get_feature_toggle(
339-
feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, value_if_missing=False
340-
)
330+
toggle = conf_store.evaluate(feature_name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False)
341331
assert toggle == expected_value
342332

343333

@@ -425,10 +415,10 @@ def test_get_feature_toggle_handles_error(mocker, config):
425415
schema_fetcher = init_fetcher_side_effect(mocker, config, GetParameterError())
426416
conf_store = FeatureFlags(schema_fetcher)
427417

428-
# WHEN calling get_feature_toggle
429-
toggle = conf_store.get_feature_toggle(feature_name="Foo", value_if_missing=False)
418+
# WHEN calling evaluate
419+
toggle = conf_store.evaluate(feature_name="Foo", default=False)
430420

431-
# THEN handle the error and return the value_if_missing
421+
# THEN handle the error and return the default
432422
assert toggle is False
433423

434424

0 commit comments

Comments
 (0)