feat: is_enabled() accepts a caller-supplied default_value (sdk-specs is-feature-enabled) - #800
Draft
posthog[bot] wants to merge 1 commit into
Draft
feat: is_enabled() accepts a caller-supplied default_value (sdk-specs is-feature-enabled)#800posthog[bot] wants to merge 1 commit into
posthog[bot] wants to merge 1 commit into
Conversation
The sdk-specs `is-feature-enabled` contract requires the boolean flag check to accept a caller-supplied boolean default and return it whenever the flag has no value. `FeatureFlagEvaluations.is_enabled()` hard-coded `False` for that case, so callers could not force a specific fallback. Add `default_value: bool = False`. A flag that has a value still wins, so a disabled flag returns `False` even with `default_value=True`. The default keeps existing calls behaving exactly as before. The deprecated `Client.feature_enabled()` is intentionally left unchanged. Generated-By: PostHog Code Task-Id: e433896a-0f63-478e-bf90-2c6d7c538d37
Contributor
posthog-python Compliance ReportDate: 2026-07-30 08:00:44 UTC ✅ All Tests Passed!111/111 tests passed Capture_V1 Tests✅ 94/94 tests passed View Details
Feature_Flags Tests✅ 17/17 tests passed View Details
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
💡 Motivation and Context
The sdk-specs
is-feature-enabledcontract requires the boolean flag check to accept a caller-supplied boolean default:openspec/specs/is-feature-enabled/spec.md— Requirement: Canonical is-feature-enabled behavior: "The SDK SHALL accept a caller-supplied boolean default (defaultValue; parameter placement per platform idiom) and SHALL return it whenever the flag has no value: flags not loaded yet, a failed flags request, or no flag with that key in the loaded flags. A flag that has a value — includingfalseand variant strings — always wins over the caller-supplied default."defaultValue?: booleanalongsidegroups,personProperties,onlyEvaluateLocally, etc.What was out of compliance:
FeatureFlagEvaluations.is_enabled(key)— the boolean check on the current, non-deprecatedevaluate_flags()path — had no default parameter and hard-codedFalsefor the no-value case. Callers had no way to make a missing flag, an empty evaluation, or a failed/flagsrequest fall back toTrue.Notably, the spec change that added this contract (sdk-specs#14 / #15) assumed the server SDKs already exposed it. posthog-python did not.
How this fixes it:
is_enabled()gainsdefault_value: bool = False, returned when the key is absent from the snapshot. A flag that has a value still wins, so a disabled flag returnsFalseeven withdefault_value=True.The deprecated
Client.feature_enabled()is intentionally not changed — it is already slated for removal in favor ofevaluate_flags(...).is_enabled(key), so the contract is satisfied on the path callers are being steered toward.💚 How did you test it?
posthog/test/test_evaluate_flags.pycovering the three spec scenarios: a missing flag returns the caller default (bothFalseandTrue), a flag that has a value beats the default (disabled/boolean/variant), and a failed/flagsrequest returns the default.uv run pytest posthog/test/test_evaluate_flags.py— 35 passed.ruff format --check .,ruff check .,mypy … | mypy-baseline filter— all clean.make public_api_snapshotregeneratedreferences/public_api_snapshot.txt(the one changed signature line).Behavior change / back-compat risk: none for existing callers.
default_valuedefaults toFalse, which is exactly whatis_enabled()returned before for missing flags. The only observable change is additive: passingdefault_value=Truenow returnsTrueinstead ofFalsefor a flag with no value. Public API surface grows by one optional parameter.📝 Checklist
If releasing new changes
sampo addto generate a changeset file🤖 Agent context
Autonomy: Fully autonomous
Opened by the SDK Spec Compliance Enforcer loop, which audits posthog-python against the PostHog/sdk-specs contracts and files one focused PR per confirmed divergence.
both-scoped specs. Other candidate divergences were found and deliberately not included here to keep the PR focused, or skipped outright: the module-levelget_feature_flag_payloadtracking default was already filed as fix: don't send $feature_flag_called from module-level get_feature_flag_payload #794 and closedwontfix; the explicit-flush-bypasses-flush_intervalgap is already open as fix: flush() delivers pending events without waiting out flush_interval #797;alias/group_identifymissing-identifier validation andSizeLimitedDict's wholesale clear at capacity are behavior-changing and left for human triage.default_valuewas placed onFeatureFlagEvaluations.is_enabled()rather than the deprecatedClient.feature_enabled(), since the spec allows platform-idiomatic parameter placement and modifying a deprecated surface adds churn without helping callers.Created with PostHog Code