Skip to main content

Official Python SDK for the smplkit platform

Project description

smplkit Python SDK

PyPI Version Build Coverage License Docs

The official Python SDK for smplkit — simple application infrastructure that just works.

Installation

pip install smplkit-sdk

Requirements

  • Python 3.10+

Quick Start

One client is the whole SDK: SmplClient (and AsyncSmplClient). Construction is side-effect-free — no threads, no network until you actually use a feature — and only an api_key is required. Every product hangs off it:

Namespace Purpose
client.flags / client.config / client.logging Runtime instrumentation — flag evaluation, config reads, log-level control (environment-scoped)
client.audit Audit — record/read events, discovery, SIEM forwarders
client.jobs Jobs — scheduled or on-demand HTTP jobs
client.manage Management / CRUD — flag/config/logger definitions, environments, contexts, account settings

environment and service are optional — supply them when instrumenting with flags/config/logging (the server can also derive the environment from the API key); audit- or jobs-only callers need nothing but the key. For single-product use, standalone SmplAuditClient / SmplJobsClient are also available.

Runtime instrumentation

from smplkit import Context, SmplClient

with SmplClient(api_key="sk_api_...", environment="production", service="my-svc") as client:
    # Resolve config values for the current environment
    db = client.config.get("database")  # {"host": "...", "port": 5432}

    # Set the current request's context once (typically from middleware) —
    # contextvars provides per-request / per-thread isolation automatically.
    client.set_context([
        Context("user", request.user.id, plan=request.user.plan),
        Context("account", request.account.id, region=request.account.region),
    ])

    # Evaluate a flag — picks up the context set above.
    checkout_v2 = client.flags.boolean_flag("checkout-v2", default=False)
    if checkout_v2.get():
        ...

    # Opt in to runtime logging level control
    client.logging.install()

    # Need to reach the management API from a runtime context?
    # Every SmplClient owns an internal management client at `client.manage`.
    cfg = client.manage.config.get("database")

set_context() returns a scope object that doubles as a with block, so you can override context for a single block (e.g. impersonation):

with client.set_context([Context("user", "u-impersonated", plan="enterprise")]):
    if checkout_v2.get():
        ...
# original context restored here

For deterministic startup — pre-fetch all flags + configs and wait for the live-updates websocket before serving traffic — call client.wait_until_ready() once at boot.

Management / CRUD — client.manage

CRUD lives on the client.manage namespace. Just an API key — no environment or service, and (because construction is side-effect-free) no threads, no websocket, no service rows registered in the target account until you actually instrument with flags/config/logging:

from smplkit import SmplClient

with SmplClient(api_key="sk_api_...") as client:
    mgmt = client.manage

    # Configs
    cfg = mgmt.config.new("my_service", name="My Service")
    cfg.save()
    configs = mgmt.config.list()

    # Flags
    flag = mgmt.flags.new_boolean_flag("checkout-v2", default=False)
    flag.save()
    flags = mgmt.flags.list()

    # Loggers + log groups
    logger = mgmt.loggers.new("sql", name="SQL Logger")
    logger.save()
    grp = mgmt.log_groups.new("databases", name="Databases")
    grp.save()

    # App-service-owned resources
    for env in mgmt.environments.list():
        print(env.id)
    mgmt.contexts.register([...])
    settings = mgmt.account_settings.get()

A setup script, CI job, or admin CLI constructs SmplClient(api_key=...) and uses client.manage.* — it pays nothing for the runtime machinery it never touches.

Audit and Jobs

Audit and Jobs are single clients (no runtime/management split). Reach them on the client, or construct them standalone:

from smplkit import SmplAuditClient, SmplClient

with SmplClient(api_key="sk_api_...", environment="production") as client:
    client.audit.events.record("invoice.created", "invoice", "inv-1", flush=True)
    forwarders = client.audit.forwarders.list()
    # jobs are enabled per environment:
    job = client.jobs.new_recurring_job("nightly", name="Nightly", schedule="0 2 * * *", configuration=...)
    job.set_enabled(True, environment="production")
    job.save()

# audit-only? construct just the audit client (no environment needed):
with SmplAuditClient(api_key="sk_api_...") as audit:
    audit.events.record("invoice.created", "invoice", "inv-1", flush=True)

Async

Swap SmplClientAsyncSmplClient (likewise SmplAuditClientAsyncSmplAuditClient, SmplJobsClientAsyncSmplJobsClient); method bodies become await-able:

from smplkit import AsyncSmplClient

async with AsyncSmplClient(api_key="sk_api_...", environment="prod", service="svc") as client:
    db = await client.config.get("database")
    cfg = await client.manage.config.get("my_service")
    page = await client.audit.events.list(resource_type="invoice")

Management namespaces

client.manage exposes flat namespaces (one per resource family):

Namespace Resource
manage.contexts Context instances (register / list / get / delete)
manage.context_types Targeting-rule entity schemas
manage.environments Environments (built-ins + AD_HOC)
manage.account_settings Per-account settings
manage.config Smpl Config CRUD
manage.flags Smpl Flags CRUD
manage.loggers Smpl Logging logger CRUD
manage.log_groups Smpl Logging log-group CRUD

