Skip to content

Commit eb72d96

Browse files
committed
Merge branch 'develop' of https://github.com/awslabs/aws-lambda-powertools-python into docs/feature-toggle-examples
* 'develop' of https://github.com/awslabs/aws-lambda-powertools-python: chore(deps): bump boto3 from 1.18.15 to 1.18.17 (#597) feat(feature flags): Add not_in action and rename contains to in (#589) chore(deps-dev): bump mkdocs-material from 7.2.2 to 7.2.3 (#596) chore(deps): bump boto3 from 1.18.1 to 1.18.15 (#591) chore(deps): bump codecov/codecov-action from 2.0.1 to 2.0.2 (#558) fix(deps): bump poetry to latest (#592) chore(deps-dev): bump mkdocs-material from 7.2.1 to 7.2.2 (#582)
2 parents dcbe08b + 7b3b032 commit eb72d96

File tree

8 files changed

+83
-25
lines changed

8 files changed

+83
-25
lines changed

.github/workflows/python_build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ jobs:
3737
- name: Complexity baseline
3838
run: make complexity-baseline
3939
- name: Upload coverage to Codecov
40-
uses: codecov/[email protected].1
40+
uses: codecov/[email protected].2
4141
with:
4242
file: ./coverage.xml
4343
# flags: unittests

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ target:
55
@$(MAKE) pr
66

77
dev:
8-
pip install --upgrade pip pre-commit poetry==1.1.4
8+
pip install --upgrade pip pre-commit poetry
99
poetry install --extras "pydantic"
1010
pre-commit install
1111

aws_lambda_powertools/utilities/feature_flags/feature_flags.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ def _match_by_action(action: str, condition_value: Any, context_value: Any) -> b
4646
schema.RuleAction.EQUALS.value: lambda a, b: a == b,
4747
schema.RuleAction.STARTSWITH.value: lambda a, b: a.startswith(b),
4848
schema.RuleAction.ENDSWITH.value: lambda a, b: a.endswith(b),
49-
schema.RuleAction.CONTAINS.value: lambda a, b: a in b,
49+
schema.RuleAction.IN.value: lambda a, b: a in b,
50+
schema.RuleAction.NOT_IN.value: lambda a, b: a not in b,
5051
}
5152

5253
try:

aws_lambda_powertools/utilities/feature_flags/schema.py

+3-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,8 @@ class RuleAction(str, Enum):
2020
EQUALS = "EQUALS"
2121
STARTSWITH = "STARTSWITH"
2222
ENDSWITH = "ENDSWITH"
23-
CONTAINS = "CONTAINS"
23+
IN = "IN"
24+
NOT_IN = "NOT_IN"
2425

2526

2627
class SchemaValidator(BaseValidator):
@@ -79,7 +80,7 @@ class SchemaValidator(BaseValidator):
7980
The value MUST contain the following members:
8081
8182
* **action**: `str`. Operation to perform to match a key and value.
82-
The value MUST be either EQUALS, STARTSWITH, ENDSWITH, CONTAINS
83+
The value MUST be either EQUALS, STARTSWITH, ENDSWITH, IN, NOT_IN
8384
* **key**: `str`. Key in given context to perform operation
8485
* **value**: `Any`. Value in given context that should match action operation.
8586

poetry.lock

+14-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ radon = "^4.5.0"
4949
xenon = "^0.7.3"
5050
flake8-eradicate = "^1.1.0"
5151
flake8-bugbear = "^21.3.2"
52-
mkdocs-material = "^7.2.1"
52+
mkdocs-material = "^7.2.3"
5353
mkdocs-git-revision-date-plugin = "^0.3.1"
5454
mike = "^0.6.0"
5555
mypy = "^0.910"

tests/functional/feature_flags/test_feature_flags.py

+55-7
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ def test_flags_conditions_rule_match_multiple_actions_multiple_rules_multiple_co
263263

264264

