Skip to main content

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
)
OptionTypeDefaultDescription
api_keystrYour environment API key (required)
api_urlstrhttps://api.toggletown.comAPI endpoint URL
polling_intervalint30Seconds between flag refreshes
on_errorCallableError callback for background polling
on_staleCallableCalled once when flags become stale (receives datetime, age_seconds)
max_stale_agefloat300Max 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