diff --git a/open_feature/flag_evaluation/flag_evaluation_details.py b/open_feature/flag_evaluation/flag_evaluation_details.py index 4deb9b1b..0caf4c0c 100644 --- a/open_feature/flag_evaluation/flag_evaluation_details.py +++ b/open_feature/flag_evaluation/flag_evaluation_details.py @@ -1,18 +1,15 @@ +import typing +from dataclasses import dataclass + from open_feature.flag_evaluation.error_code import ErrorCode from open_feature.flag_evaluation.reason import Reason +@dataclass class FlagEvaluationDetails: - def __init__( - self, - key: str, - value, - reason: Reason, - error_code: ErrorCode = None, - variant=None, - ): - self.key = key - self.value = value - self.reason = reason - self.error_code = error_code - self.variant = variant + flag_key: str + value: typing.Any + variant: str = None + reason: Reason = None + error_code: ErrorCode = None + error_message: str = None diff --git a/open_feature/open_feature_client.py b/open_feature/open_feature_client.py index 83c0b5ff..a685f4b7 100644 --- a/open_feature/open_feature_client.py +++ b/open_feature/open_feature_client.py @@ -4,6 +4,7 @@ from open_feature.evaluation_context.evaluation_context import EvaluationContext from open_feature.exception.exceptions import GeneralError +from open_feature.flag_evaluation.error_code import ErrorCode from open_feature.flag_evaluation.flag_evaluation_details import FlagEvaluationDetails from open_feature.flag_evaluation.flag_type import FlagType from open_feature.flag_evaluation.reason import Reason @@ -40,14 +41,14 @@ def add_hooks(self, hooks: typing.List[Hook]): def get_boolean_value( self, - key: str, + flag_key: str, default_value: bool, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, ) -> bool: return self.evaluate_flag_details( FlagType.BOOLEAN, - key, + flag_key, default_value, evaluation_context, flag_evaluation_options, @@ -55,14 +56,14 @@ def get_boolean_value( def get_boolean_details( self, - key: str, + flag_key: str, default_value: bool, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.BOOLEAN, - key, + flag_key, default_value, evaluation_context, flag_evaluation_options, @@ -70,14 +71,14 @@ def get_boolean_details( def get_string_value( self, - key: str, + flag_key: str, default_value: str, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, ) -> str: return self.evaluate_flag_details( FlagType.STRING, - key, + flag_key, default_value, evaluation_context, flag_evaluation_options, @@ -85,14 +86,14 @@ def get_string_value( def get_string_details( self, - key: str, + flag_key: str, default_value: str, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.STRING, - key, + flag_key, default_value, evaluation_context, flag_evaluation_options, @@ -100,14 +101,14 @@ def get_string_details( def get_number_value( self, - key: str, + flag_key: str, default_value: Number, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, ) -> Number: return self.evaluate_flag_details( FlagType.NUMBER, - key, + flag_key, default_value, evaluation_context, flag_evaluation_options, @@ -115,14 +116,14 @@ def get_number_value( def get_number_details( self, - key: str, + flag_key: str, default_value: Number, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.NUMBER, - key, + flag_key, default_value, evaluation_context, flag_evaluation_options, @@ -130,14 +131,14 @@ def get_number_details( def get_object_value( self, - key: str, + flag_key: str, default_value: dict, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, ) -> dict: return self.evaluate_flag_details( FlagType.OBJECT, - key, + flag_key, default_value, evaluation_context, flag_evaluation_options, @@ -145,14 +146,14 @@ def get_object_value( def get_object_details( self, - key: str, + flag_key: str, default_value: dict, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, ) -> FlagEvaluationDetails: return self.evaluate_flag_details( FlagType.OBJECT, - key, + flag_key, default_value, evaluation_context, flag_evaluation_options, @@ -161,7 +162,7 @@ def get_object_details( def evaluate_flag_details( self, flag_type: FlagType, - key: str, + flag_key: str, default_value: typing.Any, evaluation_context: EvaluationContext = None, flag_evaluation_options: typing.Any = None, @@ -182,7 +183,7 @@ def evaluate_flag_details( evaluation_context = EvaluationContext() hook_context = HookContext( - flag_key=key, + flag_key=flag_key, flag_type=flag_type, default_value=default_value, evaluation_context=evaluation_context, @@ -207,7 +208,7 @@ def evaluate_flag_details( flag_evaluation = self.create_provider_evaluation( flag_type, - key, + flag_key, default_value, merged_context, ) @@ -216,15 +217,26 @@ def evaluate_flag_details( return flag_evaluation + except OpenFeatureError as e: # noqa + error_hooks(flag_type, hook_context, e, merged_hooks, None) + return FlagEvaluationDetails( + flag_key=flag_key, + value=default_value, + reason=Reason.ERROR, + error_code=e.error_code, + error_message=e.error_message, + ) # Catch any type of exception here since the user can provide any exception # in the error hooks except Exception as e: # noqa error_hooks(flag_type, hook_context, e, merged_hooks, None) + error_message = getattr(e, "error_message", str(e)) return FlagEvaluationDetails( - key=key, + flag_key=flag_key, value=default_value, reason=Reason.ERROR, - error_code=e.error_message, + error_code=ErrorCode.GENERAL, + error_message=error_message, ) finally: @@ -233,7 +245,7 @@ def evaluate_flag_details( def create_provider_evaluation( self, flag_type: FlagType, - key: str, + flag_key: str, default_value: typing.Any, evaluation_context: EvaluationContext = None, ) -> FlagEvaluationDetails: @@ -248,7 +260,7 @@ def create_provider_evaluation( provider """ args = ( - key, + flag_key, default_value, evaluation_context, ) diff --git a/open_feature/provider/no_op_provider.py b/open_feature/provider/no_op_provider.py index d91395e7..515c4471 100644 --- a/open_feature/provider/no_op_provider.py +++ b/open_feature/provider/no_op_provider.py @@ -14,12 +14,12 @@ def get_name(self) -> str: def get_boolean_details( self, - key: str, + flag_key: str, default_value: bool, evaluation_context: EvaluationContext = None, ): return FlagEvaluationDetails( - key=key, + flag_key=flag_key, value=default_value, reason=Reason.DEFAULT, variant=PASSED_IN_DEFAULT, @@ -27,12 +27,12 @@ def get_boolean_details( def get_string_details( self, - key: str, + flag_key: str, default_value: str, evaluation_context: EvaluationContext = None, ): return FlagEvaluationDetails( - key=key, + flag_key=flag_key, value=default_value, reason=Reason.DEFAULT, variant=PASSED_IN_DEFAULT, @@ -40,12 +40,12 @@ def get_string_details( def get_number_details( self, - key: str, + flag_key: str, default_value: Number, evaluation_context: EvaluationContext = None, ): return FlagEvaluationDetails( - key=key, + flag_key=flag_key, value=default_value, reason=Reason.DEFAULT, variant=PASSED_IN_DEFAULT, @@ -53,12 +53,12 @@ def get_number_details( def get_object_details( self, - key: str, + flag_key: str, default_value: dict, evaluation_context: EvaluationContext = None, ): return FlagEvaluationDetails( - key=key, + flag_key=flag_key, value=default_value, reason=Reason.DEFAULT, variant=PASSED_IN_DEFAULT, diff --git a/open_feature/provider/provider.py b/open_feature/provider/provider.py index f3057039..10f37388 100644 --- a/open_feature/provider/provider.py +++ b/open_feature/provider/provider.py @@ -12,7 +12,7 @@ def get_name(self) -> str: @abstractmethod def get_boolean_details( self, - key: str, + flag_key: str, default_value: bool, evaluation_context: EvaluationContext = EvaluationContext(), ): @@ -21,7 +21,7 @@ def get_boolean_details( @abstractmethod def get_string_details( self, - key: str, + flag_key: str, default_value: str, evaluation_context: EvaluationContext = EvaluationContext(), ): @@ -30,7 +30,7 @@ def get_string_details( @abstractmethod def get_number_details( self, - key: str, + flag_key: str, default_value: Number, evaluation_context: EvaluationContext = EvaluationContext(), ): @@ -39,7 +39,7 @@ def get_number_details( @abstractmethod def get_object_details( self, - key: str, + flag_key: str, default_value: dict, evaluation_context: EvaluationContext = EvaluationContext(), ): diff --git a/tests/provider/test_no_op_provider.py b/tests/provider/test_no_op_provider.py index a493f8ea..7b237148 100644 --- a/tests/provider/test_no_op_provider.py +++ b/tests/provider/test_no_op_provider.py @@ -13,7 +13,7 @@ def setup(): def test_should_get_boolean_flag_from_no_op(no_op_provider_client): # Given # When - flag = no_op_provider_client.get_boolean_details(key="Key", default_value=True) + flag = no_op_provider_client.get_boolean_details(flag_key="Key", default_value=True) # Then assert flag is not None assert flag.value @@ -23,7 +23,7 @@ def test_should_get_boolean_flag_from_no_op(no_op_provider_client): def test_should_get_number_flag_from_no_op(no_op_provider_client): # Given # When - flag = no_op_provider_client.get_number_details(key="Key", default_value=100) + flag = no_op_provider_client.get_number_details(flag_key="Key", default_value=100) # Then assert flag is not None assert flag.value == 100 @@ -33,7 +33,9 @@ def test_should_get_number_flag_from_no_op(no_op_provider_client): def test_should_get_string_flag_from_no_op(no_op_provider_client): # Given # When - flag = no_op_provider_client.get_string_details(key="Key", default_value="String") + flag = no_op_provider_client.get_string_details( + flag_key="Key", default_value="String" + ) # Then assert flag is not None assert flag.value == "String" @@ -49,7 +51,7 @@ def test_should_get_object_flag_from_no_op(no_op_provider_client): } # When flag = no_op_provider_client.get_string_details( - key="Key", default_value=return_value + flag_key="Key", default_value=return_value ) # Then assert flag is not None