Skip to main content

Driftstack Python SDK — stealth iPhone Safari automation. Import as `driftstack`.

Project description

Driftstack Python SDK

Stealth iPhone Safari automation, called from Python. Sync (Driftstack) and async (AsyncDriftstack) clients in one package, sharing the same typed resources, error hierarchy, and retry policy.

Status: alpha. The SDK is built, tested, and wheel-buildable, but not yet published to PyPI — gated on entity setup. Until then, install from a local checkout or a tagged commit.

Install

pip install driftstack-sdk

The dist name on PyPI is driftstack-sdk; the import name is driftstack.

Requires Python 3.10+.

Quickstart (sync)

from driftstack import Driftstack

with Driftstack(api_key="ds_live_…") as client:
    session = client.sessions.create({"label": "ci-run"})
    client.sessions.navigate(str(session.id), {"url": "https://example.com/"})
    state = client.sessions.get_state(str(session.id))
    print(state.url, state.title)
    client.sessions.destroy(str(session.id))

Quickstart (async)

import asyncio
from driftstack import AsyncDriftstack

async def main():
    async with AsyncDriftstack(api_key="ds_live_…") as client:
        s = await client.sessions.create()
        await client.sessions.navigate(str(s.id), {"url": "https://example.com/"})
        await client.sessions.destroy(str(s.id))

asyncio.run(main())

Resources

Every public API endpoint is a typed method on a resource accessor:

Accessor Methods
client.sessions create, list, get, navigate, interact, wait, get_state, capture, destroy
client.api_keys create, list, revoke
client.usage current_period
client.webhooks create, list, get, delete, list_deliveries

Inputs accept either a Pydantic model OR a plain dict (both serialize identically on the wire). Outputs are typed Pydantic models — IDEs autocomplete every field.

# Either of these works:
from driftstack._generated.models import CreateSessionRequest
client.sessions.create(CreateSessionRequest(label="ci"))
client.sessions.create({"label": "ci"})

Error handling

Every server application/problem+json response is mapped to a typed exception. The base class is DriftstackError; subclasses cover the documented problem types.

from driftstack import (
    AuthError,
    ConcurrencyLimitError,
    DriftstackError,
    QuotaExceededError,
    RateLimitError,
    ValidationError,
)

try:
    session = client.sessions.create()
except AuthError:
    ...                                    # invalid / expired / revoked key
except ConcurrencyLimitError as e:
    ...                                    # e.current_sessions / e.limit
except QuotaExceededError as e:
    ...                                    # e.current / e.limit / e.record_type
except RateLimitError as e:
    time.sleep(e.retry_after_seconds or 1)
except ValidationError as e:
    ...                                    # e.message has the server's detail
except DriftstackError as e:
    ...                                    # catch-all for anything else

The full hierarchy lives in driftstack/errors.py; the URI → exception mapping is in PROBLEM_TYPE_TO_ERROR.

Retry

Default policy: 3 retries with exponential backoff and full jitter. Honours Retry-After from rate-limit responses. Customize via RetryConfig:

from driftstack import Driftstack
from driftstack.retry import RetryConfig

client = Driftstack(
    api_key="ds_live_…",
    retry=RetryConfig(max_retries=5, initial_delay_ms=500, max_delay_ms=10_000),
)

# Disable entirely for predictable testing:
client = Driftstack(api_key="…", retry=RetryConfig(enabled=False))

Retryable errors by default: TransportError (network / timeout / parse) + RateLimitError. Other typed errors (auth, validation, quota, concurrency) propagate immediately.

Webhook signature verification

Stripe-style HMAC-SHA256 over <unix_seconds>.<raw_body>. Constant-time comparison via hmac.compare_digest. 5-minute default tolerance.

from driftstack import verify_webhook_signature

@app.post("/driftstack-webhook")
def receive():
    raw = request.get_data()                   # framework-specific raw body
    ok = verify_webhook_signature(
        body=raw,
        header=request.headers.get("x-driftstack-signature"),
        secret=os.environ["DRIFTSTACK_WEBHOOK_SECRET"],
    )
    if not ok:
        return ("", 401)
    # ... process event ...
    return ("", 204)

A complete stdlib-only receiver lives in examples/webhook_receiver.py.

Examples

Configuration

client = Driftstack(
    api_key="ds_live_…",          # required
    base_url="https://api.driftstack.dev",   # default; override for self-host or test
    timeout_s=30.0,               # per-request timeout
    retry=RetryConfig(...),       # see above
    http_client=httpx.Client(...) # advanced: BYO httpx.Client
)

The async client takes the same arguments; pass httpx.AsyncClient(...) instead of httpx.Client(...).

Development

# from packages/sdk-python/
python3.10 -m venv .venv
source .venv/bin/activate
pip install -e '.[dev]'
pytest
ruff check . && ruff format --check .
mypy src

Re-generate Pydantic models from a fresh OpenAPI spec:

# from the repo root
npm run sdk:python:dump-spec     # writes packages/sdk-python/openapi.json
npm run sdk:python:generate      # runs datamodel-codegen

Build the wheel:

# from packages/sdk-python/
python -m pip install build
python -m build       # → dist/driftstack-X.Y.Z-py3-none-any.whl + sdist

License

MIT.

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

driftstack_sdk-0.1.5.tar.gz (17.2 kB view details)

Uploaded Source

Built Distribution

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

driftstack_sdk-0.1.5-py3-none-any.whl (22.5 kB view details)

Uploaded Python 3

File details

Details for the file driftstack_sdk-0.1.5.tar.gz.

File metadata

  • Download URL: driftstack_sdk-0.1.5.tar.gz
  • Upload date:
  • Size: 17.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for driftstack_sdk-0.1.5.tar.gz
Algorithm Hash digest
SHA256 7c9499fe8ce5d021eca3e7b98ebcff74ea518b688fc0fb49bc4cf9ac4261edd4
MD5 79ad15dfec30ba42ae6559af9006fca6
BLAKE2b-256 aa3cc902923aee2f22a6b92a46fb221afe4d5d7fb2525f6c1db3ec7712107d53

See more details on using hashes here.

File details

Details for the file driftstack_sdk-0.1.5-py3-none-any.whl.

File metadata

  • Download URL: driftstack_sdk-0.1.5-py3-none-any.whl
  • Upload date:
  • Size: 22.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.20

File hashes

Hashes for driftstack_sdk-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 401e3d6e93d0c2979b6aa9c8cbd4b2a16fde3688904c88a48b97d8245ce54981
MD5 63c8be95f892e5d14d4f01be86f7c810
BLAKE2b-256 2b98714cbfd02a4564489c8e1e2823148f14f972cdb92942e79cb56c698a61ef

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