# Togglr Python SDK
Python SDK for working with Togglr - feature flag management system.
## Installation
```bash
pip install togglr-sdk
```
## Quick Start
```python
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
```python
# 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:
```python
# 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
```python
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
```python
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
```python
# 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
```python
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:
```python
# 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:
```python
# 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:
```python
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:
```python
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
```python
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
```python
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
```python
# 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
```python
# 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:
```bash
make generate
```
## Building and Testing
```bash
# 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)
Raw data
{
"_id": null,
"home_page": "https://github.com/togglr-project/togglr-sdk-python",
"name": "togglr-sdk",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": "Roman Chudov <roman.chudov@gmail.com>",
"keywords": "sdk, togglr, feature-flag",
"author": "Roman Chudov",
"author_email": "Roman Chudov <roman.chudov@gmail.com>",
"download_url": "https://files.pythonhosted.org/packages/f4/35/999666b4a452579b877e3f0f92b5aa40d2a39a161f8cb3e93333023696fa/togglr_sdk-1.1.0.tar.gz",
"platform": null,
"description": "# Togglr Python SDK\n\nPython SDK for working with Togglr - feature flag management system.\n\n## Installation\n\n```bash\npip install togglr-sdk\n```\n\n## Quick Start\n\n```python\nimport togglr\nfrom togglr import RequestContext\n\n# Create client with default configuration\nclient = togglr.new_client(\n api_key=\"your-api-key-here\",\n base_url=\"http://localhost:8090\",\n timeout=1.0,\n cache={\"enabled\": True, \"max_size\": 1000, \"ttl_seconds\": 10}\n)\n\n# Use context manager for proper resource cleanup\nwith client:\n # Create request context\n context = RequestContext.new() \\\n .with_user_id(\"user123\") \\\n .with_country(\"US\") \\\n .with_device_type(\"mobile\") \\\n .with_os(\"iOS\") \\\n .with_os_version(\"15.0\") \\\n .with_browser(\"Safari\") \\\n .with_language(\"en-US\")\n \n # Evaluate feature flag\n try:\n value, enabled, found = client.evaluate(\"new_ui\", context)\n if found:\n print(f\"Feature enabled: {enabled}, value: {value}\")\n else:\n print(\"Feature not found\")\n except togglr.TogglrError as e:\n print(f\"Error evaluating feature: {e}\")\n \n # Simple enabled check\n try:\n is_enabled = client.is_enabled(\"new_ui\", context)\n print(f\"Feature is enabled: {is_enabled}\")\n except togglr.FeatureNotFoundError:\n print(\"Feature not found\")\n except togglr.TogglrError as e:\n print(f\"Error checking feature: {e}\")\n \n # With default value\n is_enabled = client.is_enabled_or_default(\"new_ui\", context, default=False)\n print(f\"Feature enabled (with default): {is_enabled}\")\n```\n\n## Configuration\n\n### Creating a client\n\n```python\n# With default settings\nclient = togglr.new_client(\"api-key\")\n\n# With custom configuration\nclient = togglr.new_client(\n api_key=\"api-key\",\n base_url=\"https://api.togglr.com\",\n timeout=2.0,\n retries=3,\n cache={\"enabled\": True, \"max_size\": 1000, \"ttl_seconds\": 10},\n insecure=True # Skip SSL verification for self-signed certificates\n)\n```\n\n### TLS/SSL Configuration\n\nThe SDK supports comprehensive TLS/SSL configuration for secure connections:\n\n```python\n# Using with_ methods\nconfig = ClientConfig.default(\"api-key\") \\\n .with_base_url(\"https://api.togglr.com\") \\\n .with_ssl_ca_cert(\"/path/to/ca-certificate.pem\") \\\n .with_client_cert(\"/path/to/client-cert.pem\", \"/path/to/client-key.pem\") \\\n .with_tls_server_name(\"api.togglr.com\") \\\n .with_ssl_hostname_verification(True)\n\nclient = Client(config)\n\n# Using new_client with TLS parameters\nclient = togglr.new_client(\n api_key=\"api-key\",\n base_url=\"https://api.togglr.com\",\n ssl_ca_cert=\"/path/to/ca-certificate.pem\",\n cert_file=\"/path/to/client-cert.pem\",\n key_file=\"/path/to/client-key.pem\",\n ca_cert_data=\"-----BEGIN CERTIFICATE-----\\n...\\n-----END CERTIFICATE-----\",\n tls_server_name=\"api.togglr.com\",\n assert_hostname=True\n)\n\n# Using CA certificate data instead of file\nconfig = ClientConfig.default(\"api-key\") \\\n .with_ca_cert_data(\"-----BEGIN CERTIFICATE-----\\n...\\n-----END CERTIFICATE-----\")\n\n# Insecure mode (only for testing)\nconfig = ClientConfig.default(\"api-key\") \\\n .with_insecure() # Disables SSL certificate verification\n```\n\n#### Available TLS Options\n\n- `ssl_ca_cert`: Path to CA certificate file\n- `cert_file`: Path to client certificate file \n- `key_file`: Path to client private key file\n- `ca_cert_data`: CA certificate data (PEM or DER format)\n- `assert_hostname`: Enable/disable SSL hostname verification\n- `tls_server_name`: TLS Server Name Indication (SNI)\n- `insecure`: Skip SSL verification (for testing only)\n\n### Advanced configuration\n\n```python\nfrom togglr import Client, ClientConfig, RequestContext\n\n# Create custom configuration\nconfig = ClientConfig.default(\"api-key\") \\\n .with_base_url(\"https://api.togglr.com\") \\\n .with_timeout(2.0) \\\n .with_retries(3) \\\n .with_cache(enabled=True, max_size=1000, ttl_seconds=10) \\\n .with_backoff(base_delay=0.2, max_delay=5.0, factor=1.5)\n\nclient = Client(config)\n```\n\n## Usage\n\n### Creating request context\n\n```python\ncontext = RequestContext.new() \\\n .with_user_id(\"user123\") \\\n .with_user_email(\"user@example.com\") \\\n .with_country(\"US\") \\\n .with_device_type(\"mobile\") \\\n .with_os(\"iOS\") \\\n .with_os_version(\"15.0\") \\\n .with_browser(\"Safari\") \\\n .with_language(\"en-US\") \\\n .with_age(25) \\\n .with_gender(\"female\") \\\n .set(\"custom_attribute\", \"custom_value\")\n```\n\n### Evaluating feature flags\n\n```python\n# Full evaluation\nvalue, enabled, found = client.evaluate(\"feature_key\", context)\n\n# Simple enabled check\nis_enabled = client.is_enabled(\"feature_key\", context)\n\n# With default value\nis_enabled = client.is_enabled_or_default(\"feature_key\", context, default=False)\n```\n\n### Health check\n\n```python\nif client.health_check():\n print(\"API is healthy\")\nelse:\n print(\"API is not healthy\")\n```\n\n### Error Reporting and Auto-Disable\n\nThe SDK supports reporting feature execution errors for auto-disable functionality:\n\n```python\n# Report an error for a feature\nclient.report_error(\n feature_key=\"feature_key\",\n error_type=\"timeout\",\n error_message=\"Service did not respond in 5s\",\n context={\n \"service\": \"payment-gateway\",\n \"timeout_ms\": 5000,\n \"retry_count\": 3\n }\n)\n\nprint(\"Error reported successfully - queued for processing\")\n```\n\n### Feature Health Monitoring\n\nCheck the health status of features:\n\n```python\n# Get feature health status\nhealth = client.get_feature_health(\"feature_key\")\nprint(f\"Feature Health:\")\nprint(f\" Enabled: {health.enabled}\")\nprint(f\" Auto Disabled: {health.auto_disabled}\")\nif health.error_rate is not None:\n print(f\" Error Rate: {health.error_rate * 100:.2f}%\")\nif health.last_error_at is not None:\n print(f\" Last Error: {health.last_error_at}\")\n\n# Simple health check\nis_healthy = client.is_feature_healthy(\"feature_key\")\nprint(f\"Feature is healthy: {is_healthy}\")\n```\n\n## Caching\n\nThe SDK supports optional caching of evaluation results:\n\n```python\nclient = togglr.new_client(\n api_key=\"api-key\",\n cache={\"enabled\": True, \"max_size\": 1000, \"ttl_seconds\": 10}\n)\n```\n\n## Retries\n\nThe SDK automatically retries requests on temporary errors:\n\n```python\nconfig = ClientConfig.default(\"api-key\") \\\n .with_retries(3) \\\n .with_backoff(base_delay=0.1, max_delay=2.0, factor=2.0)\n\nclient = Client(config)\n```\n\n## Logging and Metrics\n\n```python\ndef custom_logger(message: str, **kwargs):\n print(f\"[LOG] {message} {kwargs}\")\n\nclass CustomMetrics:\n def inc_evaluate_request(self):\n # Increment request counter\n pass\n \n def inc_cache_hit(self):\n # Increment cache hit counter\n pass\n \n def inc_evaluate_error(self, error_code: str):\n # Increment error counter\n pass\n \n def observe_evaluate_latency(self, latency: float):\n # Observe evaluation latency\n pass\n\nconfig = ClientConfig.default(\"api-key\") \\\n .with_logger(custom_logger) \\\n .with_metrics(CustomMetrics())\n\nclient = Client(config)\n```\n\n## Error Handling\n\n```python\ntry:\n value, enabled, found = client.evaluate(\"feature_key\", context)\nexcept togglr.UnauthorizedError:\n # Authorization error\n pass\nexcept togglr.BadRequestError:\n # Bad request\n pass\nexcept togglr.NotFoundError:\n # Resource not found\n pass\nexcept togglr.InternalServerError:\n # Internal server error\n pass\nexcept togglr.TooManyRequestsError:\n # Rate limit exceeded\n pass\nexcept togglr.FeatureNotFoundError:\n # Feature flag not found\n pass\nexcept togglr.TogglrError as e:\n # Other errors\n print(f\"Error: {e}\")\n```\n\n### Error Report Types\n\n```python\n# Create different types of error reports\nclient.report_error(\n feature_key=\"feature_key\",\n error_type=\"timeout\",\n error_message=\"Service timeout\",\n context={\"service\": \"payment-gateway\", \"timeout_ms\": 5000}\n)\n\nclient.report_error(\n feature_key=\"feature_key\",\n error_type=\"validation\",\n error_message=\"Invalid data\",\n context={\"field\": \"email\", \"error_code\": \"INVALID_FORMAT\"}\n)\n\nclient.report_error(\n feature_key=\"feature_key\",\n error_type=\"service_unavailable\",\n error_message=\"Service down\",\n context={\"service\": \"database\", \"status_code\": 503}\n)\n```\n\n### Feature Health Types\n\n```python\n# FeatureHealth provides detailed health information\nfrom togglr import FeatureHealth\n\n# Access health properties\nhealth = client.get_feature_health(\"feature_key\")\nprint(f\"Feature Key: {health.feature_key}\")\nprint(f\"Environment Key: {health.environment_key}\")\nprint(f\"Enabled: {health.enabled}\")\nprint(f\"Auto Disabled: {health.auto_disabled}\")\nprint(f\"Error Rate: {health.error_rate}\") # Optional\nprint(f\"Threshold: {health.threshold}\") # Optional\nprint(f\"Last Error At: {health.last_error_at}\") # Optional\n```\n\n## Client Generation\n\nTo update the generated client from OpenAPI specification:\n\n```bash\nmake generate\n```\n\n## Building and Testing\n\n```bash\n# Install development dependencies\nmake dev-install\n\n# Build\nmake build\n\n# Testing\nmake test\n\n# Linting\nmake lint\n\n# Format code\nmake format\n\n# Clean\nmake clean\n```\n\n## Examples\n\nComplete usage examples are located in the `examples/` directory:\n\n- `simple_example.py` - Simple usage example\n- `advanced_example.py` - Advanced example with custom configuration\n- `tls_example.py` - TLS/SSL configuration examples\n\n## Requirements\n\n- Python 3.8+\n- httpx\n- pydantic\n- cachetools (optional)\n",
"bugtrack_url": null,
"license": null,
"summary": "SDK for Togglr feature flags management system",
"version": "1.1.0",
"project_urls": {
"Documentation": "https://github.com/togglr-project/togglr-sdk-python",
"Homepage": "https://github.com/togglr-project/togglr-sdk-python",
"Repository": "https://github.com/togglr-project/togglr-sdk-python.git"
},
"split_keywords": [
"sdk",
" togglr",
" feature-flag"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "81d5086d5e0b9bf27d762096e91a8bf57505e3cc8547cdc896b47799b3e972ca",
"md5": "2e30110c25d142999f9de86e5983bd07",
"sha256": "267a43eb436a0436115c195117dadbe04e8b6d610de5f5a198c97cdd300985d5"
},
"downloads": -1,
"filename": "togglr_sdk-1.1.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "2e30110c25d142999f9de86e5983bd07",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 19385,
"upload_time": "2025-10-18T06:32:16",
"upload_time_iso_8601": "2025-10-18T06:32:16.091373Z",
"url": "https://files.pythonhosted.org/packages/81/d5/086d5e0b9bf27d762096e91a8bf57505e3cc8547cdc896b47799b3e972ca/togglr_sdk-1.1.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "f435999666b4a452579b877e3f0f92b5aa40d2a39a161f8cb3e93333023696fa",
"md5": "18574e77080e7c2843b0c33744578530",
"sha256": "a968780e4ee14a817f57c07009edb008aea95139270bbe2ececf2704bea1be07"
},
"downloads": -1,
"filename": "togglr_sdk-1.1.0.tar.gz",
"has_sig": false,
"md5_digest": "18574e77080e7c2843b0c33744578530",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 19195,
"upload_time": "2025-10-18T06:32:17",
"upload_time_iso_8601": "2025-10-18T06:32:17.658349Z",
"url": "https://files.pythonhosted.org/packages/f4/35/999666b4a452579b877e3f0f92b5aa40d2a39a161f8cb3e93333023696fa/togglr_sdk-1.1.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-10-18 06:32:17",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "togglr-project",
"github_project": "togglr-sdk-python",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "httpx",
"specs": [
[
">=",
"0.24.0"
]
]
},
{
"name": "pydantic",
"specs": [
[
">=",
"2.0.0"
]
]
},
{
"name": "typing-extensions",
"specs": [
[
">=",
"4.0.0"
]
]
},
{
"name": "cachetools",
"specs": [
[
">=",
"5.3.0"
]
]
}
],
"lcname": "togglr-sdk"
}