Skip to content

Commit 4290b8a

Browse files
feat: Report provider name and version to LaunchDarkly (#51)
The provider now identifies itself as the wrapper, so requests it makes are attributed to the OpenFeature provider rather than to the Python SDK. - Sets `wrapper_name` to `open-feature-python-server` and `wrapper_version` to the provider version - Uses `Config.with_wrapper_information`, released in launchdarkly-server-sdk 9.17.0 - Raises the SDK floor to `>=9.17.0` - Adds `ld_openfeature/version.py`, kept current by release-please **Requirements** - [x] I have added test coverage for new or changed functionality - [x] I have followed the repository's [pull request submission guidelines](../blob/main/CONTRIBUTING.md#submitting-pull-requests) - [x] I have validated my changes against all supported platform versions <details> <summary>Implementation details</summary> **Describe the solution you've provided** ```python self.__client = LDClient(config.with_wrapper_information(WRAPPER_NAME, VERSION)) ``` This matches the Java and .NET providers, which derive a config from the application-supplied one: ```java new LDClient(sdkKey, LDConfig.Builder.fromConfig(config) .wrapper(Components.wrapperInfo() .wrapperName("open-feature-java-server") .wrapperVersion(Version.SDK_VERSION)).build()); ``` The provider version comes from a new `ld_openfeature/version.py`, added to `extra-files` in `release-please-config.json` so the constant is bumped with each release the same way `docs/conf.py` already is. **Describe alternatives you've considered** An earlier revision of this PR copied the `Config` and assigned its name-mangled private wrapper fields, because wrapper information could only be supplied to the constructor. That depends on SDK internals, hence the SDK change instead ([python-server-sdk#501](launchdarkly/python-server-sdk#501)). **Testing** `test_provider_identifies_itself_as_the_wrapper` asserts the client's config carries the provider's name and version, and that the config passed in by the caller is unchanged. Against the released 9.17.0: 80 tests pass, mypy clean. </details> Link to Devin session: https://app.devin.ai/sessions/0c452d209ec54b068ba120b4c92b8f6c Open in Devin Desktop: https://app.devin.ai/desktop/session/0c452d209ec54b068ba120b4c92b8f6c?variant=devin Requested by: @kinyoklion <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **Overview** > LaunchDarkly traffic from this provider is now attributed to the OpenFeature integration instead of looking like plain Python SDK usage. > > `LaunchDarklyProvider` builds the underlying `LDClient` from `config.with_wrapper_information("open-feature-python-server", VERSION)` so wrapper name and version are set on the client config without mutating the caller’s `Config`. The version lives in new `ld_openfeature/version.py`, wired into release-please alongside `docs/conf.py`. > > The minimum `launchdarkly-server-sdk` dependency is raised to **>=9.17.0** for `with_wrapper_information`. A test asserts the client carries the expected wrapper fields and that the original config’s `wrapper_name` stays unset. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 8f3861b. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Devin AI <devin-ai-integration[bot]@users.noreply.github.com> Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
1 parent 9395775 commit 4290b8a

5 files changed

Lines changed: 15 additions & 3 deletions

File tree

ld_openfeature/provider.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,18 @@
1616

1717
from ld_openfeature.impl.context_converter import EvaluationContextConverter
1818
from ld_openfeature.impl.details_converter import ResolutionDetailsConverter
19+
from ld_openfeature.version import VERSION
20+
21+
22+
WRAPPER_NAME = "open-feature-python-server"
1923

2024

2125
logger = getLogger("launchdarkly-openfeature-server")
2226

2327

2428
class LaunchDarklyProvider(AbstractProvider):
2529
def __init__(self, config: Config):
26-
self.__client = LDClient(config)
30+
self.__client = LDClient(config.with_wrapper_information(WRAPPER_NAME, VERSION))
2731

2832
self.__context_converter = EvaluationContextConverter()
2933
self.__details_converter = ResolutionDetailsConverter()

ld_openfeature/version.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
VERSION = "0.6.0" # x-release-please-version

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ packages = [
2727
[tool.poetry.dependencies]
2828
python = "^3.10"
2929
openfeature-sdk = ">=0.9.0,<1"
30-
launchdarkly-server-sdk = "<10"
30+
launchdarkly-server-sdk = ">=9.17.0,<10"
3131

3232

3333
[tool.poetry.group.dev.dependencies]

release-please-config.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"release-type": "python",
55
"versioning": "default",
66
"include-v-in-tag": false,
7-
"extra-files": ["docs/conf.py"],
7+
"extra-files": ["docs/conf.py", "ld_openfeature/version.py"],
88
"include-component-in-tag": false
99
}
1010
}

tests/test_provider.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
from openfeature import api
1717

1818
from ld_openfeature import LaunchDarklyProvider, Config
19+
from ld_openfeature.version import VERSION
1920
from tests.test_data_sources import FailingDataSource, InitializedThenFailingDataSource, StaleDataSource, UpdatingDataSource, DelayedFailingDataSource
2021

2122

@@ -49,6 +50,12 @@ def test_ldclient_is_accessible(provider: LaunchDarklyProvider):
4950
assert type(provider.client) is LDClient
5051

5152

53+
def test_provider_identifies_itself_as_the_wrapper(provider: LaunchDarklyProvider, config: Config):
54+
assert provider.client._config.wrapper_name == "open-feature-python-server"
55+
assert provider.client._config.wrapper_version == VERSION
56+
assert config.wrapper_name is None
57+
58+
5259
def test_not_providing_context_returns_error(provider: LaunchDarklyProvider):
5360
resolution_details = provider.resolve_boolean_details("flag-key", True, None)
5461

0 commit comments

Comments
 (0)