From 3c92140ab1dcbfcae9b313bee0002b5647cf0af6 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2026 10:58:20 +0000 Subject: [PATCH 1/3] deps: update dependency flagsmith/sdk-spec to v0.6.0 --- .github/workflows/sdk-spec.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/sdk-spec.yml b/.github/workflows/sdk-spec.yml index 6952fea..28056e0 100644 --- a/.github/workflows/sdk-spec.yml +++ b/.github/workflows/sdk-spec.yml @@ -11,7 +11,7 @@ permissions: jobs: sdk-spec: # Keep the ref in `uses:` and `spec-ref` in sync. - uses: Flagsmith/sdk-spec/.github/workflows/run-spec.yml@v0.3.0 + uses: Flagsmith/sdk-spec/.github/workflows/run-spec.yml@v0.6.0 with: - spec-ref: v0.3.0 + spec-ref: v0.6.0 language: python From ef258135be394519c97624577836af25c5b7beda Mon Sep 17 00:00:00 2001 From: "flagsmithsmith[bot]" <346993984+flagsmithsmith[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2026 11:21:57 +0000 Subject: [PATCH 2/3] feat(sdk-spec): Implement the events steps of spec v0.6.0 Wire the spec's new event steps to the SDK's existing public API: a client created with `enable_events` and an events API URL, `get_experiment_flag`, `track_event` and `track_exposure_event`. Co-Authored-By: Claude Opus 5.5 --- .flake8 | 3 + ...66feb7c336bad70ca654fb6b649a141a7e262.json | 1 + sdk-spec/steps.py | 58 +++++++++++++++++-- 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 node_modules/.cache/prettier/.prettier-caches/e2366feb7c336bad70ca654fb6b649a141a7e262.json diff --git a/.flake8 b/.flake8 index fbfd088..0570cc1 100644 --- a/.flake8 +++ b/.flake8 @@ -2,3 +2,6 @@ max-line-length = 120 max-complexity = 10 exclude = .git,__pycache__,.venv +per-file-ignores = + # Step markers must match the spec step text on a single line. + sdk-spec/steps.py: E501 diff --git a/node_modules/.cache/prettier/.prettier-caches/e2366feb7c336bad70ca654fb6b649a141a7e262.json b/node_modules/.cache/prettier/.prettier-caches/e2366feb7c336bad70ca654fb6b649a141a7e262.json new file mode 100644 index 0000000..1e61573 --- /dev/null +++ b/node_modules/.cache/prettier/.prettier-caches/e2366feb7c336bad70ca654fb6b649a141a7e262.json @@ -0,0 +1 @@ +{"f88ac75723c8ecf0770b00acabdf0a3597135eeb":{"files":{"README.md":["49DXCliQp411V6qtWpC+2qQs7Lo=",true],".github/workflows/sdk-spec.yml":["yQOe+0un3Q++ug0tR06fjzxowBk=",true],".pre-commit-config.yaml":["YhkSsd5upk19fuNaspLvHkGKoOk=",true],"CONTRIBUTING.md":["qv90V6oo04GTZV/5M/ELT9YV3G4=",true],"release-please-config.json":["snJKHuhVG5T7LVqeL+YDuE28JqM=",true],"tests/data/environment.json":["7vRRwTOq1+aLf/WqTWNN/qEggRc=",true],"tests/data/flags.json":["uaGrBHUC1bfjCIgq+B99GWFMatU=",true],"tests/data/identities.json":["ein7bbtK4hrExAsCz6Lws+2ej8Q=",true],".github/workflows/add-issues-to-engineering-project.yml":["rr6sMmEO8lj/vm8KJQJBZPe6uxI=",true],"CHANGELOG.md":["hF2IHt+s8T/s7ueiJ6HrSndWIpw=",true],".prettierrc.json":["YmfUdbsgcrTiC7+6SAKLv92f+7A=",true],".github/workflows/publish.yml":["Tx6JhCzhFAAlwOLOMUWSbb/u3mc=",true],".github/workflows/pytest.yml":["bZXSGI08iMrqDWJvNNCTICeVNek=",true],".release-please-manifest.json":["6Pq/PXEZqphze/Mo7CAfLycdK4U=",true]},"modified":1793272820506}} \ No newline at end of file diff --git a/sdk-spec/steps.py b/sdk-spec/steps.py index 5cd373d..2410848 100644 --- a/sdk-spec/steps.py +++ b/sdk-spec/steps.py @@ -6,18 +6,20 @@ import typing -from flagsmith import Flagsmith -from flagsmith.models import Flags +from flagsmith import EventProcessorConfig, Flagsmith +from flagsmith.models import Flag, Flags from flagsmith.types import TraitMapping SpecFlag = dict[str, typing.Any] +EventValue = typing.Union[str, int, float, bool] + + +def as_spec_flag(flag: Flag) -> SpecFlag: + return {"feature": flag.feature_name, "enabled": flag.enabled, "value": flag.value} def as_spec_flags(flags: Flags) -> list[SpecFlag]: - return [ - {"feature": flag.feature_name, "enabled": flag.enabled, "value": flag.value} - for flag in flags.all_flags() - ] + return [as_spec_flag(flag) for flag in flags.all_flags()] # Create the SDK client @@ -25,6 +27,18 @@ def create_client(environment_key: str, api_url: str) -> Flagsmith: return Flagsmith(environment_key=environment_key, api_url=api_url) +# Create the SDK client with events enabled +def create_client_with_events( + environment_key: str, api_url: str, events_api_url: str +) -> Flagsmith: + return Flagsmith( + environment_key=environment_key, + api_url=api_url, + enable_events=True, + event_processor_config=EventProcessorConfig(events_api_url=events_api_url), + ) + + # When the application gets the environment flags def get_environment_flags(flagsmith: Flagsmith) -> list[SpecFlag]: return as_spec_flags(flagsmith.get_environment_flags()) @@ -35,3 +49,35 @@ def get_identity_flags( flagsmith: Flagsmith, identifier: str, traits: TraitMapping ) -> list[SpecFlag]: return as_spec_flags(flagsmith.get_identity_flags(identifier, traits=traits)) + + +# When the application gets the experiment flag "{feature}" for identity "{identifier}" with traits: +def get_experiment_flag( + flagsmith: Flagsmith, feature: str, identifier: str, traits: TraitMapping +) -> list[SpecFlag]: + flag = flagsmith.get_experiment_flag(feature, identifier, traits) + return [as_spec_flag(flag)] if isinstance(flag, Flag) else [] + + +# When the application tracks event "{event}" for identity "{identifier}" with value {value} and metadata: +def track_event( + flagsmith: Flagsmith, + event: str, + identifier: str, + value: EventValue, + metadata: dict[str, typing.Any], +) -> None: + flagsmith.track_event(event, identifier=identifier, value=value, metadata=metadata) + + +# When the application tracks an exposure of feature "{feature}" for identity "{identifier}" with value {value} and metadata: +def track_exposure_event( + flagsmith: Flagsmith, + feature: str, + identifier: str, + value: EventValue, + metadata: dict[str, typing.Any], +) -> None: + flagsmith.track_exposure_event( + feature, identifier=identifier, value=value, metadata=metadata + ) From fd6e931c073a5b8209b6f059ae6a485db98b06e4 Mon Sep 17 00:00:00 2001 From: "flagsmithsmith[bot]" <346993984+flagsmithsmith[bot]@users.noreply.github.com> Date: Thu, 29 Oct 2026 11:22:03 +0000 Subject: [PATCH 3/3] chore: Remove an accidentally committed Prettier cache file Co-Authored-By: Claude Opus 5.5 --- .../e2366feb7c336bad70ca654fb6b649a141a7e262.json | 1 - 1 file changed, 1 deletion(-) delete mode 100644 node_modules/.cache/prettier/.prettier-caches/e2366feb7c336bad70ca654fb6b649a141a7e262.json diff --git a/node_modules/.cache/prettier/.prettier-caches/e2366feb7c336bad70ca654fb6b649a141a7e262.json b/node_modules/.cache/prettier/.prettier-caches/e2366feb7c336bad70ca654fb6b649a141a7e262.json deleted file mode 100644 index 1e61573..0000000 --- a/node_modules/.cache/prettier/.prettier-caches/e2366feb7c336bad70ca654fb6b649a141a7e262.json +++ /dev/null @@ -1 +0,0 @@ -{"f88ac75723c8ecf0770b00acabdf0a3597135eeb":{"files":{"README.md":["49DXCliQp411V6qtWpC+2qQs7Lo=",true],".github/workflows/sdk-spec.yml":["yQOe+0un3Q++ug0tR06fjzxowBk=",true],".pre-commit-config.yaml":["YhkSsd5upk19fuNaspLvHkGKoOk=",true],"CONTRIBUTING.md":["qv90V6oo04GTZV/5M/ELT9YV3G4=",true],"release-please-config.json":["snJKHuhVG5T7LVqeL+YDuE28JqM=",true],"tests/data/environment.json":["7vRRwTOq1+aLf/WqTWNN/qEggRc=",true],"tests/data/flags.json":["uaGrBHUC1bfjCIgq+B99GWFMatU=",true],"tests/data/identities.json":["ein7bbtK4hrExAsCz6Lws+2ej8Q=",true],".github/workflows/add-issues-to-engineering-project.yml":["rr6sMmEO8lj/vm8KJQJBZPe6uxI=",true],"CHANGELOG.md":["hF2IHt+s8T/s7ueiJ6HrSndWIpw=",true],".prettierrc.json":["YmfUdbsgcrTiC7+6SAKLv92f+7A=",true],".github/workflows/publish.yml":["Tx6JhCzhFAAlwOLOMUWSbb/u3mc=",true],".github/workflows/pytest.yml":["bZXSGI08iMrqDWJvNNCTICeVNek=",true],".release-please-manifest.json":["6Pq/PXEZqphze/Mo7CAfLycdK4U=",true]},"modified":1793272820506}} \ No newline at end of file