Skip to content

Commit c3ad697

Browse files
authored
refactor: bind providers explicitly to a registry with attach/detach (#324)
* test: make sure provider is registered in events test Signed-off-by: Federico Bond <[email protected]> * refactor: bind providers explicitly to a registry with attach/detach Signed-off-by: Federico Bond <[email protected]> --------- Signed-off-by: Federico Bond <[email protected]>
1 parent f352045 commit c3ad697

File tree

3 files changed

+27
-5
lines changed

3 files changed

+27
-5
lines changed

openfeature/provider/__init__.py

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,15 @@ class ProviderStatus(Enum):
2323

2424

2525
class FeatureProvider(typing.Protocol): # pragma: no cover
26+
def attach(
27+
self,
28+
on_emit: typing.Callable[
29+
[FeatureProvider, ProviderEvent, ProviderEventDetails], None
30+
],
31+
) -> None: ...
32+
33+
def detach(self) -> None: ...
34+
2635
def initialize(self, evaluation_context: EvaluationContext) -> None: ...
2736

2837
def shutdown(self) -> None: ...
@@ -68,6 +77,18 @@ def resolve_object_details(
6877

6978

7079
class AbstractProvider(FeatureProvider):
80+
def attach(
81+
self,
82+
on_emit: typing.Callable[
83+
[FeatureProvider, ProviderEvent, ProviderEventDetails], None
84+
],
85+
) -> None:
86+
self._on_emit = on_emit
87+
88+
def detach(self) -> None:
89+
if hasattr(self, "_on_emit"):
90+
del self._on_emit
91+
7192
def initialize(self, evaluation_context: EvaluationContext) -> None:
7293
pass
7394

@@ -141,6 +162,5 @@ def emit_provider_stale(self, details: ProviderEventDetails) -> None:
141162
self.emit(ProviderEvent.PROVIDER_STALE, details)
142163

143164
def emit(self, event: ProviderEvent, details: ProviderEventDetails) -> None:
144-
from openfeature.provider._registry import provider_registry
145-
146-
provider_registry.dispatch_event(self, event, details)
165+
if hasattr(self, "_on_emit"):
166+
self._on_emit(self, event, details)

openfeature/provider/_registry.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ def _get_evaluation_context(self) -> EvaluationContext:
7171
return get_evaluation_context()
7272

7373
def _initialize_provider(self, provider: FeatureProvider) -> None:
74+
provider.attach(self.dispatch_event)
7475
try:
7576
if hasattr(provider, "initialize"):
7677
provider.initialize(self._get_evaluation_context())
@@ -106,6 +107,7 @@ def _shutdown_provider(self, provider: FeatureProvider) -> None:
106107
error_code=ErrorCode.PROVIDER_FATAL,
107108
),
108109
)
110+
provider.detach()
109111

110112
def get_provider_status(self, provider: FeatureProvider) -> ProviderStatus:
111113
return self._provider_status.get(provider, ProviderStatus.NOT_READY)

tests/test_api.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ def test_clear_providers_shutdowns_every_provider_and_resets_default_provider():
235235
def test_provider_events():
236236
# Given
237237
spy = MagicMock()
238+
provider = NoOpProvider()
239+
set_provider(provider)
238240

239241
add_handler(ProviderEvent.PROVIDER_READY, spy.provider_ready)
240242
add_handler(
@@ -243,8 +245,6 @@ def test_provider_events():
243245
add_handler(ProviderEvent.PROVIDER_ERROR, spy.provider_error)
244246
add_handler(ProviderEvent.PROVIDER_STALE, spy.provider_stale)
245247

246-
provider = NoOpProvider()
247-
248248
provider_details = ProviderEventDetails(message="message")
249249
details = EventDetails.from_provider_event_details(
250250
provider.get_metadata().name, provider_details

0 commit comments

Comments
 (0)