Skip to main content

philiprehberger-feature-flag

Tests PyPI version Last updated

Simple feature flags with percentage rollout and user targeting.

Installation

pip install philiprehberger-feature-flag

Usage

from philiprehberger_feature_flag import flags

flags.load({"dark_mode": True, "beta_ui": False})

if flags.is_enabled("dark_mode"):
    enable_dark_mode()

Percentage rollout

from philiprehberger_feature_flag import flags

flags.load({
    "new_checkout": {
        "enabled": True,
        "rollout": 25,  # 25% of users
    }
})

if flags.is_enabled("new_checkout", user_id="user-42"):
    show_new_checkout()

User targeting

from philiprehberger_feature_flag import flags

flags.load({
    "admin_panel": {
        "enabled": True,
        "users": ["alice", "bob"],
    }
})

if flags.is_enabled("admin_panel", user_id="alice"):
    show_admin_panel()

Segment targeting

from philiprehberger_feature_flag import flags

flags.define_segment("beta_testers", {"plan": "beta", "region": "us"})
flags.load({
    "new_ui": {
        "enabled": True,
        "segments": ["beta_testers"],
    }
})

if flags.is_enabled("new_ui", plan="beta", region="us"):
    show_new_ui()

Flag dependencies

from philiprehberger_feature_flag import flags

flags.load({"auth": True, "billing": True, "premium": True})
flags.add_dependency("premium", "auth")
flags.add_dependency("premium", "billing")

# premium is only enabled when both auth and billing are enabled
flags.is_enabled("premium")  # True

Scheduled activation

from datetime import datetime, timezone
from philiprehberger_feature_flag import flags

flags.load({"launch": True})
flags.schedule(
    "launch",
    activate_at=datetime(2026, 7, 1, tzinfo=timezone.utc),
    deactivate_at=datetime(2026, 8, 1, tzinfo=timezone.utc),
)

# Flag is only enabled between July 1 and August 1
flags.is_enabled("launch")

Change callbacks

from philiprehberger_feature_flag import flags

def on_flag_change(name, old, new):
    print(f"Flag {name} changed from {old} to {new}")

flags.on_change(on_flag_change)
flags.load({"dark_mode": True})
# prints: Flag dark_mode changed from None to True

flags.remove_listener(on_flag_change)

Snapshot and restore

from philiprehberger_feature_flag import flags

flags.load({"feature_a": True, "feature_b": False})
snap = flags.snapshot()

# Modify state for testing
flags.override("feature_b", True)
assert flags.is_enabled("feature_b")

# Restore original state
flags.restore(snap)
assert not flags.is_enabled("feature_b")

Load from JSON file

from philiprehberger_feature_flag import flags

flags.load("flags.json")

Load from environment variables

from philiprehberger_feature_flag import flags

# Set FF_DARK_MODE=true, FF_BETA=0, etc.
flags.load()  # reads FF_* env vars

Runtime overrides

from philiprehberger_feature_flag import flags

flags.override("beta_ui", True)   # force-enable for testing
flags.reset()                     # clear all overrides

Usage metrics

from philiprehberger_feature_flag import flags

flags.load({"dark_mode": True, "beta": False})

flags.is_enabled("dark_mode")
flags.is_enabled("dark_mode")
flags.is_enabled("beta")

flags.export_metrics()
# {
#     "dark_mode": {"enabled_count": 2, "disabled_count": 0, "total_evaluations": 2},
#     "beta":      {"enabled_count": 0, "disabled_count": 1, "total_evaluations": 1},
# }

flags.reset_metrics()  # zero counters; flag definitions untouched

Flag groups

from philiprehberger_feature_flag import flags

flags.load({
    "ui_dark_mode": True,
    "ui_sidebar": False,
    "api_rate_limit": 100,
})

ui_flags = flags.group("ui_")
# {"ui_dark_mode": True, "ui_sidebar": False}

API

Function / Class Description
FlagStore() Create a new flag store
store.load(config) Load flags from dict, JSON file path, or env vars (None)
store.is_enabled(name, **context) Check if a flag is enabled
store.all() Return all loaded flags as a dict
store.override(name, value) Set a runtime override
store.reset() Clear all runtime overrides
store.on_change(callback) Register a callback fired as callback(flag_name, old_value, new_value) on changes
store.remove_listener(callback) Remove a previously registered change callback
store.group(prefix) Return dict of flags whose name starts with prefix with resolved values
store.define_segment(name, attributes) Define a user segment with required attribute key-value pairs
store.remove_segment(name) Remove a previously defined segment
store.add_dependency(flag, depends_on) Declare that flag requires depends_on to be enabled
store.remove_dependency(flag, depends_on) Remove a dependency from a flag
store.schedule(name, activate_at, deactivate_at) Schedule a flag to activate/deactivate at specific datetimes
store.remove_schedule(name) Remove the schedule for a flag
store.snapshot() Capture full store state (flags, overrides, segments, dependencies, schedules)
store.restore(snap) Restore the store to a previously captured snapshot
store.export_metrics() Return a snapshot of per-flag enabled_count, disabled_count, and total_evaluations counters
store.reset_metrics() Zero all usage counters without touching flag definitions
flags Module-level FlagStore instance

Development

pip install -e .
python -m pytest tests/ -v

Support

If you find this project useful:

⭐ Star the repo

🐛 Report issues

💡 Suggest features

❤️ Sponsor development

🌐 All Open Source Projects

💻 GitHub Profile

🔗 LinkedIn Profile

License

MIT

Release files for philiprehberger-feature-flag 0.4.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for philiprehberger-feature-flag 0.4.0
File Size Uploaded
philiprehberger_feature_flag-0.4.0.tar.gz 11.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for philiprehberger-feature-flag 0.4.0
File Interpreter ABI Platform
philiprehberger_feature_flag-0.4.0-py3-none-any.whl Python 3 none any Details

Total release size: 20.2 kB

Release files / philiprehberger_feature_flag-0.4.0.tar.gz

Download URL philiprehberger_feature_flag-0.4.0.tar.gz
Size 11.6 kB
Tags Source
SHA-256 checksum
How to use checksums
315f62ca200318ce7f85990b0d9064d746d56f76d154c4b72dc3f0d397c48c44
BLAKE2b-256 checksum
How to use checksums
27a634d5112759d370886454ad5941ab6324d5f9d6527265521a4ffbbb2e648a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release files / philiprehberger_feature_flag-0.4.0-py3-none-any.whl

Download URL philiprehberger_feature_flag-0.4.0-py3-none-any.whl
Size 8.6 kB
Tags Python 3
SHA-256 checksum
How to use checksums
4efe92223e6296395c1e9306e75a3e3a1a927f4a375ba60f8e44f24c39abe80e
BLAKE2b-256 checksum
How to use checksums
d89195d6eafdddb14637f3e7c20413ea10f28da536f0dd65f6984411e8827073
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.12.13

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page