Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 48 additions & 0 deletions posthog/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -617,6 +617,7 @@ def get_all_flags(
disable_geoip=None, # type: Optional[bool]
device_id=None, # type: Optional[str]
flag_keys_to_evaluate=None, # type: Optional[list[str]]
send_feature_flag_events=False, # type: bool
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

iirc there was rfc to kill this flag due to its side effect
https://github.com/PostHog/requests-for-comments-internal/pull/1020 i think
so before adding this flag to more sdks, should we double check if we actually want to do this?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

so my interpretation of that SDK is to remove it from methods like e.g. capture, since we really don't need to send flag data for non-flag calls. Me adding to to get_all_flags here was to make it so that people could still use get_all_flags and send the flag values as events. what I noticed this week when talking to a customer was that they basically call get_all_flags once as part of the initial page load, save those values into their own app memory, and then use them throughout. This would make it so that they don't have to refactor their code to use my proposed new get_feature_flags() method, and could instead just add a field to their existing code.

but I read that RFC and it's a much saner approach IMO, so maybe rather than me adding this new method that follows the existing patterns, I should do the heavier lift and just implement the RFC. The reason I'm hesitant is because it turns this into a heavier lift for the customer – rather than them just bumping the SDK and adding this new method, they have to bump to a bigger version and deprecate their other methods everywhere. Maybe in LLM world, that's just as easy, but I wanted to be cognizant of that.

) -> Optional[dict[str, FeatureFlag]]:
"""
Get all flags for a given user.
Expand All @@ -629,6 +630,8 @@ def get_all_flags(
only_evaluate_locally: Whether to evaluate only locally
disable_geoip: Whether to disable GeoIP lookup
flag_keys_to_evaluate: Optional list of flag keys to evaluate (evaluates all if None)
send_feature_flag_events: If True, emit a `$feature_flag_called` event for each
resolved flag. Defaults to False to preserve historical behavior.

Details:
Flags are key-value pairs where the key is the flag key and the value is the flag variant, or True, or False.
Expand All @@ -652,6 +655,7 @@ def get_all_flags(
disable_geoip=disable_geoip,
device_id=device_id,
flag_keys_to_evaluate=flag_keys_to_evaluate,
send_feature_flag_events=send_feature_flag_events,
)


Expand Down Expand Up @@ -756,6 +760,7 @@ def get_all_flags_and_payloads(
disable_geoip=None, # type: Optional[bool]
device_id=None, # type: Optional[str]
flag_keys_to_evaluate=None, # type: Optional[list[str]]
send_feature_flag_events=False, # type: bool
) -> FlagsAndPayloads:
return _proxy(
"get_all_flags_and_payloads",
Expand All @@ -767,6 +772,49 @@ def get_all_flags_and_payloads(
disable_geoip=disable_geoip,
device_id=device_id,
flag_keys_to_evaluate=flag_keys_to_evaluate,
send_feature_flag_events=send_feature_flag_events,
)


def get_feature_flags(
keys, # type: list[str]
distinct_id,
groups=None, # type: Optional[dict]
person_properties=None, # type: Optional[dict]
group_properties=None, # type: Optional[dict]
only_evaluate_locally=False,
send_feature_flag_events=True,
disable_geoip=None, # type: Optional[bool]
device_id=None, # type: Optional[str]
):
# type: (...) -> dict[str, Optional[FeatureFlagResult]]
"""
Evaluate a subset of feature flags in one bulk pass and return a FeatureFlagResult per requested key.

Evaluates each key locally first (when local evaluation is enabled) and then makes at most one remote
`/flags` request for any keys that could not be resolved locally. Emits `$feature_flag_called` events
per resolved flag (deduped across calls via the same cache as `get_feature_flag`).

Example:
```python
from posthog import get_feature_flags
results = get_feature_flags(['beta-feature', 'new-dashboard'], 'distinct_id')
if results['beta-feature'] and results['beta-feature'].enabled:
# Use the variant and payload
print(results['beta-feature'].variant)
```
"""
return _proxy(
"get_feature_flags",
keys=keys,
distinct_id=distinct_id,
groups=groups or {},
person_properties=person_properties or {},
group_properties=group_properties or {},
only_evaluate_locally=only_evaluate_locally,
send_feature_flag_events=send_feature_flag_events,
disable_geoip=disable_geoip,
device_id=device_id,
)


Expand Down
Loading
Loading