From ade462ed58a2adde4a8f5052c578578785cf1786 Mon Sep 17 00:00:00 2001 From: Federico Bond Date: Thu, 14 Mar 2024 09:26:17 +1100 Subject: [PATCH] refactor: replace EventSupport class with module-level functions Signed-off-by: Federico Bond --- openfeature/_event_support.py | 141 ++++++++++++++++--------------- openfeature/api.py | 25 +----- openfeature/client.py | 6 +- openfeature/provider/provider.py | 5 +- openfeature/provider/registry.py | 5 +- 5 files changed, 80 insertions(+), 102 deletions(-) diff --git a/openfeature/_event_support.py b/openfeature/_event_support.py index c15d68b0..32cdb453 100644 --- a/openfeature/_event_support.py +++ b/openfeature/_event_support.py @@ -15,72 +15,75 @@ from openfeature.client import OpenFeatureClient -class EventSupport: - _global_handlers: Dict[ProviderEvent, List[EventHandler]] - _client_handlers: Dict[OpenFeatureClient, Dict[ProviderEvent, List[EventHandler]]] - - def __init__(self) -> None: - self._global_handlers = defaultdict(list) - self._client_handlers = defaultdict(lambda: defaultdict(list)) - - def run_client_handlers( - self, client: OpenFeatureClient, event: ProviderEvent, details: EventDetails - ) -> None: - for handler in self._client_handlers[client][event]: - handler(details) - - def run_global_handlers(self, event: ProviderEvent, details: EventDetails) -> None: - for handler in self._global_handlers[event]: - handler(details) - - def add_client_handler( - self, client: OpenFeatureClient, event: ProviderEvent, handler: EventHandler - ) -> None: - handlers = self._client_handlers[client][event] - handlers.append(handler) - - self._run_immediate_handler(client, event, handler) - - def remove_client_handler( - self, client: OpenFeatureClient, event: ProviderEvent, handler: EventHandler - ) -> None: - handlers = self._client_handlers[client][event] - handlers.remove(handler) - - def add_global_handler(self, event: ProviderEvent, handler: EventHandler) -> None: - self._global_handlers[event].append(handler) - - from openfeature.api import get_client - - self._run_immediate_handler(get_client(), event, handler) - - def remove_global_handler( - self, event: ProviderEvent, handler: EventHandler - ) -> None: - self._global_handlers[event].remove(handler) - - def run_handlers_for_provider( - self, - provider: FeatureProvider, - event: ProviderEvent, - provider_details: ProviderEventDetails, - ) -> None: - details = EventDetails.from_provider_event_details( - provider.get_metadata().name, provider_details - ) - # run the global handlers - self.run_global_handlers(event, details) - # run the handlers for clients associated to this provider - for client in self._client_handlers: - if client.provider == provider: - self.run_client_handlers(client, event, details) - - def _run_immediate_handler( - self, client: OpenFeatureClient, event: ProviderEvent, handler: EventHandler - ) -> None: - if event == ProviderEvent.from_provider_status(client.get_provider_status()): - handler(EventDetails(provider_name=client.provider.get_metadata().name)) - - def clear(self) -> None: - self._global_handlers.clear() - self._client_handlers.clear() +_global_handlers: Dict[ProviderEvent, List[EventHandler]] = defaultdict(list) +_client_handlers: Dict[ + OpenFeatureClient, Dict[ProviderEvent, List[EventHandler]] +] = defaultdict(lambda: defaultdict(list)) + + +def run_client_handlers( + client: OpenFeatureClient, event: ProviderEvent, details: EventDetails +) -> None: + for handler in _client_handlers[client][event]: + handler(details) + + +def run_global_handlers(event: ProviderEvent, details: EventDetails) -> None: + for handler in _global_handlers[event]: + handler(details) + + +def add_client_handler( + client: OpenFeatureClient, event: ProviderEvent, handler: EventHandler +) -> None: + handlers = _client_handlers[client][event] + handlers.append(handler) + + _run_immediate_handler(client, event, handler) + + +def remove_client_handler( + client: OpenFeatureClient, event: ProviderEvent, handler: EventHandler +) -> None: + handlers = _client_handlers[client][event] + handlers.remove(handler) + + +def add_global_handler(event: ProviderEvent, handler: EventHandler) -> None: + _global_handlers[event].append(handler) + + from openfeature.api import get_client + + _run_immediate_handler(get_client(), event, handler) + + +def remove_global_handler(event: ProviderEvent, handler: EventHandler) -> None: + _global_handlers[event].remove(handler) + + +def run_handlers_for_provider( + provider: FeatureProvider, + event: ProviderEvent, + provider_details: ProviderEventDetails, +) -> None: + details = EventDetails.from_provider_event_details( + provider.get_metadata().name, provider_details + ) + # run the global handlers + run_global_handlers(event, details) + # run the handlers for clients associated to this provider + for client in _client_handlers: + if client.provider == provider: + run_client_handlers(client, event, details) + + +def _run_immediate_handler( + client: OpenFeatureClient, event: ProviderEvent, handler: EventHandler +) -> None: + if event == ProviderEvent.from_provider_status(client.get_provider_status()): + handler(EventDetails(provider_name=client.provider.get_metadata().name)) + + +def clear() -> None: + _global_handlers.clear() + _client_handlers.clear() diff --git a/openfeature/api.py b/openfeature/api.py index bbbda081..4460cc70 100644 --- a/openfeature/api.py +++ b/openfeature/api.py @@ -1,12 +1,11 @@ import typing -from openfeature._event_support import EventSupport +from openfeature import _event_support from openfeature.client import OpenFeatureClient from openfeature.evaluation_context import EvaluationContext from openfeature.event import ( EventHandler, ProviderEvent, - ProviderEventDetails, ) from openfeature.exception import GeneralError from openfeature.hook import Hook @@ -20,8 +19,6 @@ _provider_registry: ProviderRegistry = ProviderRegistry() -_event_support: EventSupport = EventSupport() - def get_client( domain: typing.Optional[str] = None, version: typing.Optional[str] = None @@ -84,23 +81,3 @@ def add_handler(event: ProviderEvent, handler: EventHandler) -> None: def remove_handler(event: ProviderEvent, handler: EventHandler) -> None: _event_support.remove_global_handler(event, handler) - - -def _add_client_handler( - client: OpenFeatureClient, event: ProviderEvent, handler: EventHandler -) -> None: - _event_support.add_client_handler(client, event, handler) - - -def _remove_client_handler( - client: OpenFeatureClient, event: ProviderEvent, handler: EventHandler -) -> None: - _event_support.remove_client_handler(client, event, handler) - - -def _run_handlers_for_provider( - provider: FeatureProvider, - event: ProviderEvent, - provider_details: ProviderEventDetails, -) -> None: - _event_support.run_handlers_for_provider(provider, event, provider_details) diff --git a/openfeature/client.py b/openfeature/client.py index 384f37b5..9847ee6b 100644 --- a/openfeature/client.py +++ b/openfeature/client.py @@ -2,7 +2,7 @@ import typing from dataclasses import dataclass -from openfeature import api +from openfeature import _event_support, api from openfeature.evaluation_context import EvaluationContext from openfeature.event import EventHandler, ProviderEvent from openfeature.exception import ( @@ -440,10 +440,10 @@ def _create_provider_evaluation( ) def add_handler(self, event: ProviderEvent, handler: EventHandler) -> None: - api._add_client_handler(self, event, handler) + _event_support.add_client_handler(self, event, handler) def remove_handler(self, event: ProviderEvent, handler: EventHandler) -> None: - api._remove_client_handler(self, event, handler) + _event_support.remove_client_handler(self, event, handler) def _typecheck_flag_value(value: typing.Any, flag_type: FlagType) -> None: diff --git a/openfeature/provider/provider.py b/openfeature/provider/provider.py index 70486e96..2e5da576 100644 --- a/openfeature/provider/provider.py +++ b/openfeature/provider/provider.py @@ -1,6 +1,7 @@ import typing from abc import abstractmethod +from openfeature._event_support import run_handlers_for_provider from openfeature.evaluation_context import EvaluationContext from openfeature.event import ProviderEvent, ProviderEventDetails from openfeature.flag_evaluation import FlagResolutionDetails @@ -83,6 +84,4 @@ def emit_provider_stale(self, details: ProviderEventDetails) -> None: self.emit(ProviderEvent.PROVIDER_STALE, details) def emit(self, event: ProviderEvent, details: ProviderEventDetails) -> None: - from openfeature.api import _run_handlers_for_provider - - _run_handlers_for_provider(self, event, details) + run_handlers_for_provider(self, event, details) diff --git a/openfeature/provider/registry.py b/openfeature/provider/registry.py index f15ddb45..8d764465 100644 --- a/openfeature/provider/registry.py +++ b/openfeature/provider/registry.py @@ -1,5 +1,6 @@ import typing +from openfeature._event_support import run_handlers_for_provider from openfeature.evaluation_context import EvaluationContext from openfeature.event import ( ProviderEvent, @@ -100,6 +101,4 @@ def _set_provider_status( self._provider_status[provider] = status if event := ProviderEvent.from_provider_status(status): - from openfeature.api import _run_handlers_for_provider - - _run_handlers_for_provider(provider, event, ProviderEventDetails()) + run_handlers_for_provider(provider, event, ProviderEventDetails())