Skip to content

Commit 283bfe8

Browse files
committed
chore(deps): move the workspace onto openfeature-sdk 0.10.0
The lock has resolved 0.8.4 since 2025-12-09 while 0.9.0 and 0.10.0 have shipped, so nothing in this repository has ever been tested against either. Nothing pinned it there: every floor is a `>=`, every member is `requires-python >=3.10`, and the lock carries no constraints -- renovate's lock-file maintenance simply never picked the release up. `uv lock --upgrade-package openfeature-sdk` moves 0.8.4 -> 0.10.0 and touches nothing else. Two behaviour changes reach the tests. Neither touches the flagd source, which needs no change and stays clean under `poe mypy` on 26 files. First, 0.10.0 made `set_provider` non-blocking, so a test that sets a provider and evaluates on the next line now races initialisation and reads PROVIDER_NOT_READY -- 20 failures across test_errors.py and test_metadata.py. `set_provider_and_wait` restores the old blocking behaviour with one difference that matters here: it re-raises whatever `initialize` raised, where `set_provider` only dispatched PROVIDER_ERROR. Several of these scenarios feed the provider a deliberately broken flag file, so that raise is the scenario rather than a failure, hence the `contextlib.suppress`; it is not papering over an unexpected error. Second, 0.10.0 isolated event-handler dispatch onto a ThreadPoolExecutor where 0.8.4 called handlers inline -- open-feature/python-sdk#599. test_grpc_sync_fail_deadline read a flag set by a PROVIDER_ERROR handler on the line after the call returned, which is now a race: `_run_initialize` submits the event and then re-raises, and submit is not run. Rather than wait on the handler, the assertion goes: it existed because the old `set_provider` blocked and swallowed the error, leaving the event as the only way to observe a failed init, and `pytest.raises(ProviderNotReadyError)` now carries that claim directly. What the handler would assert today is that the SDK's registry dispatches PROVIDER_ERROR when `initialize` raises -- SDK plumbing, uniform across providers, and not this suite's to cover. The deadline measurement it shared the test with is untouched, though it now has to wait rather than time a call that would return immediately. The other two handler-driven tests here -- test_invalid_flag_set_metadata and the e2e event steps -- already poll with a timeout and need nothing. The tests are the only thing that needs 0.10.0, so the floor goes in flagd's dev group and the runtime floor stays at 0.8.2. Measured, not assumed: flagd is 208 passed at 0.8.4 and 208 passed at 0.10.0 after this change, having been 188 passed / 20 failed in between. CI covers tests/e2e, which needs docker, and reported 783 passed on this branch with the handler race as its only failure. The other nine packages pass tests and mypy unchanged, except unleash, which the next commit fixes. Signed-off-by: Simon Schrottner <simon.schrottner@flagsmith.com>
1 parent 8416d9d commit 283bfe8

4 files changed

Lines changed: 31 additions & 23 deletions

File tree

‎providers/openfeature-provider-flagd/pyproject.toml‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ dev = [
3535
"coverage[toml]>=7.10.0,<8.0.0",
3636
"grpcio-health-checking>=1.82.1,<2.0.0",
3737
"mypy>=1.18.0,<2.0.0",
38+
# The tests call `api.set_provider_and_wait`, which arrived in 0.10.0. The
39+
# runtime floor stays at 0.8.2 because the provider itself needs nothing newer.
40+
"openfeature-sdk>=0.10.0",
3841
"poethepoet>=0.37.0",
3942
"pytest>=9.0.0,<10.0.0",
4043
"pytest-bdd>=8.1.0,<9.0.0",

‎providers/openfeature-provider-flagd/tests/test_errors.py‎

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import contextlib
12
import os
23
import time
34

@@ -7,13 +8,19 @@
78
from openfeature.contrib.provider.flagd import FlagdProvider
89
from openfeature.contrib.provider.flagd.config import ResolverType
910
from openfeature.evaluation_context import EvaluationContext
10-
from openfeature.event import ProviderEvent
11-
from openfeature.exception import ErrorCode
11+
from openfeature.exception import (
12+
ErrorCode,
13+
OpenFeatureError,
14+
ProviderNotReadyError,
15+
)
1216
from openfeature.flag_evaluation import Reason
1317

1418

1519
def create_client(provider: FlagdProvider):
16-
api.set_provider(provider)
20+
# These flag files are deliberately broken, so init may fail; what the
21+
# evaluation returns afterwards is the assertion.
22+
with contextlib.suppress(OpenFeatureError):
23+
api.set_provider_and_wait(provider)
1724
return api.get_client()
1825

1926

@@ -119,23 +126,15 @@ def test_flag_disabled():
119126

120127
@pytest.mark.parametrize("wait", (500, 250))
121128
def test_grpc_sync_fail_deadline(wait: int):
122-
init_failed = False
123-
124-
def fail(*args, **kwargs):
125-
nonlocal init_failed
126-
init_failed = True
127-
128-
api.get_client().add_handler(ProviderEvent.PROVIDER_ERROR, fail)
129-
130129
t = time.time()
131-
api.set_provider(
132-
FlagdProvider(
133-
resolver_type=ResolverType.IN_PROCESS,
134-
port=99999, # dead port to test failure
135-
deadline_ms=wait,
130+
with pytest.raises(ProviderNotReadyError):
131+
api.set_provider_and_wait(
132+
FlagdProvider(
133+
resolver_type=ResolverType.IN_PROCESS,
134+
port=99999, # dead port to test failure
135+
deadline_ms=wait,
136+
)
136137
)
137-
)
138138

139139
elapsed = time.time() - t
140140
assert abs(elapsed - wait * 0.001) < 0.17
141-
assert init_failed

‎providers/openfeature-provider-flagd/tests/test_metadata.py‎

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import contextlib
12
import os
23
import time
34
from time import sleep
@@ -11,7 +12,7 @@
1112
_validate_metadata,
1213
)
1314
from openfeature.event import EventDetails, ProviderEvent
14-
from openfeature.exception import ErrorCode, ParseError
15+
from openfeature.exception import ErrorCode, OpenFeatureError, ParseError
1516

1617

1718
def create_client(file_name):
@@ -21,7 +22,10 @@ def create_client(file_name):
2122
offline_flag_source_path=f"{path}/{file_name}",
2223
)
2324

24-
api.set_provider(provider)
25+
# Some of these flag files are deliberately broken, so init may fail; what
26+
# the evaluation returns afterwards is the assertion.
27+
with contextlib.suppress(OpenFeatureError):
28+
api.set_provider_and_wait(provider)
2529
return api.get_client()
2630

2731

‎uv.lock‎

Lines changed: 5 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)