265265
# check a case where the feature exists but the rule doesn't match so we revert to the default value of the feature
266-
def test_flags_match_rule_with_contains_action(mocker, config):
266+
def test_flags_match_rule_with_in_action(mocker, config):
267267
expected_value = True
268268
mocked_app_config_schema = {
269269
"my_feature": {
@@ -273,7 +273,7 @@ def test_flags_match_rule_with_contains_action(mocker, config):
273273
"when_match": expected_value,
274274
"conditions": [
275275
{
276-
"action": RuleAction.CONTAINS.value,
276+
"action": RuleAction.IN.value,
277277
"key": "tenant_id",
278278
"value": ["6", "2"],
279279
}
@@ -287,7 +287,7 @@ def test_flags_match_rule_with_contains_action(mocker, config):
287287
assert toggle == expected_value
288288

289289

290-
def test_flags_no_match_rule_with_contains_action(mocker, config):
290+
def test_flags_no_match_rule_with_in_action(mocker, config):
291291
expected_value = False
292292
mocked_app_config_schema = {
293293
"my_feature": {
@@ -297,7 +297,7 @@ def test_flags_no_match_rule_with_contains_action(mocker, config):
297297
"when_match": True,
298298
"conditions": [
299299
{
300-
"action": RuleAction.CONTAINS.value,
300+
"action": RuleAction.IN.value,
301301
"key": "tenant_id",
302302
"value": ["8", "2"],
303303
}
@@ -311,6 +311,54 @@ def test_flags_no_match_rule_with_contains_action(mocker, config):
311311
assert toggle == expected_value
312312

313313

314+
def test_flags_match_rule_with_not_in_action(mocker, config):
315+
expected_value = True
316+
mocked_app_config_schema = {
317+
"my_feature": {
318+
"default": False,
319+
"rules": {
320+
"tenant id is contained in [8, 2]": {
321+
"when_match": expected_value,
322+
"conditions": [
323+
{
324+
"action": RuleAction.NOT_IN.value,
325+
"key": "tenant_id",
326+
"value": ["10", "4"],
327+
}
328+
],
329+
}
330+
},
331+
}
332+
}
333+
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
334+
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False)
335+
assert toggle == expected_value
336+
337+
338+
def test_flags_no_match_rule_with_not_in_action(mocker, config):
339+
expected_value = False
340+
mocked_app_config_schema = {
341+
"my_feature": {
342+
"default": expected_value,
343+
"rules": {
344+
"tenant id is contained in [8, 2]": {
345+
"when_match": True,
346+
"conditions": [
347+
{
348+
"action": RuleAction.NOT_IN.value,
349+
"key": "tenant_id",
350+
"value": ["6", "4"],
351+
}
352+
],
353+
}
354+
},
355+
}
356+
}
357+
feature_flags = init_feature_flags(mocker, mocked_app_config_schema, config)
358+
toggle = feature_flags.evaluate(name="my_feature", context={"tenant_id": "6", "username": "a"}, default=False)
359+
assert toggle == expected_value
360+
361+
314362
def test_multiple_features_enabled(mocker, config):
315363
expected_value = ["my_feature", "my_feature2"]
316364
mocked_app_config_schema = {
@@ -321,7 +369,7 @@ def test_multiple_features_enabled(mocker, config):
321369
"when_match": True,
322370
"conditions": [
323371
{
324-
"action": RuleAction.CONTAINS.value,
372+
"action": RuleAction.IN.value,
325373
"key": "tenant_id",
326374
"value": ["6", "2"],
327375
}
@@ -351,7 +399,7 @@ def test_multiple_features_only_some_enabled(mocker, config):
351399
"when_match": True,
352400
"conditions": [
353401
{
354-
"action": RuleAction.CONTAINS.value,
402+
"action": RuleAction.IN.value,
355403
"key": "tenant_id",
356404
"value": ["6", "2"],
357405
}
@@ -464,7 +512,7 @@ def test_features_jmespath_envelope(mocker, config):
464512
assert toggle == expected_value
465513

466514

467-
# test_match_rule_with_contains_action
515+
# test_match_rule_with_equals_action
468516
def test_match_condition_with_dict_value(mocker, config):
469517
expected_value = True
470518
mocked_app_config_schema = {

tests/functional/feature_flags/test_schema_validation.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -211,10 +211,15 @@ def test_valid_condition_all_actions():
211211
CONDITION_VALUE: "a",
212212
},
213213
{
214-
CONDITION_ACTION: RuleAction.CONTAINS.value,
214+
CONDITION_ACTION: RuleAction.IN.value,
215215
CONDITION_KEY: "username",
216216
CONDITION_VALUE: ["a", "b"],
217217
},
218+
{
219+
CONDITION_ACTION: RuleAction.NOT_IN.value,
220+
CONDITION_KEY: "username",
221+
CONDITION_VALUE: ["c"],
222+
},
218223
],
219224
}
220225
},

0 commit comments

Comments
 (0)