Endpoints outside this curated set — for example, Environment Access Groups and their memberships — are reachable via the generated client at smplkit._generated.app.api.{groups,group_memberships}. The generated module accepts the same authenticated client object you already construct for the curated namespaces.

Logging Adapters

client.logging.install() auto-loads adapters for every supported framework it finds installed. Two adapters ship with the SDK:

Adapter Covers
stdlib-logging Python logging.getLogger(...) — discovered and managed automatically
loguru The loguru library — requires pip install smplkit-sdk[loguru]

Both are registered as smplkit.logging.adapters entry points in pyproject.toml, so they are discovered via importlib.metadata at install() time with no extra wiring.

Adding a custom adapter — implement LoggingAdapter and register it before install():

from smplkit.logging.adapters.base import LoggingAdapter

class StructlogAdapter(LoggingAdapter):
    @property
    def name(self) -> str:
        return "structlog"

    def discover(self): ...
    def apply_level(self, name, level): ...
    def install_hook(self, on_new_logger): ...
    def uninstall_hook(self): ...

client.logging.register_adapter(StructlogAdapter())
client.logging.install()

Calling register_adapter() disables auto-loading — only the adapters you register are used.

Packaging an adapter for auto-discovery — declare the entry point in your package's pyproject.toml so it is picked up without any caller code change:

[project.entry-points."smplkit.logging.adapters"]
structlog = "my_package.adapter:StructlogAdapter"

Configuration

All settings are resolved from three sources, in order of precedence:

  1. Constructor arguments — highest priority, always wins.
  2. Environment variables — e.g. SMPLKIT_API_KEY, SMPLKIT_ENVIRONMENT.
  3. Configuration file (~/.smplkit) — INI-format with profile support.
  4. Defaults — built-in SDK defaults.

Configuration File

The ~/.smplkit file supports a [common] section (applied to all profiles) and named profiles:

[common]
environment = production
service = my-app

[default]
api_key = sk_api_abc123

[local]
base_domain = localhost
scheme = http
api_key = sk_api_local_xyz
environment = development
debug = true

Constructor Examples

# Use a named profile
client = SmplClient(profile="local")

# Or configure explicitly
client = SmplClient(
    api_key="sk_api_...",
    environment="production",
    service="my-service",
)

For the complete configuration reference, see the Configuration Guide.

Error Handling

All SDK errors extend smplkit.Error:

from smplkit import Error, NotFoundError

try:
    config = client.manage.config.get("nonexistent")
except NotFoundError:
    print("Config not found")
except Error as e:
    print(f"SDK error: {e}")

The error classes shadow built-ins (ConnectionError, TimeoutError, ValidationError), so import them from smplkit rather than relying on from smplkit import *, or alias on import (e.g. from smplkit import NotFoundError as SmplNotFound) if that collides with your own names.

Exception Cause
NotFoundError Resource not found
ConflictError Conflict (e.g., has children)
ValidationError Validation error
TimeoutError Request timed out
ConnectionError Network connectivity issue
Error Any other SDK error

Debug Logging

Set SMPLKIT_DEBUG=1 to enable verbose diagnostic output to stderr. This is useful for troubleshooting real-time level changes, WebSocket connectivity, and SDK initialization. Debug output bypasses the managed logging framework and writes directly to stderr.

SMPLKIT_DEBUG=1 python my_app.py

Accepted values: 1, true, yes (case-insensitive). Any other value (or unset) disables debug output.

Documentation

License

MIT

Project details


Release history Release notifications | RSS feed

Download files

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

Source Distribution

smplkit_sdk-3.2.181.tar.gz (638.0 kB view details)

Uploaded Source

Built Distribution

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

smplkit_sdk-3.2.181-py3-none-any.whl (916.8 kB view details)

Uploaded Python 3

File details

Details for the file smplkit_sdk-3.2.181.tar.gz.

File metadata

  • Download URL: smplkit_sdk-3.2.181.tar.gz
  • Upload date:
  • Size: 638.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for smplkit_sdk-3.2.181.tar.gz
Algorithm Hash digest
SHA256 5efbd373631639471f4d8a014dc0c05cadefb46c2189bb1c4c4eef4efb21f4a2
MD5 02d5f7b4f1f60e1fc8bec254f7dd9816
BLAKE2b-256 b7673b6b2993517432009b3f37a2815a937eee8f3edb4d709138ac87300b8595

See more details on using hashes here.

Provenance

The following attestation bundles were made for smplkit_sdk-3.2.181.tar.gz:

Publisher: ci-cd.yml on smplkit/python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file smplkit_sdk-3.2.181-py3-none-any.whl.

File metadata

  • Download URL: smplkit_sdk-3.2.181-py3-none-any.whl
  • Upload date:
  • Size: 916.8 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for smplkit_sdk-3.2.181-py3-none-any.whl
Algorithm Hash digest
SHA256 69694eaaba90baa5e9abec36c3f21112d335e9ce8eabca2f995743a28572888b
MD5 41f45ff88fe96c3804cb39a92c9b5544
BLAKE2b-256 df9122d37a5e33cd3f7f2789276f9622270bf0cb3e1bd0950f40cff1a9534274

See more details on using hashes here.

Provenance

The following attestation bundles were made for smplkit_sdk-3.2.181-py3-none-any.whl:

Publisher: ci-cd.yml on smplkit/python-sdk

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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