From ab0c3641e014093babd3b5fe5c33b6586511e077 Mon Sep 17 00:00:00 2001 From: vjymisal0 Date: Wed, 11 Nov 2026 10:18:36 +0530 Subject: [PATCH 1/3] feat: expose client readiness for local evaluation Signed-off-by: vjymisal0 --- README.md | 21 +++++++++++++++++++++ flagsmith/flagsmith.py | 12 ++++++++++++ tests/test_flagsmith.py | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+) diff --git a/README.md b/README.md index 583de91..0359870 100644 --- a/README.md +++ b/README.md @@ -10,6 +10,27 @@ The SDK for Python applications for [https://www.flagsmith.com/](https://www.fla For full documentation visit [https://docs.flagsmith.com/clients/server-side?language=python](https://docs.flagsmith.com/clients/server-side?language=python). +## Checking client readiness + +`flagsmith.ready()` returns whether the client has an environment document +available for local or offline evaluation. It makes no network requests and +does not block. Remote-evaluation clients return `True` immediately; readiness +does not indicate API connectivity or document freshness. + +If the initial local-evaluation fetch fails, readiness is `False` until the +background poller successfully loads a document. A later refresh failure keeps +the last successful document available, so readiness remains `True`. + +Check readiness before evaluating flags to avoid the existing remote API +fallback while the first local document is unavailable: + +```python +if flagsmith.ready(): + enabled = flagsmith.get_environment_flags().is_feature_enabled("feature") +else: + enabled = False # Application-defined fallback while waiting for a document. +``` + ## Contributing Please read [CONTRIBUTING.md](CONTRIBUTING.md) for details on our code of conduct, and the process for submitting pull diff --git a/flagsmith/flagsmith.py b/flagsmith/flagsmith.py index f50ceec..9328011 100644 --- a/flagsmith/flagsmith.py +++ b/flagsmith/flagsmith.py @@ -275,6 +275,18 @@ def handle_stream_event(self, event: StreamEvent) -> None: if event["updated_at"] > environment_updated_at: self.update_environment() + def ready(self) -> bool: + """Return whether the client can evaluate in its configured mode. + + Local and offline evaluation require an environment document. Remote + evaluation is immediately ready; this does not check API connectivity. + This method does not make requests or wait for a document to load. + """ + return ( + not (self.enable_local_evaluation or self.offline_mode) + or self._local_evaluation is not None + ) + def get_environment_flags(self) -> Flags: """ Get all the default for flags for the current environment. diff --git a/tests/test_flagsmith.py b/tests/test_flagsmith.py index 7998c23..0b79fee 100644 --- a/tests/test_flagsmith.py +++ b/tests/test_flagsmith.py @@ -23,6 +23,41 @@ from flagsmith.types import SDKEvaluationContext +@responses.activate() +def test_ready_tracks_local_document_availability( + mocker: MockerFixture, environment_json: str +) -> None: + mocker.patch("flagsmith.flagsmith.EnvironmentDataPollingManager") + url = "https://edge.api.flagsmith.com/api/v1/environment-document/" + responses.get(url, status=500) + responses.get(url, body=environment_json) + responses.get(url, status=500) + client = Flagsmith(environment_key="ser.test", enable_local_evaluation=True) + + assert client.ready() is False + assert len(responses.calls) == 1 + client.update_environment() + assert client.ready() is True + client.update_environment() + assert client.ready() is True + assert len(responses.calls) == 3 + + +def test_ready_remote_evaluation(flagsmith: Flagsmith) -> None: + assert flagsmith.ready() is True + + +def test_ready_offline_document( + mocker: MockerFixture, environment: EnvironmentModel +) -> None: + handler = mocker.Mock(spec=OfflineHandler) + handler.get_environment.return_value = environment + client = Flagsmith(offline_mode=True, offline_handler=handler) + + assert client.ready() is True + assert client.get_environment_flags().is_feature_enabled("some_feature") + + def test_flagsmith_starts_polling_manager_on_init_if_enabled( mocker: MockerFixture, server_api_key: str, requests_session_response_ok: None ) -> None: From 2af2aad27f603b686201f0b17fc832d633ed62bb Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Wed, 11 Nov 2026 04:49:02 +0000 Subject: [PATCH 2/3] [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --- README.md | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 0359870..db22205 100644 --- a/README.md +++ b/README.md @@ -12,17 +12,15 @@ For full documentation visit ## Checking client readiness -`flagsmith.ready()` returns whether the client has an environment document -available for local or offline evaluation. It makes no network requests and -does not block. Remote-evaluation clients return `True` immediately; readiness -does not indicate API connectivity or document freshness. +`flagsmith.ready()` returns whether the client has an environment document available for local or offline evaluation. It +makes no network requests and does not block. Remote-evaluation clients return `True` immediately; readiness does not +indicate API connectivity or document freshness. -If the initial local-evaluation fetch fails, readiness is `False` until the -background poller successfully loads a document. A later refresh failure keeps -the last successful document available, so readiness remains `True`. +If the initial local-evaluation fetch fails, readiness is `False` until the background poller successfully loads a +document. A later refresh failure keeps the last successful document available, so readiness remains `True`. -Check readiness before evaluating flags to avoid the existing remote API -fallback while the first local document is unavailable: +Check readiness before evaluating flags to avoid the existing remote API fallback while the first local document is +unavailable: ```python if flagsmith.ready(): From 5e5b31678d56267ed3552168b1ea6344994e7080 Mon Sep 17 00:00:00 2001 From: vjymisal0 Date: Wed, 11 Nov 2026 10:37:12 +0530 Subject: [PATCH 3/3] docs: distinguish realtime startup failures from polling readiness --- README.md | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 0359870..f2f751c 100644 --- a/README.md +++ b/README.md @@ -17,9 +17,11 @@ available for local or offline evaluation. It makes no network requests and does not block. Remote-evaluation clients return `True` immediately; readiness does not indicate API connectivity or document freshness. -If the initial local-evaluation fetch fails, readiness is `False` until the -background poller successfully loads a document. A later refresh failure keeps -the last successful document available, so readiness remains `True`. +If the initial local-evaluation fetch fails and no document is available, +clients with realtime updates disabled are not ready until the background +poller loads a document. With realtime updates enabled, construction raises +`ValueError` instead. A later refresh failure keeps the last successful +document available, so readiness remains `True`. Check readiness before evaluating flags to avoid the existing remote API fallback while the first local document is unavailable: