Skip to content

Python SDK for working with Togglr - feature flag management system.

togglr-project/togglr-sdk-python

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

15 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Togglr Python SDK

Python SDK for working with Togglr - feature flag management system.

Installation

pip install togglr-sdk

Quick Start

import togglr
from togglr import RequestContext

# Create client with default configuration
client = togglr.new_client(
    api_key="your-api-key-here",
    base_url="http://localhost:8090",
    timeout=1.0,
    cache={"enabled": True, "max_size": 1000, "ttl_seconds": 10}
)

# Use context manager for proper resource cleanup
with client:
    # Create request context
    context = RequestContext.new() \
        .with_user_id("user123") \
        .with_country("US") \
        .with_device_type("mobile") \
        .with_os("iOS") \
        .with_os_version("15.0") \
        .with_browser("Safari") \
        .with_language("en-US")
    
    # Evaluate feature flag
    try:
        value, enabled, found = client.evaluate("new_ui", context)
        if found:
            print(f"Feature enabled: {enabled}, value: {value}")
        else:
            print("Feature not found")
    except togglr.TogglrError as e:
        print(f"Error evaluating feature: {e}")
    
    # Simple enabled check
    try:
        is_enabled = client.is_enabled("new_ui", context)
        print(f"Feature is enabled: {is_enabled}")
    except togglr.FeatureNotFoundError:
        print("Feature not found")
    except togglr.TogglrError as e:
        print(f"Error checking feature: {e}")
    
    # With default value
    is_enabled = client.is_enabled_or_default("new_ui", context, default=False)
    print(f"Feature enabled (with default): {is_enabled}")

Configuration

Creating a client

# With default settings
client = togglr.new_client("api-key")

# With custom configuration
client = togglr.new_client(
    api_key="api-key",
    base_url="https://api.togglr.com",
    timeout=2.0,
    retries=3,
    cache={"enabled": True, "max_size": 1000, "ttl_seconds": 10},
    insecure=True  # Skip SSL verification for self-signed certificates
)

TLS/SSL Configuration

The SDK supports comprehensive TLS/SSL configuration for secure connections:

# Using with_ methods
config = ClientConfig.default("api-key") \
    .with_base_url("https://api.togglr.com") \
    .with_ssl_ca_cert("/path/to/ca-certificate.pem") \
    .with_client_cert("/path/to/client-cert.pem", "/path/to/client-key.pem") \
    .with_tls_server_name("api.togglr.com") \
    .with_ssl_hostname_verification(True)

client = Client(config)

# Using new_client with TLS parameters
client = togglr.new_client(
    api_key="api-key",
    base_url="https://api.togglr.com",
    ssl_ca_cert="/path/to/ca-certificate.pem",
    cert_file="/path/to/client-cert.pem",
    key_file="/path/to/client-key.pem",
    ca_cert_data="-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----",
    tls_server_name="api.togglr.com",
    assert_hostname=True
)

# Using CA certificate data instead of file
config = ClientConfig.default("api-key") \
    .with_ca_cert_data("-----BEGIN CERTIFICATE-----\n...\n-----END CERTIFICATE-----")

# Insecure mode (only for testing)
config = ClientConfig.default("api-key") \
    .with_insecure()  # Disables SSL certificate verification

Available TLS Options

  • ssl_ca_cert: Path to CA certificate file
  • cert_file: Path to client certificate file
  • key_file: Path to client private key file
  • ca_cert_data: CA certificate data (PEM or DER format)
  • assert_hostname: Enable/disable SSL hostname verification
  • tls_server_name: TLS Server Name Indication (SNI)
  • insecure: Skip SSL verification (for testing only)

Advanced configuration

from togglr import Client, ClientConfig, RequestContext

# Create custom configuration
config = ClientConfig.default("api-key") \
    .with_base_url("https://api.togglr.com") \
    .with_timeout(2.0) \
    .with_retries(3) \
    .with_cache(enabled=True, max_size=1000, ttl_seconds=10) \
    .with_backoff(base_delay=0.2, max_delay=5.0, factor=1.5)

client = Client(config)

Usage

Creating request context

context = RequestContext.new() \
    .with_user_id("user123") \
    .with_user_email("user@example.com") \
    .with_country("US") \
    .with_device_type("mobile") \
    .with_os("iOS") \
    .with_os_version("15.0") \
    .with_browser("Safari") \
    .with_language("en-US") \
    .with_age(25) \
    .with_gender("female") \
    .set("custom_attribute", "custom_value")

Evaluating feature flags

# Full evaluation
value, enabled, found = client.evaluate("feature_key", context)

# Simple enabled check
is_enabled = client.is_enabled("feature_key", context)

# With default value
is_enabled = client.is_enabled_or_default("feature_key", context, default=False)

Health check

if client.health_check():
    print("API is healthy")
else:
    print("API is not healthy")

Error Reporting and Auto-Disable

The SDK supports reporting feature execution errors for auto-disable functionality:

# Report an error for a feature
client.report_error(
    feature_key="feature_key",
    error_type="timeout",
    error_message="Service did not respond in 5s",
    context={
        "service": "payment-gateway",
        "timeout_ms": 5000,
        "retry_count": 3
    }
)

print("Error reported successfully - queued for processing")

Feature Health Monitoring

Check the health status of features:

# Get feature health status
health = client.get_feature_health("feature_key")
print(f"Feature Health:")
print(f"  Enabled: {health.enabled}")
print(f"  Auto Disabled: {health.auto_disabled}")
if health.error_rate is not None:
    print(f"  Error Rate: {health.error_rate * 100:.2f}%")
if health.last_error_at is not None:
    print(f"  Last Error: {health.last_error_at}")

# Simple health check
is_healthy = client.is_feature_healthy("feature_key")
print(f"Feature is healthy: {is_healthy}")

Caching

The SDK supports optional caching of evaluation results:

client = togglr.new_client(
    api_key="api-key",
    cache={"enabled": True, "max_size": 1000, "ttl_seconds": 10}
)

Retries

The SDK automatically retries requests on temporary errors:

config = ClientConfig.default("api-key") \
    .with_retries(3) \
    .with_backoff(base_delay=0.1, max_delay=2.0, factor=2.0)

client = Client(config)

Logging and Metrics

def custom_logger(message: str, **kwargs):
    print(f"[LOG] {message} {kwargs}")

class CustomMetrics:
    def inc_evaluate_request(self):
        # Increment request counter
        pass
    
    def inc_cache_hit(self):
        # Increment cache hit counter
        pass
    
    def inc_evaluate_error(self, error_code: str):
        # Increment error counter
        pass
    
    def observe_evaluate_latency(self, latency: float):
        # Observe evaluation latency
        pass

config = ClientConfig.default("api-key") \
    .with_logger(custom_logger) \
    .with_metrics(CustomMetrics())

client = Client(config)

Error Handling

try:
    value, enabled, found = client.evaluate("feature_key", context)
except togglr.UnauthorizedError:
    # Authorization error
    pass
except togglr.BadRequestError:
    # Bad request
    pass
except togglr.NotFoundError:
    # Resource not found
    pass
except togglr.InternalServerError:
    # Internal server error
    pass
except togglr.TooManyRequestsError:
    # Rate limit exceeded
    pass
except togglr.FeatureNotFoundError:
    # Feature flag not found
    pass
except togglr.TogglrError as e:
    # Other errors
    print(f"Error: {e}")

Error Report Types

# Create different types of error reports
client.report_error(
    feature_key="feature_key",
    error_type="timeout",
    error_message="Service timeout",
    context={"service": "payment-gateway", "timeout_ms": 5000}
)

client.report_error(
    feature_key="feature_key",
    error_type="validation",
    error_message="Invalid data",
    context={"field": "email", "error_code": "INVALID_FORMAT"}
)

client.report_error(
    feature_key="feature_key",
    error_type="service_unavailable",
    error_message="Service down",
    context={"service": "database", "status_code": 503}
)

Feature Health Types

# FeatureHealth provides detailed health information
from togglr import FeatureHealth

# Access health properties
health = client.get_feature_health("feature_key")
print(f"Feature Key: {health.feature_key}")
print(f"Environment Key: {health.environment_key}")
print(f"Enabled: {health.enabled}")
print(f"Auto Disabled: {health.auto_disabled}")
print(f"Error Rate: {health.error_rate}")  # Optional
print(f"Threshold: {health.threshold}")    # Optional
print(f"Last Error At: {health.last_error_at}")  # Optional

Client Generation

To update the generated client from OpenAPI specification:

make generate

Building and Testing

# Install development dependencies
make dev-install

# Build
make build

# Testing
make test

# Linting
make lint

# Format code
make format

# Clean
make clean

Examples

Complete usage examples are located in the examples/ directory:

  • simple_example.py - Simple usage example
  • advanced_example.py - Advanced example with custom configuration
  • tls_example.py - TLS/SSL configuration examples

Requirements

  • Python 3.8+
  • httpx
  • pydantic
  • cachetools (optional)

About

Python SDK for working with Togglr - feature flag management system.

Topics

Resources

Stars

Watchers

Forks

Packages

No packages published