Python SDK
Official Python SDK for ToggleTown feature flags.
Package: toggletown
Installation
pip install git+https://github.com/toggletown/sdk-python.git
Quick Start
from toggletown import ToggleTownClient
# Initialize the client
client = ToggleTownClient("tt_live_your_api_key")
client.initialize()
# Evaluate a boolean flag
enabled = client.get_boolean_flag("new-feature", False, {
"user_id": "user-123",
"plan": "pro",
})
if enabled:
print("New feature is enabled!")
# Clean up when done
client.close()
Context Manager
Use the context manager for automatic cleanup:
from toggletown import ToggleTownClient
with ToggleTownClient("tt_live_xxx") as client:
enabled = client.get_boolean_flag("feature", False, {"user_id": "123"})
Configuration
client = ToggleTownClient(
api_key="tt_live_xxx",
api_url="https://api.toggletown.com", # Optional
polling_interval=30, # Seconds between flag refreshes
on_error=lambda e: print(f"Error: {e}"), # Error callback
)
| Option | Type | Default | Description |
|---|---|---|---|
api_key | str | — | Your environment API key (required) |
api_url | str | https://api.toggletown.com | API endpoint URL |
polling_interval | int | 30 | Seconds between flag refreshes |
on_error | Callable | — | Error callback for background polling |
on_stale | Callable | — | Called once when flags become stale (receives datetime, age_seconds) |
max_stale_age | float | 300 | Max age in seconds before flags are considered stale (default: 5 min) |
Flag Types
Boolean Flags
enabled = client.get_boolean_flag("feature-enabled", False, context)
String Flags
variant = client.get_string_flag("experiment-variant", "control", context)
Number Flags
max_items = client.get_number_flag("max-items", 10, context)
JSON Flags
config = client.get_json_flag("feature-config", {"enabled": False}, context)
User Context
Pass user attributes for targeting rules:
context = {
"user_id": "user-123", # Required for percentage rollouts
"email": "[email protected]",
"plan": "enterprise",
"country": "US",
"beta_user": True,
}
enabled = client.get_boolean_flag("premium-feature", False, context)
Flask Integration
from flask import Flask, g, request
from toggletown import ToggleTownClient
app = Flask(__name__)
client = ToggleTownClient("tt_live_xxx")
client.initialize()
@app.before_request
def setup_flags():
g.flag_context = {
"user_id": request.headers.get("X-User-ID"),
"plan": request.headers.get("X-User-Plan", "free"),
}
@app.route("/api/feature")
def feature():
enabled = client.get_boolean_flag("new-feature", False, g.flag_context)
return {"enabled": enabled}
@app.teardown_appcontext
def cleanup(exception):
pass # Client cleanup handled at app shutdown
# Cleanup on shutdown
import atexit
atexit.register(client.close)
Django Integration
# settings.py
from toggletown import ToggleTownClient
FEATURE_FLAGS = ToggleTownClient("tt_live_xxx")
FEATURE_FLAGS.initialize()
# views.py
from django.conf import settings
def my_view(request):
context = {
"user_id": str(request.user.id) if request.user.is_authenticated else None,
"plan": getattr(request.user, "plan", "free"),
}
enabled = settings.FEATURE_FLAGS.get_boolean_flag("feature", False, context)
return JsonResponse({"enabled": enabled})
Staleness Detection
The client tracks when flags were last successfully fetched. If the API becomes unreachable, you can detect stale flags:
def handle_stale(last_updated_at, age_seconds):
print(f"Flags are stale! Last updated: {last_updated_at}, age: {age_seconds}s")
client = ToggleTownClient(
"tt_live_xxx",
max_stale_age=300, # 5 minutes (default)
on_stale=handle_stale,
)
# Check staleness programmatically
client.is_stale() # True if age > max_stale_age
client.get_last_updated_at() # datetime of last successful fetch (or None)
client.get_status() # {"status": "fresh"|"stale", "last_updated_at": ..., "age_seconds": ...}
The on_stale callback fires once when flags become stale and resets on the next successful fetch.
Debugging
# Get all flag configurations
all_flags = client.get_all_flags()
for key, config in all_flags.items():
print(f"Flag: {key}, Enabled: {config.get('enabled')}, Rollout: {config.get('rolloutPercentage')}%")
# Check if client is initialized
client.is_initialized() # True once flags have been fetched
Thread Safety
The client is thread-safe. Flag data is protected by locks and can be safely accessed from multiple threads.
Error Handling
def handle_error(error: Exception):
print(f"Flag fetch failed: {error}")
# Optionally send to error tracking
client = ToggleTownClient(
"tt_live_xxx",
on_error=handle_error,
)
try:
client.initialize()
except Exception as e:
print(f"Initialization failed: {e}")
# Use defaults if initialization fails