diff --git a/openfeature/client.py b/openfeature/client.py index 1edfca63..602e3bca 100644 --- a/openfeature/client.py +++ b/openfeature/client.py @@ -325,6 +325,7 @@ def evaluate_flag_details( # noqa: PLR0915 error_code=ErrorCode.PROVIDER_FATAL, ) + flag_evaluation = None try: # https://github.com/open-feature/spec/blob/main/specification/sections/03-evaluation-context.md # Any resulting evaluation context from a before hook will overwrite @@ -364,13 +365,14 @@ def evaluate_flag_details( # noqa: PLR0915 except OpenFeatureError as err: error_hooks(flag_type, hook_context, err, reversed_merged_hooks, hook_hints) - return FlagEvaluationDetails( + flag_evaluation = FlagEvaluationDetails( flag_key=flag_key, value=default_value, reason=Reason.ERROR, error_code=err.error_code, error_message=err.error_message, ) + return flag_evaluation # Catch any type of exception here since the user can provide any exception # in the error hooks except Exception as err: # pragma: no cover @@ -381,16 +383,17 @@ def evaluate_flag_details( # noqa: PLR0915 error_hooks(flag_type, hook_context, err, reversed_merged_hooks, hook_hints) error_message = getattr(err, "error_message", str(err)) - return FlagEvaluationDetails( + flag_evaluation = FlagEvaluationDetails( flag_key=flag_key, value=default_value, reason=Reason.ERROR, error_code=ErrorCode.GENERAL, error_message=error_message, ) + return flag_evaluation finally: - after_all_hooks(flag_type, hook_context, reversed_merged_hooks, hook_hints) + after_all_hooks(flag_type, hook_context, flag_evaluation, reversed_merged_hooks, hook_hints) def _create_provider_evaluation( self, diff --git a/openfeature/hook/__init__.py b/openfeature/hook/__init__.py index 77190dc0..8e4189e3 100644 --- a/openfeature/hook/__init__.py +++ b/openfeature/hook/__init__.py @@ -109,7 +109,7 @@ def error( """ pass - def finally_after(self, hook_context: HookContext, hints: HookHints) -> None: + def finally_after(self, hook_context: HookContext, details: FlagEvaluationDetails[typing.Any], hints: HookHints) -> None: """ Run after flag evaluation, including any error processing. This will always run. Errors will be swallowed. diff --git a/openfeature/hook/_hook_support.py b/openfeature/hook/_hook_support.py index 349b25f3..2c151ae1 100644 --- a/openfeature/hook/_hook_support.py +++ b/openfeature/hook/_hook_support.py @@ -25,10 +25,11 @@ def error_hooks( def after_all_hooks( flag_type: FlagType, hook_context: HookContext, + details: FlagEvaluationDetails[typing.Any], hooks: typing.List[Hook], hints: typing.Optional[HookHints] = None, ) -> None: - kwargs = {"hook_context": hook_context, "hints": hints} + kwargs = {"hook_context": hook_context, "details": details, "hints": hints} _execute_hooks( flag_type=flag_type, hooks=hooks, hook_method=HookType.FINALLY_AFTER, **kwargs ) diff --git a/tests/hook/test_hook_support.py b/tests/hook/test_hook_support.py index 64bb8f6f..37ba0637 100644 --- a/tests/hook/test_hook_support.py +++ b/tests/hook/test_hook_support.py @@ -137,12 +137,15 @@ def test_after_hooks_run_after_method(mock_hook): def test_finally_after_hooks_run_finally_after_method(mock_hook): # Given hook_context = HookContext("flag_key", FlagType.BOOLEAN, True, "") + flag_evaluation_details = FlagEvaluationDetails( + hook_context.flag_key, "val", "unknown" + ) hook_hints = MappingProxyType({}) # When - after_all_hooks(FlagType.BOOLEAN, hook_context, [mock_hook], hook_hints) + after_all_hooks(FlagType.BOOLEAN, hook_context, flag_evaluation_details, [mock_hook], hook_hints) # Then mock_hook.supports_flag_value_type.assert_called_once() mock_hook.finally_after.assert_called_once() mock_hook.finally_after.assert_called_with( - hook_context=hook_context, hints=hook_hints + hook_context=hook_context, details=flag_evaluation_details, hints=hook_hints )