diff --git a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py index 861f23025fa..3d8100bd366 100644 --- a/aws_lambda_powertools/utilities/feature_flags/feature_flags.py +++ b/aws_lambda_powertools/utilities/feature_flags/feature_flags.py @@ -57,7 +57,7 @@ def _is_rule_matched(self, feature_name: str, rule: Dict[str, Any], context: Dic return False # if we got here, all conditions match logger.debug( - f"rule matched, rule_name={rule_name}, rule_default_value={rule_default_value}, " f"name={feature_name}" + f"rule matched, rule_name={rule_name}, rule_default_value={rule_default_value}, name={feature_name}" ) return True return False @@ -160,7 +160,7 @@ def evaluate(self, *, name: str, context: Optional[Dict[str, Any]] = None, defau feature = features.get(name) if feature is None: logger.debug( - f"feature does not appear in configuration, using provided default, " f"name={name}, default={default}" + f"feature does not appear in configuration, using provided default, name={name}, default={default}" ) return default diff --git a/aws_lambda_powertools/utilities/feature_flags/schema.py b/aws_lambda_powertools/utilities/feature_flags/schema.py index cc7216d8dde..09a54b11dda 100644 --- a/aws_lambda_powertools/utilities/feature_flags/schema.py +++ b/aws_lambda_powertools/utilities/feature_flags/schema.py @@ -38,12 +38,9 @@ def validate(self) -> None: class FeaturesValidator(BaseValidator): - def __init__(self, schema): + def __init__(self, schema: Dict): self.schema = schema - self.features: Optional[Dict[str, Dict]] = None - - if isinstance(self.schema, dict): - self.features = self.schema.get(FEATURES_KEY) + self.features: Optional[Dict[str, Dict]] = self.schema.get(FEATURES_KEY) def validate(self): if not isinstance(self.features, dict): @@ -71,13 +68,13 @@ def __init__(self, feature: Dict[str, Any], feature_name: str): self.rules: Optional[List[Dict]] = self.feature.get(RULES_KEY) def validate(self): - if not isinstance(self.rules, list): - raise ConfigurationError(f"Feature rules is not a list, feature_name={self.feature_name}") - if not self.rules: logger.debug("Rules are empty, ignoring validation") return + if not isinstance(self.rules, list): + raise ConfigurationError(f"Feature rules is not a list, feature_name={self.feature_name}") + for rule in self.rules: self.validate_rule(rule, self.feature) conditions = ConditionsValidator(rule=rule, rule_name=rule.get(RULE_NAME_KEY)) diff --git a/tests/functional/feature_toggles/test_feature_toggles.py b/tests/functional/feature_toggles/test_feature_toggles.py index 295e7623dac..88cf455d0db 100644 --- a/tests/functional/feature_toggles/test_feature_toggles.py +++ b/tests/functional/feature_toggles/test_feature_toggles.py @@ -279,7 +279,7 @@ def test_toggles_match_rule_with_contains_action(mocker, config): "feature_default_value": False, "rules": [ { - "rule_name": "tenant id is contained in [6,2] ", + "rule_name": "tenant id is contained in [6, 2]", "value_when_applies": expected_value, "conditions": [ { @@ -306,7 +306,7 @@ def test_toggles_no_match_rule_with_contains_action(mocker, config): "feature_default_value": expected_value, "rules": [ { - "rule_name": "tenant id is contained in [6,2] ", + "rule_name": "tenant id is contained in [8, 2]", "value_when_applies": True, "conditions": [ { @@ -333,7 +333,7 @@ def test_multiple_features_enabled(mocker, config): "feature_default_value": False, "rules": [ { - "rule_name": "tenant id is contained in [6,2] ", + "rule_name": "tenant id is contained in [6, 2]", "value_when_applies": True, "conditions": [ { @@ -366,7 +366,7 @@ def test_multiple_features_only_some_enabled(mocker, config): "feature_default_value": False, "rules": [ { - "rule_name": "tenant id is contained in [6,2] ", + "rule_name": "tenant id is contained in [6, 2]", "value_when_applies": True, "conditions": [ { diff --git a/tests/functional/feature_toggles/test_schema_validation.py b/tests/functional/feature_toggles/test_schema_validation.py index 8329dd68987..6495a00e727 100644 --- a/tests/functional/feature_toggles/test_schema_validation.py +++ b/tests/functional/feature_toggles/test_schema_validation.py @@ -33,11 +33,13 @@ def test_invalid_features_dict(): schema = [] # invalid type + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() # invalid features key schema = {FEATURES_KEY: []} + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() @@ -57,33 +59,38 @@ def test_invalid_feature_dict(): # empty feature dict schema = {FEATURES_KEY: {"my_feature": {}}} + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() # invalid FEATURE_DEFAULT_VAL_KEY type, not boolean schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: "False"}}} + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() # invalid FEATURE_DEFAULT_VAL_KEY type, not boolean #2 schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: 5}}} + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() # invalid rules type, not list schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False, RULES_KEY: "4"}}} + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() def test_valid_feature_dict(): - # no rules list at all - schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False}}} + # empty rules list + schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False, RULES_KEY: []}}} validator = SchemaValidator(schema) validator.validate() - # empty rules list - schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False, RULES_KEY: []}}} + # no rules list at all + schema = {FEATURES_KEY: {"my_feature": {FEATURE_DEFAULT_VAL_KEY: False}}} + validator = SchemaValidator(schema) validator.validate() @@ -118,6 +125,7 @@ def test_invalid_rule(): } } } + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() @@ -135,6 +143,7 @@ def test_invalid_rule(): } } } + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() @@ -149,6 +158,7 @@ def test_invalid_rule(): } } } + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() @@ -163,6 +173,7 @@ def test_invalid_rule(): } } } + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() @@ -202,6 +213,7 @@ def test_invalid_condition(): } } } + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate() @@ -224,6 +236,7 @@ def test_invalid_condition(): } } } + validator = SchemaValidator(schema) with pytest.raises(ConfigurationError): validator.validate()