Skip to content

Commit cad6862

Browse files
committed
update to remove async hooks
1 parent 272d659 commit cad6862

File tree

6 files changed

+19
-312
lines changed

6 files changed

+19
-312
lines changed

openfeature/client.py

Lines changed: 7 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,9 @@
2323
from openfeature.hook import Hook, HookContext
2424
from openfeature.hook._hook_support import (
2525
after_all_hooks,
26-
after_all_hooks_async,
2726
after_hooks,
28-
after_hooks_async,
2927
before_hooks,
30-
before_hooks_async,
3128
error_hooks,
32-
error_hooks_async,
3329
)
3430
from openfeature.provider import FeatureProvider, ProviderStatus
3531
from openfeature.provider._registry import provider_registry
@@ -673,7 +669,7 @@ async def evaluate_flag_details( # noqa: PLR0915
673669

674670
status = self.get_provider_status()
675671
if status == ProviderStatus.NOT_READY:
676-
await error_hooks_async(
672+
error_hooks(
677673
flag_type,
678674
hook_context,
679675
ProviderNotReadyError(),
@@ -687,7 +683,7 @@ async def evaluate_flag_details( # noqa: PLR0915
687683
error_code=ErrorCode.PROVIDER_NOT_READY,
688684
)
689685
if status == ProviderStatus.FATAL:
690-
await error_hooks_async(
686+
error_hooks(
691687
flag_type,
692688
hook_context,
693689
ProviderFatalError(),
@@ -706,7 +702,7 @@ async def evaluate_flag_details( # noqa: PLR0915
706702
# Any resulting evaluation context from a before hook will overwrite
707703
# duplicate fields defined globally, on the client, or in the invocation.
708704
# Requirement 3.2.2, 4.3.4: API.context->client.context->invocation.context
709-
invocation_context = await before_hooks_async(
705+
invocation_context = before_hooks(
710706
flag_type, hook_context, merged_hooks, hook_hints
711707
)
712708

@@ -726,7 +722,7 @@ async def evaluate_flag_details( # noqa: PLR0915
726722
merged_context,
727723
)
728724

729-
await after_hooks_async(
725+
after_hooks(
730726
flag_type,
731727
hook_context,
732728
flag_evaluation,
@@ -737,9 +733,7 @@ async def evaluate_flag_details( # noqa: PLR0915
737733
return flag_evaluation
738734

739735
except OpenFeatureError as err:
740-
await error_hooks_async(
741-
flag_type, hook_context, err, reversed_merged_hooks, hook_hints
742-
)
736+
error_hooks(flag_type, hook_context, err, reversed_merged_hooks, hook_hints)
743737

744738
return FlagEvaluationDetails(
745739
flag_key=flag_key,
@@ -755,9 +749,7 @@ async def evaluate_flag_details( # noqa: PLR0915
755749
"Unable to correctly evaluate flag with key: '%s'", flag_key
756750
)
757751

758-
await error_hooks_async(
759-
flag_type, hook_context, err, reversed_merged_hooks, hook_hints
760-
)
752+
error_hooks(flag_type, hook_context, err, reversed_merged_hooks, hook_hints)
761753

762754
error_message = getattr(err, "error_message", str(err))
763755
return FlagEvaluationDetails(
@@ -769,9 +761,7 @@ async def evaluate_flag_details( # noqa: PLR0915
769761
)
770762

771763
finally:
772-
await after_all_hooks_async(
773-
flag_type, hook_context, reversed_merged_hooks, hook_hints
774-
)
764+
after_all_hooks(flag_type, hook_context, reversed_merged_hooks, hook_hints)
775765

776766
async def _create_provider_evaluation(
777767
self,

openfeature/hook/__init__.py

Lines changed: 0 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -128,66 +128,3 @@ def supports_flag_value_type(self, flag_type: FlagType) -> bool:
128128
or not (False)
129129
"""
130130
return True
131-
132-
class AsyncHook:
133-
async def before(
134-
self, hook_context: HookContext, hints: HookHints
135-
) -> typing.Optional[EvaluationContext]:
136-
"""
137-
Runs before flag is resolved.
138-
139-
:param hook_context: Information about the particular flag evaluation
140-
:param hints: An immutable mapping of data for users to
141-
communicate to the hooks.
142-
:return: An EvaluationContext. It will be merged with the
143-
EvaluationContext instances from other hooks, the client and API.
144-
"""
145-
return None
146-
147-
async def after(
148-
self,
149-
hook_context: HookContext,
150-
details: FlagEvaluationDetails[typing.Any],
151-
hints: HookHints,
152-
) -> None:
153-
"""
154-
Runs after a flag is resolved.
155-
156-
:param hook_context: Information about the particular flag evaluation
157-
:param details: Information about how the flag was resolved,
158-
including any resolved values.
159-
:param hints: A mapping of data for users to communicate to the hooks.
160-
"""
161-
pass
162-
163-
async def error(
164-
self, hook_context: HookContext, exception: Exception, hints: HookHints
165-
) -> None:
166-
"""
167-
Run when evaluation encounters an error. Errors thrown will be swallowed.
168-
169-
:param hook_context: Information about the particular flag evaluation
170-
:param exception: The exception that was thrown
171-
:param hints: A mapping of data for users to communicate to the hooks.
172-
"""
173-
pass
174-
175-
async def finally_after(self, hook_context: HookContext, hints: HookHints) -> None:
176-
"""
177-
Run after flag evaluation, including any error processing.
178-
This will always run. Errors will be swallowed.
179-
180-
:param hook_context: Information about the particular flag evaluation
181-
:param hints: A mapping of data for users to communicate to the hooks.
182-
"""
183-
pass
184-
185-
def supports_flag_value_type(self, flag_type: FlagType) -> bool:
186-
"""
187-
Check to see if the hook supports the particular flag type.
188-
189-
:param flag_type: particular type of the flag
190-
:return: a boolean containing whether the flag type is supported (True)
191-
or not (False)
192-
"""
193-
return True

openfeature/hook/_hook_support.py

Lines changed: 0 additions & 124 deletions
Original file line numberDiff line numberDiff line change
@@ -22,19 +22,6 @@ def error_hooks(
2222
)
2323

2424

25-
async def error_hooks_async(
26-
flag_type: FlagType,
27-
hook_context: HookContext,
28-
exception: Exception,
29-
hooks: typing.List[Hook],
30-
hints: typing.Optional[HookHints] = None,
31-
) -> None:
32-
kwargs = {"hook_context": hook_context, "exception": exception, "hints": hints}
33-
await _execute_hooks_async(
34-
flag_type=flag_type, hooks=hooks, hook_method=HookType.ERROR, **kwargs
35-
)
36-
37-
3825
def after_all_hooks(
3926
flag_type: FlagType,
4027
hook_context: HookContext,
@@ -47,18 +34,6 @@ def after_all_hooks(
4734
)
4835

4936

50-
async def after_all_hooks_async(
51-
flag_type: FlagType,
52-
hook_context: HookContext,
53-
hooks: typing.List[Hook],
54-
hints: typing.Optional[HookHints] = None,
55-
) -> None:
56-
kwargs = {"hook_context": hook_context, "hints": hints}
57-
await _execute_hooks_async(
58-
flag_type=flag_type, hooks=hooks, hook_method=HookType.FINALLY_AFTER, **kwargs
59-
)
60-
61-
6237
def after_hooks(
6338
flag_type: FlagType,
6439
hook_context: HookContext,
@@ -72,19 +47,6 @@ def after_hooks(
7247
)
7348

7449

75-
async def after_hooks_async(
76-
flag_type: FlagType,
77-
hook_context: HookContext,
78-
details: FlagEvaluationDetails[typing.Any],
79-
hooks: typing.List[Hook],
80-
hints: typing.Optional[HookHints] = None,
81-
) -> None:
82-
kwargs = {"hook_context": hook_context, "details": details, "hints": hints}
83-
await _execute_hooks_async_unchecked(
84-
flag_type=flag_type, hooks=hooks, hook_method=HookType.AFTER, **kwargs
85-
)
86-
87-
8850
def before_hooks(
8951
flag_type: FlagType,
9052
hook_context: HookContext,
@@ -103,23 +65,6 @@ def before_hooks(
10365
return EvaluationContext()
10466

10567

106-
async def before_hooks_async(
107-
flag_type: FlagType,
108-
hook_context: HookContext,
109-
hooks: typing.List[Hook],
110-
hints: typing.Optional[HookHints] = None,
111-
) -> EvaluationContext:
112-
kwargs = {"hook_context": hook_context, "hints": hints}
113-
executed_hooks = await _execute_hooks_async(
114-
flag_type=flag_type, hooks=hooks, hook_method=HookType.BEFORE, **kwargs
115-
)
116-
filtered_hooks = [result for result in executed_hooks if result is not None]
117-
if filtered_hooks:
118-
return reduce(lambda a, b: a.merge(b), filtered_hooks)
119-
120-
return EvaluationContext()
121-
122-
12368
def _execute_hooks(
12469
flag_type: FlagType,
12570
hooks: typing.List[Hook],
@@ -143,29 +88,6 @@ def _execute_hooks(
14388
]
14489

14590

146-
async def _execute_hooks_async(
147-
flag_type: FlagType,
148-
hooks: typing.List[Hook],
149-
hook_method: HookType,
150-
**kwargs: typing.Any,
151-
) -> list:
152-
"""
153-
Run multiple hooks of any hook type. All of these hooks will be run through an
154-
exception check.
155-
156-
:param flag_type: particular type of flag
157-
:param hooks: a list of hooks
158-
:param hook_method: the type of hook that is being run
159-
:param kwargs: arguments that need to be provided to the hook method
160-
:return: a list of results from the applied hook methods
161-
"""
162-
return [
163-
await _execute_hook_checked_async(hook, hook_method, **kwargs)
164-
for hook in hooks
165-
if hook.supports_flag_value_type(flag_type)
166-
]
167-
168-
16991
def _execute_hooks_unchecked(
17092
flag_type: FlagType,
17193
hooks: typing.List[Hook],
@@ -190,30 +112,6 @@ def _execute_hooks_unchecked(
190112
]
191113

192114

193-
async def _execute_hooks_async_unchecked(
194-
flag_type: FlagType,
195-
hooks: typing.List[Hook],
196-
hook_method: HookType,
197-
**kwargs: typing.Any,
198-
) -> typing.List[typing.Optional[EvaluationContext]]:
199-
"""
200-
Execute a single hook without checking whether an exception is thrown. This is
201-
used in the before and after hooks since any exception will be caught in the
202-
client.
203-
204-
:param flag_type: particular type of flag
205-
:param hooks: a list of hooks
206-
:param hook_method: the type of hook that is being run
207-
:param kwargs: arguments that need to be provided to the hook method
208-
:return: a list of results from the applied hook methods
209-
"""
210-
return [
211-
await getattr(hook, hook_method.value)(**kwargs)
212-
for hook in hooks
213-
if hook.supports_flag_value_type(flag_type)
214-
]
215-
216-
217115
def _execute_hook_checked(
218116
hook: Hook, hook_method: HookType, **kwargs: typing.Any
219117
) -> typing.Optional[EvaluationContext]:
@@ -234,25 +132,3 @@ def _execute_hook_checked(
234132
except Exception: # pragma: no cover
235133
logger.exception(f"Exception when running {hook_method.value} hooks")
236134
return None
237-
238-
239-
async def _execute_hook_checked_async(
240-
hook: Hook, hook_method: HookType, **kwargs: typing.Any
241-
) -> typing.Optional[EvaluationContext]:
242-
"""
243-
Try and run a single hook and catch any exception thrown. This is used in the
244-
after all and error hooks since any error thrown at this point needs to be caught.
245-
246-
:param hook: a list of hooks
247-
:param hook_method: the type of hook that is being run
248-
:param kwargs: arguments that need to be provided to the hook method
249-
:return: the result of the hook method
250-
"""
251-
try:
252-
return typing.cast(
253-
"typing.Optional[EvaluationContext]",
254-
await getattr(hook, hook_method.value)(**kwargs),
255-
)
256-
except Exception: # pragma: no cover
257-
logger.exception(f"Exception when running {hook_method.value} hooks")
258-
return None

tests/hook/conftest.py

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import pytest
44

55
from openfeature.evaluation_context import EvaluationContext
6-
from openfeature.hook import AsyncHook
76

87

98
@pytest.fixture()
@@ -15,14 +14,3 @@ def mock_hook():
1514
mock_hook.error.return_value = None
1615
mock_hook.finally_after.return_value = None
1716
return mock_hook
18-
19-
20-
@pytest.fixture()
21-
def mock_hook_async():
22-
mock_hook = AsyncHook()
23-
mock_hook.supports_flag_value_type = mock.MagicMock(return_value=True)
24-
mock_hook.before = mock.AsyncMock(return_value=None)
25-
mock_hook.after = mock.AsyncMock(return_value=None)
26-
mock_hook.error = mock.AsyncMock(return_value=None)
27-
mock_hook.finally_after = mock.AsyncMock(return_value=None)
28-
return mock_hook

0 commit comments

Comments
 (0)