refactor!: move api hooks methods to api module (#169)

* refactor!: move api hooks methods to api module

Signed-off-by: Federico Bond <federicobond@gmail.com>

* refactor!: rename api-level hook methods

Signed-off-by: Federico Bond <federicobond@gmail.com>

---------

Signed-off-by: Federico Bond <federicobond@gmail.com>
This commit is contained in:
Federico Bond 2023-09-01 13:19:50 +12:00 committed by GitHub
parent 9e1bcb38fd
commit a7da26fd93
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 44 additions and 46 deletions

View File

@ -1,21 +0,0 @@
import typing
from open_feature.hooks.hook import Hook
_hooks: typing.List[Hook] = []
def add_api_hooks(hooks: typing.List[Hook]):
global _hooks
_hooks = _hooks + hooks
def clear_api_hooks():
global _hooks
_hooks = []
def api_hooks() -> typing.List[Hook]:
global _hooks
return _hooks

View File

@ -2,6 +2,7 @@ import typing
from open_feature.evaluation_context.evaluation_context import EvaluationContext
from open_feature.exception.exceptions import GeneralError
from open_feature.hooks.hook import Hook
from open_feature.open_feature_client import OpenFeatureClient
from open_feature.provider.metadata import Metadata
from open_feature.provider.no_op_provider import NoOpProvider
@ -11,6 +12,8 @@ _provider: AbstractProvider = NoOpProvider()
_evaluation_context = EvaluationContext()
_hooks: typing.List[Hook] = []
def get_client(
name: typing.Optional[str] = None, version: typing.Optional[str] = None
@ -45,3 +48,18 @@ def set_evaluation_context(evaluation_context: EvaluationContext):
if evaluation_context is None:
raise GeneralError(error_message="No api level evaluation context")
_evaluation_context = evaluation_context
def add_hooks(hooks: typing.List[Hook]):
global _hooks
_hooks = _hooks + hooks
def clear_hooks():
global _hooks
_hooks = []
def get_hooks() -> typing.List[Hook]:
global _hooks
return _hooks

View File

@ -15,7 +15,6 @@ from open_feature.flag_evaluation.flag_evaluation_options import FlagEvaluationO
from open_feature.flag_evaluation.flag_type import FlagType
from open_feature.flag_evaluation.reason import Reason
from open_feature.flag_evaluation.resolution_details import FlagResolutionDetails
from open_feature.hooks import api_hooks
from open_feature.hooks.hook import Hook
from open_feature.hooks.hook_context import HookContext
from open_feature.hooks.hook_support import (
@ -259,7 +258,7 @@ class OpenFeatureClient:
# in the flag evaluation
# before: API, Client, Invocation, Provider
merged_hooks = (
api_hooks()
api.get_hooks()
+ self.hooks
+ evaluation_hooks
+ self.provider.get_provider_hooks()

View File

@ -150,8 +150,8 @@ class MyHook(Hook):
# set global hooks at the API-level
from open_feature.hooks import add_api_hooks
add_api_hooks([MyHook()])
from open_feature.open_feature_api import add_hooks
add_hooks([MyHook()])
# or configure them in the client
client = OpenFeatureClient()

View File

@ -1,18 +0,0 @@
from unittest.mock import MagicMock
from open_feature.hooks.hook import Hook
from open_feature.hooks import add_api_hooks, clear_api_hooks, api_hooks
def test_should_add_hooks_to_api_hooks():
# Given
hook_1 = MagicMock(spec=Hook)
hook_2 = MagicMock(spec=Hook)
clear_api_hooks()
# When
add_api_hooks([hook_1])
add_api_hooks([hook_2])
# Then
assert api_hooks() == [hook_1, hook_2]

View File

@ -1,6 +1,9 @@
from unittest.mock import MagicMock
import pytest
from open_feature.evaluation_context.evaluation_context import EvaluationContext
from open_feature.hooks.hook import Hook
from open_feature.exception.error_code import ErrorCode
from open_feature.exception.exceptions import GeneralError
from open_feature.open_feature_api import (
@ -10,6 +13,9 @@ from open_feature.open_feature_api import (
get_provider_metadata,
get_evaluation_context,
set_evaluation_context,
get_hooks,
add_hooks,
clear_hooks,
)
from open_feature.provider.metadata import Metadata
from open_feature.provider.no_op_provider import NoOpProvider
@ -97,3 +103,17 @@ def test_should_successfully_set_evaluation_context_for_api():
assert global_evaluation_context
assert global_evaluation_context.targeting_key == evaluation_context.targeting_key
assert global_evaluation_context.attributes == evaluation_context.attributes
def test_should_add_hooks_to_api_hooks():
# Given
hook_1 = MagicMock(spec=Hook)
hook_2 = MagicMock(spec=Hook)
clear_hooks()
# When
add_hooks([hook_1])
add_hooks([hook_2])
# Then
assert get_hooks() == [hook_1, hook_2]

View File

@ -2,10 +2,10 @@ from unittest.mock import MagicMock
import pytest
from open_feature.open_feature_api import add_hooks, clear_hooks
from open_feature.exception.error_code import ErrorCode
from open_feature.exception.exceptions import OpenFeatureError
from open_feature.flag_evaluation.reason import Reason
from open_feature.hooks import clear_api_hooks, add_api_hooks
from open_feature.hooks.hook import Hook
from open_feature.open_feature_client import OpenFeatureClient
from open_feature.provider.no_op_provider import NoOpProvider
@ -149,9 +149,9 @@ def test_should_return_client_metadata_with_name():
def test_should_call_api_level_hooks(no_op_provider_client):
# Given
clear_api_hooks()
clear_hooks()
api_hook = MagicMock(spec=Hook)
add_api_hooks([api_hook])
add_hooks([api_hook])
# When
no_op_provider_client.get_boolean_details(flag_key="Key", default_value=True)