in aws_lambda_powertools/utilities/feature_flags/feature_flags.py [0:0]
def evaluate(self, *, name: str, context: Optional[Dict[str, Any]] = None, default: JSONType) -> JSONType:
"""Evaluate whether a feature flag should be enabled according to stored schema and input context
**Logic when evaluating a feature flag**
1. Feature exists and a rule matches, returns when_match value
2. Feature exists but has either no rules or no match, return feature default value
3. Feature doesn't exist in stored schema, encountered an error when fetching -> return default value provided
Parameters
----------
name: str
feature name to evaluate
context: Optional[Dict[str, Any]]
Attributes that should be evaluated against the stored schema.
for example: `{"tenant_id": "X", "username": "Y", "region": "Z"}`
default: JSONType
default value if feature flag doesn't exist in the schema,
or there has been an error when fetching the configuration from the store
Can be boolean or any JSON values for non-boolean features.
Returns
------
JSONType
whether feature should be enabled (bool flags) or JSON value when non-bool feature matches
Raises
------
SchemaValidationError
When schema doesn't conform with feature flag schema
"""
if context is None:
context = {}
try:
features = self.get_configuration()
except ConfigurationStoreError as err:
self.logger.debug(f"Failed to fetch feature flags from store, returning default provided, reason={err}")
return default
feature = features.get(name)
if feature is None:
self.logger.debug(f"Feature not found; returning default provided, name={name}, default={default}")
return default
rules = feature.get(schema.RULES_KEY)
feat_default = feature.get(schema.FEATURE_DEFAULT_VAL_KEY)
# Maintenance: Revisit before going GA. We might to simplify customers on-boarding by not requiring it
# for non-boolean flags. It'll need minor implementation changes, docs changes, and maybe refactor
# get_enabled_features. We can minimize breaking change, despite Beta label, by having a new
# method `get_matching_features` returning Dict[feature_name, feature_value]
boolean_feature = feature.get(
schema.FEATURE_DEFAULT_VAL_TYPE_KEY, True
) # backwards compatability ,assume feature flag
if not rules:
self.logger.debug(
f"no rules found, returning feature default, name={name}, default={str(feat_default)}, boolean_feature={boolean_feature}" # noqa: E501
)
# Maintenance: Revisit before going GA. We might to simplify customers on-boarding by not requiring it
# for non-boolean flags.
return bool(feat_default) if boolean_feature else feat_default
self.logger.debug(
f"looking for rule match, name={name}, default={str(feat_default)}, boolean_feature={boolean_feature}" # noqa: E501
)
return self._evaluate_rules(
feature_name=name, context=context, feat_default=feat_default, rules=rules, boolean_feature=boolean_feature
)