Metadata-Version: 2.4
Name: shipeasy
Version: 0.14.0
Summary: Shipeasy server SDK for Python — feature flags, configs, experiments, metrics.
Project-URL: Homepage, https://shipeasy.dev
Project-URL: Source, https://github.com/shipeasy-ai/sdk-python
Author: Shipeasy
License: MIT
License-File: LICENSE
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.9
Provides-Extra: admin
Requires-Dist: pydantic>=2.11; extra == 'admin'
Requires-Dist: python-dateutil>=2.8.2; extra == 'admin'
Requires-Dist: typing-extensions>=4.7.1; extra == 'admin'
Requires-Dist: urllib3<3.0.0,>=2.1.0; extra == 'admin'
Provides-Extra: django
Requires-Dist: django>=3.2; extra == 'django'
Provides-Extra: openfeature
Requires-Dist: openfeature-sdk>=0.7; extra == 'openfeature'
Description-Content-Type: text/markdown

<!--
  This file is GENERATED by scripts/gen_readme.py from docs/.
  Do NOT edit by hand — edit the docs, then run: python scripts/gen_readme.py
-->

# shipeasy (Python)

[![Tests](https://github.com/shipeasy-ai/sdk-python/actions/workflows/tests.yml/badge.svg)](https://github.com/shipeasy-ai/sdk-python/actions/workflows/tests.yml)
[![PyPI](https://img.shields.io/pypi/v/shipeasy.svg)](https://pypi.org/project/shipeasy/)
[![Python](https://img.shields.io/pypi/pyversions/shipeasy.svg)](https://pypi.org/project/shipeasy/)

Server SDK for [Shipeasy](https://shipeasy.dev) — **feature flags, dynamic
configs, kill switches, A/B experiments, and metric tracking**. Server-key only;
never embed in a browser.

> 📚 **Full documentation:** **<https://shipeasy-ai.github.io/sdk-python/>** — also browsable under
> [`docs/`](https://github.com/shipeasy-ai/sdk-python/blob/main/docs). This README is generated from those docs.

## 🤖 Using an AI agent?

This SDK ships an installable **agent skill** — a copy-paste-ready guide to
`configure()` + `Client(user)`, testing, experiments, error reporting, and more,
with links the agent can pull for deeper docs:

- **Skill:** [`docs/skill/SKILL.md`](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/skill/SKILL.md) · raw:
  `https://shipeasy-ai.github.io/sdk-python/skill/SKILL.md`
- **Install it** (ships with the package — no network):
  `shipeasy-skill install` → `.claude/skills/shipeasy-python/SKILL.md`
  (or via the Shipeasy CLI: `shipeasy docs skill --sdk python --install`)

**Humans:** you can copy that skill straight into your own project's agent skills
directory (e.g. `.claude/skills/shipeasy-python/SKILL.md`) so your
coding agent always uses the correct Shipeasy patterns. Every doc page and snippet
is also fetchable by URL — start from the manifest at `https://shipeasy-ai.github.io/sdk-python/manifest.json`.

## Install

```bash
# pip
pip install shipeasy

# poetry
poetry add shipeasy

# uv
uv add shipeasy
```

Requires Python 3.9+. Per-framework setup (Django / Flask / FastAPI) and the
anon-id middleware are on the [Installation](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/installation.md) page.

## Quickstart — `configure()` once, then `Client(user)` per request

```python
import shipeasy

shipeasy.configure(
    api_key="sdk_server_...",
    attributes=lambda u: {"user_id": u.id, "country": u.country, "plan": u.plan},
)

# construct once per callsite (cheap; binds the user)
client = shipeasy.Client(current_user)

if client.get_flag("new_checkout"):
    ...
config = client.get_config("billing_copy")
result = client.get_experiment("checkout_button", default_params={"color": "blue"})
client.log_exposure("checkout_button")    # at the decision point
client.track("purchase", {"amount": 49})  # on conversion
```

Constructing `Client(user)` before `configure()` raises `RuntimeError`.

## Documentation

| Page | What |
| --- | --- |
| [Overview](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/overview.md) | The `configure()` + `Client(user)` model. |
| [Installation](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/installation.md) | Install, frameworks (Django / Flask / FastAPI), `configure()` wiring. |
| [Configuration](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/configuration.md) | Keys, `attributes`, one-shot vs poll, every option. |
| [Feature flags](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/flags.md) | `get_flag`, `get_flag_detail`, defaults. |
| [Dynamic configs](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/configs.md) | `get_config`, typed decode, defaults. |
| [Kill switches](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/killswitches.md) | `get_killswitch`, named switches. |
| [Experiments](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/experiments.md) | `get_experiment`, `log_exposure`, `track`. |
| [Internationalization](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/i18n.md) | SSR loader tag (rendering is client-side). |
| [Error reporting](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/error-reporting.md) | `see()` structured error reporting. |
| [Testing](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/testing.md) | `configure_for_testing` / `configure_for_offline`, overrides. |
| [OpenFeature](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/openfeature.md) | `ShipeasyProvider` (OpenFeature server provider). |
| [Advanced](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/advanced.md) | Anon-id middleware, private attributes, sticky bucketing, SSR. |
| [Admin API client](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/admin-api.md) | Optional `shipeasy.admin` client for administering resources (generated from the OpenAP… |

Copy-paste snippets live under [`docs/snippets/`](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/snippets)
(release · metrics · i18n · ops); an installable agent skill is at
[`docs/skill/SKILL.md`](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/skill/SKILL.md).

## Testing

Use **`configure_for_testing()`** — the test-mode sibling of [`configure()`](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/configuration.md). It does **zero network**, needs no api_key, and seeds the values your code under test should see via override arguments. Then read through the ordinary `shipeasy.Client(user)` — the *same* call your production code uses.

```python
import shipeasy
from shipeasy import Client

shipeasy.configure_for_testing(
    flags={"new_checkout": True},
    configs={"billing_copy": {"title": "Welcome"}},
    experiments={"checkout_button": ("treatment", {"color": "green"})},
)

# construct once per callsite (cheap; binds the user)
client = Client({"user_id": "u_123"})

assert client.get_flag("new_checkout") is True
assert client.get_config("billing_copy") == {"title": "Welcome"}

result = client.get_experiment("checkout_button", default_params={"color": "blue"})
assert result.in_experiment and result.group == "treatment"
assert result.params == {"color": "green"}

# track()/log_exposure() are no-ops in test mode — safe to call, send nothing
client.track("purchase", {"amount": 49})
```

More — the on-the-spot override helpers and a working example
`shipeasy-snapshot.json` — on the [Testing](https://github.com/shipeasy-ai/sdk-python/blob/main/docs/pages/testing.md) page.

## License

MIT. Evaluation is tested against the cross-language MurmurHash3 vectors in
`experiment-platform/04-evaluation.md`.
