From cd0b5c77ea4968d4f64618fb90b7c2ad50312ff8 Mon Sep 17 00:00:00 2001 From: Andrew Helsby Date: Tue, 18 Oct 2022 11:32:42 +0400 Subject: [PATCH 1/6] fix/flag-error-message: Move flag evaluation details to a dataclass and add error message to the class Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby --- .../flag_evaluation_details.py | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) 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 From bcbf4e91304ae3ccbd00e9931902bf91e5c88a0b Mon Sep 17 00:00:00 2001 From: Andrew Helsby Date: Tue, 18 Oct 2022 12:06:22 +0400 Subject: [PATCH 2/6] fix/flag-error-message: Rename flag_key in FlagEvaluationDetails to match spec Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby --- open_feature/provider/no_op_provider.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/open_feature/provider/no_op_provider.py b/open_feature/provider/no_op_provider.py index d91395e7..10c3aeb9 100644 --- a/open_feature/provider/no_op_provider.py +++ b/open_feature/provider/no_op_provider.py @@ -19,7 +19,7 @@ def get_boolean_details( evaluation_context: EvaluationContext = None, ): return FlagEvaluationDetails( - key=key, + flag_key=key, value=default_value, reason=Reason.DEFAULT, variant=PASSED_IN_DEFAULT, @@ -32,7 +32,7 @@ def get_string_details( evaluation_context: EvaluationContext = None, ): return FlagEvaluationDetails( - key=key, + flag_key=key, value=default_value, reason=Reason.DEFAULT, variant=PASSED_IN_DEFAULT, @@ -45,7 +45,7 @@ def get_number_details( evaluation_context: EvaluationContext = None, ): return FlagEvaluationDetails( - key=key, + flag_key=key, value=default_value, reason=Reason.DEFAULT, variant=PASSED_IN_DEFAULT, @@ -58,7 +58,7 @@ def get_object_details( evaluation_context: EvaluationContext = None, ): return FlagEvaluationDetails( - key=key, + flag_key=key, value=default_value, reason=Reason.DEFAULT, variant=PASSED_IN_DEFAULT, From c7d5b4772ab460881b1344d7d73238198a1625a3 Mon Sep 17 00:00:00 2001 From: Andrew Helsby Date: Tue, 18 Oct 2022 12:35:59 +0400 Subject: [PATCH 3/6] fix/flag-error-message: Rename flag_key in provider.py to match spec Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby --- open_feature/provider/no_op_provider.py | 16 ++++++++-------- open_feature/provider/provider.py | 8 ++++---- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/open_feature/provider/no_op_provider.py b/open_feature/provider/no_op_provider.py index 10c3aeb9..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( - flag_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( - flag_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( - flag_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( - flag_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(), ): From f49403d223b95194e7ef53373784e3b515b8fd46 Mon Sep 17 00:00:00 2001 From: Andrew Helsby Date: Tue, 18 Oct 2022 12:43:42 +0400 Subject: [PATCH 4/6] fix/flag-error-message: Rename flag_key in open_feature_client.py Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby --- open_feature/open_feature_client.py | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/open_feature/open_feature_client.py b/open_feature/open_feature_client.py index 83c0b5ff..69182d41 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 @@ -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=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 = e.error_message if e.error_message else str(e) return FlagEvaluationDetails( - key=key, + flag_key=key, value=default_value, reason=Reason.ERROR, - error_code=e.error_message, + error_code=ErrorCode.GENERAL, + error_message=error_message, ) finally: From f9e555e862bf22d479c8f22e661ed466f5d69598 Mon Sep 17 00:00:00 2001 From: Andrew Helsby Date: Tue, 18 Oct 2022 12:58:15 +0400 Subject: [PATCH 5/6] fix/flag-error-message: Rename flag_key in open_feature_client.py Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby --- open_feature/open_feature_client.py | 46 +++++++++++++-------------- tests/provider/test_no_op_provider.py | 10 +++--- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/open_feature/open_feature_client.py b/open_feature/open_feature_client.py index 69182d41..2644faf1 100644 --- a/open_feature/open_feature_client.py +++ b/open_feature/open_feature_client.py @@ -41,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, @@ -56,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, @@ -71,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, @@ -86,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, @@ -101,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, @@ -116,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, @@ -131,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, @@ -146,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, @@ -162,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, @@ -183,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, @@ -208,7 +208,7 @@ def evaluate_flag_details( flag_evaluation = self.create_provider_evaluation( flag_type, - key, + flag_key, default_value, merged_context, ) @@ -220,7 +220,7 @@ def evaluate_flag_details( except OpenFeatureError as e: # noqa error_hooks(flag_type, hook_context, e, merged_hooks, None) return FlagEvaluationDetails( - flag_key=key, + flag_key=flag_key, value=default_value, reason=Reason.ERROR, error_code=e.error_code, @@ -232,7 +232,7 @@ def evaluate_flag_details( error_hooks(flag_type, hook_context, e, merged_hooks, None) error_message = e.error_message if e.error_message else str(e) return FlagEvaluationDetails( - flag_key=key, + flag_key=flag_key, value=default_value, reason=Reason.ERROR, error_code=ErrorCode.GENERAL, @@ -245,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: @@ -260,7 +260,7 @@ def create_provider_evaluation( provider """ args = ( - key, + flag_key, default_value, evaluation_context, ) 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 From de93a56d060e88376d7623d16c6aad810a2acca5 Mon Sep 17 00:00:00 2001 From: Andrew Helsby Date: Tue, 18 Oct 2022 14:07:51 +0400 Subject: [PATCH 6/6] fix/flag-error-message: handle error_message doesn't exist exception Signed-off-by: Andrew Helsby Signed-off-by: Andrew Helsby --- open_feature/open_feature_client.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/open_feature/open_feature_client.py b/open_feature/open_feature_client.py index 2644faf1..a685f4b7 100644 --- a/open_feature/open_feature_client.py +++ b/open_feature/open_feature_client.py @@ -230,7 +230,7 @@ def evaluate_flag_details( # in the error hooks except Exception as e: # noqa error_hooks(flag_type, hook_context, e, merged_hooks, None) - error_message = e.error_message if e.error_message else str(e) + error_message = getattr(e, "error_message", str(e)) return FlagEvaluationDetails( flag_key=flag_key, value=default_value,