Skip to main content

Python SDK for Astrolabe feature flag system

Project description

Astrolabe Python SDK

A Python SDK for the Astrolabe feature flag system, supporting number, string, boolean, and JSON flags with environment-based configuration.

Installation

pip install astrolabe-python-sdk

Quick Start

from astrolabe import AstrolabeClient

# Initialize the client with your environment
client = AstrolabeClient(env="development")  # or "staging", "production"

# Evaluate different types of flags
boolean_flag = client.get_boolean_flag("feature_enabled", default=False)
string_flag = client.get_string_flag("welcome_message", default="Hello!")
number_flag = client.get_number_flag("max_items", default=10)
json_flag = client.get_json_flag("config", default={"theme": "light"})

# Generic flag evaluation (type inferred from default)
flag_value = client.get_flag("any_flag", default="default_value")

Usage

Initialization

from astrolabe import AstrolabeClient
from astrolabe.client import Environment

# Using string
client = AstrolabeClient("production")

# Using enum
client = AstrolabeClient(Environment.PRODUCTION)

Flag Evaluation with Attributes

# Pass attributes for context-aware flag evaluation
attributes = {
    "user_id": "12345",
    "region": "us-east-1",
    "plan": "premium"
}

result = client.get_boolean_flag(
    key="premium_feature", 
    default=False, 
    attributes=attributes
)

Supported Flag Types

  • Boolean flags: get_boolean_flag(key, default, attributes=None)
  • String flags: get_string_flag(key, default, attributes=None)
  • Number flags: get_number_flag(key, default, attributes=None) (supports int and float)
  • JSON flags: get_json_flag(key, default, attributes=None) (returns dict)
  • Generic flags: get_flag(key, default, attributes=None) (type inferred from default)

Environments

Supported environments:

  • development
  • staging
  • production

Async Support

For use in async frameworks (FastAPI, Starlette, aiohttp, etc.), install the async extra:

pip install astrolabe-python-sdk[async]

Then use AsyncAstrolabeClient, which uses httpx.AsyncClient under the hood and an asyncio.Task for background polling — it never blocks the event loop.

Basic async usage

import os
from astrolabe import AsyncAstrolabeClient

os.environ["ASTROLABE_API_URL"] = "https://your-astrolabe-api.com"

async def main():
    async with AsyncAstrolabeClient(
        env="production",
        subscribed_projects=["my-project"],
    ) as client:
        # Evaluate flags (sync — pure in-memory cache reads, no I/O)
        enabled = client.get_bool("my-project/dark-mode", default=False)
        limit  = client.get_number("my-project/rate-limit", default=100)
        banner = client.get_string("my-project/banner-text", default="Welcome!")
        config = client.get_json("my-project/ui-config", default={"theme": "light"})

        # With user attributes for rule-based targeting
        premium = client.get_bool(
            "my-project/premium-feature",
            default=False,
            attributes={"user_id": "u-42", "plan": "enterprise"},
        )

        # Manual refresh (non-blocking)
        await client.refresh_flags()

FastAPI example

from contextlib import asynccontextmanager
from fastapi import FastAPI, Request
from astrolabe import AsyncAstrolabeClient

astrolabe: AsyncAstrolabeClient | None = None

@asynccontextmanager
async def lifespan(app: FastAPI):
    global astrolabe
    astrolabe = await AsyncAstrolabeClient(
        env="production",
        subscribed_projects=["backend"],
    ).start()
    yield
    await astrolabe.close()

app = FastAPI(lifespan=lifespan)

@app.get("/feature")
async def feature(request: Request):
    enabled = astrolabe.get_bool("backend/new-checkout", default=False)
    return {"new_checkout_enabled": enabled}

FastAPI with Depends()

You can inject the client through FastAPI's dependency injection system:

from contextlib import asynccontextmanager
from fastapi import Depends, FastAPI
from astrolabe import AsyncAstrolabeClient

@asynccontextmanager
async def lifespan(app: FastAPI):
    app.state.astrolabe = await AsyncAstrolabeClient(
        env="production",
        subscribed_projects=["backend"],
    ).start()
    yield
    await app.state.astrolabe.close()

app = FastAPI(lifespan=lifespan)


def get_astrolabe(request) -> AsyncAstrolabeClient:
    """Dependency that provides the shared AsyncAstrolabeClient."""
    return request.app.state.astrolabe


@app.get("/feature")
async def feature(flags: AsyncAstrolabeClient = Depends(get_astrolabe)):
    enabled = flags.get_bool("backend/new-checkout", default=False)
    limit = flags.get_number("backend/rate-limit", default=100)
    return {"new_checkout_enabled": enabled, "rate_limit": limit}


@app.get("/dashboard")
async def dashboard(flags: AsyncAstrolabeClient = Depends(get_astrolabe)):
    theme = flags.get_string("backend/theme", default="light")
    config = flags.get_json(
        "backend/dashboard-config",
        default={"widgets": []},
        attributes={"role": "admin"},
    )
    return {"theme": theme, "config": config}

This pattern stores the client on app.state and injects it via Depends(), so your route handlers stay testable — just override the dependency in tests.

Explicit lifecycle (without context manager)

client = AsyncAstrolabeClient("staging", subscribed_projects=["svc"])
await client.start()       # creates httpx client, fetches flags, starts polling

try:
    value = client.get_flag("svc/experiment", default="control")
finally:
    await client.close()   # stops polling, closes httpx client

Development

This SDK is currently in development. Flag evaluation logic is stubbed and will be implemented in future versions.

License

MIT License

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

astrolabe_python_sdk-1.1.1.tar.gz (34.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

astrolabe_python_sdk-1.1.1-py3-none-any.whl (15.6 kB view details)

Uploaded Python 3

File details

Details for the file astrolabe_python_sdk-1.1.1.tar.gz.

File metadata

  • Download URL: astrolabe_python_sdk-1.1.1.tar.gz
  • Upload date:
  • Size: 34.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.3

File hashes

Hashes for astrolabe_python_sdk-1.1.1.tar.gz
Algorithm Hash digest
SHA256 c87f7ff6acf01d4a7a6bf75f8d8f469b4551302b8ca068ca75d937938e1685fb
MD5 a149d2b6db5555944bdd6681aedfd6af
BLAKE2b-256 12fd89f4892edb810c049411996dc952959e48c8a0c2772a703767c86d384621

See more details on using hashes here.

File details

Details for the file astrolabe_python_sdk-1.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for astrolabe_python_sdk-1.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 2cf1127b40c5d2e9f9db64ed75332019716c49388b91327a35305bdaf1bf64b0
MD5 874a6918385d423f0bad8b68cbaa0a84
BLAKE2b-256 cbbdbf4b9f06547c421a665ea4b8eb6fbc2304bfcce5432dd8efd5617ee9b8c9

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page