From d6cf0c5c39b198360aa6c590825a7bb08624d6ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pere=20Pic=C3=B3?= Date: Mon, 28 Sep 2026 11:19:02 +0200 Subject: [PATCH] refactor: make ContextEnricher a private collaborator --- UnleashClient/{context.py => _context.py} | 7 ++++++- UnleashClient/_evaluator.py | 6 +++--- UnleashClient/clients/async_unleash_client.py | 4 ++-- UnleashClient/clients/unleash_client.py | 4 ++-- tests/unit_tests/test_context.py | 8 ++++---- tests/unit_tests/test_evaluator.py | 6 +++--- 6 files changed, 20 insertions(+), 15 deletions(-) rename UnleashClient/{context.py => _context.py} (93%) diff --git a/UnleashClient/context.py b/UnleashClient/_context.py similarity index 93% rename from UnleashClient/context.py rename to UnleashClient/_context.py index 7251e625..22909e36 100644 --- a/UnleashClient/context.py +++ b/UnleashClient/_context.py @@ -22,13 +22,18 @@ def _safe_value(value: Any) -> str: return str(value) -class ContextEnricher: +class _ContextEnricher: """ Turns a caller-supplied context into the shape the engine expects. The config's static context is read on every call, so reassigning ``config.static_context`` (which ``UnleashClient.unleash_static_context`` does) takes effect immediately. + + Example:: + + enricher = _ContextEnricher(config) + context = enricher.build({"userId": "123"}) """ def __init__(self, config: UnleashConfig) -> None: diff --git a/UnleashClient/_evaluator.py b/UnleashClient/_evaluator.py index 3088c7e6..07587e31 100644 --- a/UnleashClient/_evaluator.py +++ b/UnleashClient/_evaluator.py @@ -6,8 +6,8 @@ from yggdrasil_engine.engine import UnleashEngine +from UnleashClient._context import _ContextEnricher from UnleashClient.config import UnleashConfig -from UnleashClient.context import ContextEnricher from UnleashClient.events import ( EventDispatcher, UnleashEvent, @@ -29,7 +29,7 @@ class _Evaluator: def __init__( self, engine: UnleashEngine, - enricher: ContextEnricher, + enricher: _ContextEnricher, config: UnleashConfig, events: Optional[EventDispatcher] = None, ) -> None: @@ -40,7 +40,7 @@ def __init__( :param events: Optional dispatcher that delivers events to the user's callback. """ self._engine: UnleashEngine = engine - self._enricher: ContextEnricher = enricher + self._enricher: _ContextEnricher = enricher self._config: UnleashConfig = config self._events: Optional[EventDispatcher] = events diff --git a/UnleashClient/clients/async_unleash_client.py b/UnleashClient/clients/async_unleash_client.py index b4c5428c..712be157 100644 --- a/UnleashClient/clients/async_unleash_client.py +++ b/UnleashClient/clients/async_unleash_client.py @@ -9,6 +9,7 @@ from UnleashClient._async_scheduler import _AsyncScheduler from UnleashClient._async_transport import _AsyncTransport +from UnleashClient._context import _ContextEnricher from UnleashClient._evaluator import _Evaluator from UnleashClient._feature_store import _FeatureStore from UnleashClient._instance_registry import _get_instance_registry @@ -16,7 +17,6 @@ from UnleashClient.cache import BaseCache, FileCache from UnleashClient.config import ExperimentalMode, UnleashConfig from UnleashClient.constants import REQUEST_RETRIES, REQUEST_TIMEOUT -from UnleashClient.context import ContextEnricher from UnleashClient.events import BaseEvent, EventDispatcher from UnleashClient.headers import HeaderFactory from UnleashClient.impact_metrics import ImpactMetrics @@ -84,7 +84,7 @@ def __init__( # noqa: PLR0913, PLR0917 experimental_mode=experimental_mode, custom_strategies=custom_strategies, ) - self._enricher: ContextEnricher = ContextEnricher(self._config) + self._enricher: _ContextEnricher = _ContextEnricher(self._config) self._headers: HeaderFactory = HeaderFactory(self._config) self._event_dispatcher: Optional[EventDispatcher] = ( diff --git a/UnleashClient/clients/unleash_client.py b/UnleashClient/clients/unleash_client.py index 8fad21d2..4d29714e 100644 --- a/UnleashClient/clients/unleash_client.py +++ b/UnleashClient/clients/unleash_client.py @@ -9,6 +9,7 @@ from apscheduler.schedulers.base import BaseScheduler from yggdrasil_engine.engine import UnleashEngine +from UnleashClient._context import _ContextEnricher from UnleashClient._evaluator import _Evaluator from UnleashClient._feature_store import _FeatureStore from UnleashClient._instance_registry import _get_instance_registry @@ -35,7 +36,6 @@ REQUEST_RETRIES, REQUEST_TIMEOUT, ) -from UnleashClient.context import ContextEnricher from UnleashClient.events import ( BaseEvent, EventDispatcher, @@ -177,7 +177,7 @@ def __init__( # noqa: PLR0913, PLR0917 experimental_mode=experimental_mode, custom_strategies=custom_strategies, ) - self._enricher = ContextEnricher(self._config) + self._enricher = _ContextEnricher(self._config) self._headers = HeaderFactory(self._config) self.unleash_event_callback = event_callback # Events are handed to the dispatcher, which delivers them to the user's diff --git a/tests/unit_tests/test_context.py b/tests/unit_tests/test_context.py index e0d30d38..fb8a47a4 100644 --- a/tests/unit_tests/test_context.py +++ b/tests/unit_tests/test_context.py @@ -1,15 +1,15 @@ import uuid from datetime import datetime, timezone +from UnleashClient._context import _ContextEnricher from UnleashClient.config import UnleashConfig -from UnleashClient.context import ContextEnricher URL = "http://localhost:4242/api" APP_NAME = "pytest" -def build_enricher(**kwargs) -> ContextEnricher: - return ContextEnricher(UnleashConfig(URL, APP_NAME, **kwargs)) +def build_enricher(**kwargs) -> _ContextEnricher: + return _ContextEnricher(UnleashConfig(URL, APP_NAME, **kwargs)) def test_static_context_is_merged_in(): @@ -118,7 +118,7 @@ def test_static_context_is_read_on_every_call(): # UnleashClient.unleash_static_context has a setter, so a client can swap # the dict out after the enricher was constructed. config = UnleashConfig(URL, APP_NAME, environment="unit") - enricher = ContextEnricher(config) + enricher = _ContextEnricher(config) config.static_context = {"appName": "replaced", "environment": "qa"} context = enricher.build({}) diff --git a/tests/unit_tests/test_evaluator.py b/tests/unit_tests/test_evaluator.py index 2b3c9e92..371fc9de 100644 --- a/tests/unit_tests/test_evaluator.py +++ b/tests/unit_tests/test_evaluator.py @@ -8,9 +8,9 @@ MOCK_FEATURE_RESPONSE, MOCK_FEATURE_RESPONSE_PROJECT, ) +from UnleashClient._context import _ContextEnricher from UnleashClient._evaluator import _Evaluator from UnleashClient.config import UnleashConfig -from UnleashClient.context import ContextEnricher from UnleashClient.events import UnleashEventType URL = "http://localhost:4242/api" @@ -37,7 +37,7 @@ def build_evaluator(state=FEATURES, events=None, **kwargs): engine.take_state(state) return _Evaluator( engine=engine, - enricher=ContextEnricher(config), + enricher=_ContextEnricher(config), config=config, events=events, ) @@ -184,7 +184,7 @@ def test_the_verbose_log_level_is_read_on_every_call(caplog): engine.take_state(FEATURES) evaluator = _Evaluator( engine=engine, - enricher=ContextEnricher(config), + enricher=_ContextEnricher(config), config=config, events=FailingDispatcher(), )