From 4b944736c3911d9c60c498cf0cd81647c5381cc1 Mon Sep 17 00:00:00 2001 From: "posthog[bot]" <206114724+posthog[bot]@users.noreply.github.com> Date: Tue, 28 Jul 2026 07:53:19 +0000 Subject: [PATCH] fix: don't send $feature_flag_called from module-level get_feature_flag_payload `Client.get_feature_flag_payload()` defaults `send_feature_flag_events` to `False`, but the module-level `posthog.get_feature_flag_payload()` wrapper still defaulted it to `True` and forwarded the value explicitly, so the client-side default was always overridden. The sdk-specs `get-feature-flag-payload` contract requires payload-only reads not to emit `$feature_flag_called`, and names `send_feature_flag_events=False` in the canonical Python signature. Align the module-level default with the client method. Generated-By: PostHog Code Task-Id: 213ed5a0-6911-4256-a84f-c1fe8eb63de7 --- .../module-level-flag-payload-no-events.md | 5 +++++ posthog/__init__.py | 5 +++-- posthog/test/test_module.py | 19 +++++++++++++++++++ references/public_api_snapshot.txt | 2 +- 4 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 .sampo/changesets/module-level-flag-payload-no-events.md diff --git a/.sampo/changesets/module-level-flag-payload-no-events.md b/.sampo/changesets/module-level-flag-payload-no-events.md new file mode 100644 index 00000000..1dd9e91a --- /dev/null +++ b/.sampo/changesets/module-level-flag-payload-no-events.md @@ -0,0 +1,5 @@ +--- +pypi/posthog: patch +--- + +Stop `posthog.get_feature_flag_payload()` sending `$feature_flag_called` events by default, matching `Client.get_feature_flag_payload()` diff --git a/posthog/__init__.py b/posthog/__init__.py index ff2dc7eb..83e34143 100644 --- a/posthog/__init__.py +++ b/posthog/__init__.py @@ -893,7 +893,7 @@ def get_feature_flag_payload( person_properties: Optional[Dict[str, Any]] = None, group_properties: Optional[Dict[str, Dict[str, Any]]] = None, only_evaluate_locally: bool = False, - send_feature_flag_events: bool = True, + send_feature_flag_events: bool = False, disable_geoip: Optional[bool] = None, device_id: Optional[str] = None, ) -> Optional[object]: @@ -911,7 +911,8 @@ def get_feature_flag_payload( person_properties: Person properties to use for evaluation. group_properties: Group properties keyed by group type. only_evaluate_locally: Whether to evaluate only locally. - send_feature_flag_events: Whether to send a $feature_flag_called event. + send_feature_flag_events: Deprecated. Payload-only reads do not send a + $feature_flag_called event; use get_feature_flag() if you need events. disable_geoip: Whether to disable GeoIP lookup. device_id: Optional device ID override for experience-continuity flags. diff --git a/posthog/test/test_module.py b/posthog/test/test_module.py index ec3031c4..6c55d7d0 100644 --- a/posthog/test/test_module.py +++ b/posthog/test/test_module.py @@ -41,6 +41,25 @@ def test_module_flush_forwards_timeout(self): proxy.assert_called_once_with("flush", timeout_seconds=1.5) + def test_module_get_feature_flag_payload_does_not_send_events_by_default(self): + """Payload-only reads must not emit $feature_flag_called. + + The module-level wrapper forwards `send_feature_flag_events` explicitly, so its + default has to match `Client.get_feature_flag_payload`, which is `False`. + """ + with mock.patch.object(posthog, "_proxy") as proxy: + posthog.get_feature_flag_payload("flag-key", "distinct_id") + + self.assertIs(proxy.call_args.kwargs["send_feature_flag_events"], False) + + def test_module_get_feature_flag_payload_can_opt_into_events(self): + with mock.patch.object(posthog, "_proxy") as proxy: + posthog.get_feature_flag_payload( + "flag-key", "distinct_id", send_feature_flag_events=True + ) + + self.assertIs(proxy.call_args.kwargs["send_feature_flag_events"], True) + class TestModuleLevelSetup(unittest.TestCase): def setUp(self): diff --git a/references/public_api_snapshot.txt b/references/public_api_snapshot.txt index b3276684..4dfcf385 100644 --- a/references/public_api_snapshot.txt +++ b/references/public_api_snapshot.txt @@ -1103,7 +1103,7 @@ function posthog.flush(timeout_seconds: Optional[float] = 10) -> None function posthog.get_all_flags(distinct_id: ID_TYPES, groups: Optional[Mapping[str, Union[str, int]]] = None, person_properties: Optional[Dict[str, Any]] = None, group_properties: Optional[Dict[str, Dict[str, Any]]] = None, only_evaluate_locally: bool = False, disable_geoip: Optional[bool] = None, device_id: Optional[str] = None, flag_keys_to_evaluate: Optional[list[str]] = None) -> Optional[dict[str, FlagValue]] function posthog.get_all_flags_and_payloads(distinct_id: ID_TYPES, groups: Optional[Mapping[str, Union[str, int]]] = None, person_properties: Optional[Dict[str, Any]] = None, group_properties: Optional[Dict[str, Dict[str, Any]]] = None, only_evaluate_locally: bool = False, disable_geoip: Optional[bool] = None, device_id: Optional[str] = None, flag_keys_to_evaluate: Optional[list[str]] = None) -> FlagsAndPayloads function posthog.get_feature_flag(key: str, distinct_id: ID_TYPES, groups: Optional[Mapping[str, Union[str, int]]] = None, person_properties: Optional[Dict[str, Any]] = None, group_properties: Optional[Dict[str, Dict[str, Any]]] = None, only_evaluate_locally: bool = False, send_feature_flag_events: bool = True, disable_geoip: Optional[bool] = None, device_id: Optional[str] = None) -> Optional[FlagValue] -function posthog.get_feature_flag_payload(key: str, distinct_id: ID_TYPES, match_value: Optional[FlagValue] = None, groups: Optional[Mapping[str, Union[str, int]]] = None, person_properties: Optional[Dict[str, Any]] = None, group_properties: Optional[Dict[str, Dict[str, Any]]] = None, only_evaluate_locally: bool = False, send_feature_flag_events: bool = True, disable_geoip: Optional[bool] = None, device_id: Optional[str] = None) -> Optional[object] +function posthog.get_feature_flag_payload(key: str, distinct_id: ID_TYPES, match_value: Optional[FlagValue] = None, groups: Optional[Mapping[str, Union[str, int]]] = None, person_properties: Optional[Dict[str, Any]] = None, group_properties: Optional[Dict[str, Dict[str, Any]]] = None, only_evaluate_locally: bool = False, send_feature_flag_events: bool = False, disable_geoip: Optional[bool] = None, device_id: Optional[str] = None) -> Optional[object] function posthog.get_feature_flag_result(key: str, distinct_id: ID_TYPES, groups: Optional[Mapping[str, Union[str, int]]] = None, person_properties: Optional[Dict[str, Any]] = None, group_properties: Optional[Dict[str, Dict[str, Any]]] = None, only_evaluate_locally: bool = False, send_feature_flag_events: bool = True, disable_geoip: Optional[bool] = None, device_id: Optional[str] = None) -> Optional[FeatureFlagResult] function posthog.get_remote_config_payload(key: str) function posthog.get_tags() -> Dict[str, Any]