Skip to main content

Zenmanage Python SDK

PyPI version CI Codacy Badge Coverage

Add feature flags to your Python application in minutes. Control feature rollouts, A/B test, and manage configurations without deploying code.

Why Zenmanage?

  • Fast: rules cached locally for low-latency evaluation
  • Targeted: roll out by user, organization, or custom attributes
  • Safe: graceful defaults and typed accessors
  • Insightful: optional usage reporting
  • Testable: deterministic rollout logic and isolated rule engine

Installation

pip install zenmanage

Requirements: Python 3.9+

Key Compatibility

  • Supported in Python SDK: case-sensitive server keys prefixed with srv_
  • Not supported in Python SDK: client keys (cli_) and mobile keys (mob_) (initialization fails fast)

Get Started in 60 Seconds

  1. Get your server key (srv_...) from zenmanage.com
  2. Initialize the SDK:
from zenmanage import ConfigBuilder, Zenmanage

zenmanage = Zenmanage(
    ConfigBuilder.create()
    .with_environment_token("srv_your_server_key_here")
    .build()
)
  1. Check a feature flag:
flag = zenmanage.flags().single("new-dashboard", False)

if flag.is_enabled():
    show_new_dashboard()
else:
    show_old_dashboard()

Common Use Cases

Async Frameworks (FastAPI, Starlette, etc.)

from zenmanage import AsyncZenmanage, ConfigBuilder, Context

zenmanage = AsyncZenmanage(
    ConfigBuilder.from_environment().build()
)

async def is_enabled_for_user(user_id: str) -> bool:
    context = Context.single("user", user_id)
    flag = await zenmanage.flags().with_context(context).single("new-dashboard", False)
    return flag.is_enabled()

Remember to close the async client on shutdown:

await zenmanage.aclose()

Roll Out a New Feature Gradually

from zenmanage import Context

context = Context.single("user", user_id, user_name)

beta_access = (
    zenmanage.flags()
    .with_context(context)
    .single("beta-program", False)
    .is_enabled()
)

if beta_access:
    enable_beta_features()

A/B Testing

from zenmanage import Attribute, Context

context = Context.single("user", user.id, user.name)
context.add_attribute(Attribute.from_strings("country", [user.country]))
context.add_attribute(Attribute.from_strings("plan", [user.subscription_plan]))

variant = (
    zenmanage.flags()
    .with_context(context)
    .single("checkout-flow", "multi-page")
    .as_string()
)

if variant == "one-page":
    render_one_page_checkout()
else:
    render_multi_page_checkout()

JSON Configuration

# Structured configuration values (both JSON objects and arrays decode to Python dict/list)
theme = zenmanage.flags().single("theme-config", {"mode": "light", "accent": "#4f46e5"}).as_json()

rollout_plan = zenmanage.flags().single("rollout-plan", []).as_json()

Percentage Rollouts

from zenmanage import Context

context = Context.single("user", user_id)

flag = (
    zenmanage.flags()
    .with_context(context)
    .single("new-checkout-flow", False)
)

if flag.is_enabled():
    render_new_checkout()
else:
    render_classic_checkout()

How it works:

  • Configure rollout percentage (0-100) and salt in Zenmanage
  • SDK computes CRC32B bucket from salt:contextIdentifier
  • Same user always lands in same bucket
  • Increasing percentage only adds users, never removes included users

Use Defaults Across Many Flags

from zenmanage import DefaultsCollection

defaults = DefaultsCollection.from_dict(
    {
        "new-ui": True,
        "api-version": "v2",
        "max-items": 100,
    }
)

flag_manager = zenmanage.flags().with_defaults(defaults)
new_ui = flag_manager.single("new-ui").as_bool()

Fetch All Flags

for flag in zenmanage.flags().all():
    print(flag.key, flag.get_value())

Configuration

import logging

config = (
    ConfigBuilder.create()
    .with_environment_token("srv_your_server_key_here")
    .with_cache_ttl(3600)
    .with_cache_backend("memory")  # memory | filesystem | null
    .with_cache_directory(".cache/zenmanage")  # required for filesystem
    .with_usage_reporting(True)
    .with_api_endpoint("https://api.zenmanage.com")
    .with_logger(logging.getLogger("my-app"))
    .build()
)

You can also load from environment variables:

  • ZENMANAGE_ENVIRONMENT_TOKEN
  • ZENMANAGE_CACHE_TTL
  • ZENMANAGE_CACHE_BACKEND
  • ZENMANAGE_CACHE_DIR
  • ZENMANAGE_ENABLE_USAGE_REPORTING
  • ZENMANAGE_API_ENDPOINT
config = ConfigBuilder.from_environment().build()

Cache Backends

  • memory: default, fastest, process-local
  • filesystem: durable between process restarts
  • null: disables caching

Custom cache objects are supported with with_cache(...) as long as they implement get, set, has, delete, and clear.

Examples

See examples/README.md for runnable examples:

  • simple-flags
  • ab-testing
  • caching
  • context-based-flags
  • defaults
  • percentage-rollouts
  • django-integration
  • flask-integration
  • fastapi-async

Framework integrations: docs/FRAMEWORK_INTEGRATIONS.md

License

MIT

Release files for zenmanage 1.2.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 zenmanage 1.2.0
File Size Uploaded
zenmanage-1.2.0.tar.gz 30.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for zenmanage 1.2.0
File Interpreter ABI Platform
zenmanage-1.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 55.5 kB

Release files / zenmanage-1.2.0.tar.gz

Download URL zenmanage-1.2.0.tar.gz
Size 30.2 kB
Tags Source
SHA-256 checksum
How to use checksums
98218f9c9739c943e813f4a2312039080a6bbcce4c5b3e1f52e0306192f696c1
BLAKE2b-256 checksum
How to use checksums
ebc78dc1c39c2cf27b8ebb2188b045f3c987563b6e06d6d48502c4b7f46db86c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release files / zenmanage-1.2.0-py3-none-any.whl

Download URL zenmanage-1.2.0-py3-none-any.whl
Size 25.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
91455d5eb3249db83dfe813d9a97ee07fc6ed4bde35b474706376447c6cd655b
BLAKE2b-256 checksum
How to use checksums
449b16006edf22fd98530b9de33b84f08dfaa07362540f85445b163022aaadbf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.12.14

Release history Release notifications | RSS feed

This release

1.2.0 This release

2 release files

1.1.3

2 release files

1.1.2

2 release files

1.1.1

2 release files

1.1.0

2 release files

1.0.1

2 release files

1.0.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