driftstack-sdk 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,226 @@
1
+ Metadata-Version: 2.4
2
+ Name: driftstack-sdk
3
+ Version: 0.1.0
4
+ Summary: Driftstack Python SDK — stealth iPhone Safari automation. Import as `driftstack`.
5
+ Project-URL: Homepage, https://driftstack.dev
6
+ Project-URL: Repository, https://github.com/driftstackdev/driftstack-api
7
+ Project-URL: Issues, https://github.com/driftstackdev/driftstack-api/issues
8
+ Author: Driftstack
9
+ License: MIT
10
+ Keywords: browser-automation,driftstack,ios,safari,stealth
11
+ Classifier: Development Status :: 3 - Alpha
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: License :: OSI Approved :: MIT License
14
+ Classifier: Operating System :: OS Independent
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
+ Classifier: Typing :: Typed
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: httpx<1.0,>=0.27
26
+ Requires-Dist: pydantic[email]<3.0,>=2.5
27
+ Provides-Extra: dev
28
+ Requires-Dist: datamodel-code-generator[http]>=0.25; extra == 'dev'
29
+ Requires-Dist: mypy>=1.10; extra == 'dev'
30
+ Requires-Dist: pytest-asyncio>=0.23; extra == 'dev'
31
+ Requires-Dist: pytest>=8.0; extra == 'dev'
32
+ Requires-Dist: respx>=0.21; extra == 'dev'
33
+ Requires-Dist: ruff>=0.5; extra == 'dev'
34
+ Description-Content-Type: text/markdown
35
+
36
+ # Driftstack Python SDK
37
+
38
+ 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.
39
+
40
+ > **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.
41
+
42
+ ## Install
43
+
44
+ ```bash
45
+ pip install driftstack-sdk
46
+ ```
47
+
48
+ The dist name on PyPI is `driftstack-sdk`; the import name is `driftstack`.
49
+
50
+ Requires Python 3.10+.
51
+
52
+ ## Quickstart (sync)
53
+
54
+ ```python
55
+ from driftstack import Driftstack
56
+
57
+ with Driftstack(api_key="ds_live_…") as client:
58
+ session = client.sessions.create({"label": "ci-run"})
59
+ client.sessions.navigate(str(session.id), {"url": "https://example.com/"})
60
+ state = client.sessions.get_state(str(session.id))
61
+ print(state.url, state.title)
62
+ client.sessions.destroy(str(session.id))
63
+ ```
64
+
65
+ ## Quickstart (async)
66
+
67
+ ```python
68
+ import asyncio
69
+ from driftstack import AsyncDriftstack
70
+
71
+ async def main():
72
+ async with AsyncDriftstack(api_key="ds_live_…") as client:
73
+ s = await client.sessions.create()
74
+ await client.sessions.navigate(str(s.id), {"url": "https://example.com/"})
75
+ await client.sessions.destroy(str(s.id))
76
+
77
+ asyncio.run(main())
78
+ ```
79
+
80
+ ## Resources
81
+
82
+ Every public API endpoint is a typed method on a resource accessor:
83
+
84
+ | Accessor | Methods |
85
+ | ----------------- | ------------------------------------------------------------------------------------------ |
86
+ | `client.sessions` | `create`, `list`, `get`, `navigate`, `interact`, `wait`, `get_state`, `capture`, `destroy` |
87
+ | `client.api_keys` | `create`, `list`, `revoke` |
88
+ | `client.usage` | `current_period` |
89
+ | `client.webhooks` | `create`, `list`, `get`, `delete`, `list_deliveries` |
90
+
91
+ 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.
92
+
93
+ ```python
94
+ # Either of these works:
95
+ from driftstack._generated.models import CreateSessionRequest
96
+ client.sessions.create(CreateSessionRequest(label="ci"))
97
+ client.sessions.create({"label": "ci"})
98
+ ```
99
+
100
+ ## Error handling
101
+
102
+ Every server `application/problem+json` response is mapped to a typed exception. The base class is `DriftstackError`; subclasses cover the documented problem types.
103
+
104
+ ```python
105
+ from driftstack import (
106
+ AuthError,
107
+ ConcurrencyLimitError,
108
+ DriftstackError,
109
+ QuotaExceededError,
110
+ RateLimitError,
111
+ ValidationError,
112
+ )
113
+
114
+ try:
115
+ session = client.sessions.create()
116
+ except AuthError:
117
+ ... # invalid / expired / revoked key
118
+ except ConcurrencyLimitError as e:
119
+ ... # e.current_sessions / e.limit
120
+ except QuotaExceededError as e:
121
+ ... # e.current / e.limit / e.record_type
122
+ except RateLimitError as e:
123
+ time.sleep(e.retry_after_seconds or 1)
124
+ except ValidationError as e:
125
+ ... # e.message has the server's detail
126
+ except DriftstackError as e:
127
+ ... # catch-all for anything else
128
+ ```
129
+
130
+ The full hierarchy lives in `driftstack/errors.py`; the URI → exception mapping is in `PROBLEM_TYPE_TO_ERROR`.
131
+
132
+ ## Retry
133
+
134
+ Default policy: 3 retries with exponential backoff and full jitter. Honours `Retry-After` from rate-limit responses. Customize via `RetryConfig`:
135
+
136
+ ```python
137
+ from driftstack import Driftstack
138
+ from driftstack.retry import RetryConfig
139
+
140
+ client = Driftstack(
141
+ api_key="ds_live_…",
142
+ retry=RetryConfig(max_retries=5, initial_delay_ms=500, max_delay_ms=10_000),
143
+ )
144
+
145
+ # Disable entirely for predictable testing:
146
+ client = Driftstack(api_key="…", retry=RetryConfig(enabled=False))
147
+ ```
148
+
149
+ Retryable errors by default: `TransportError` (network / timeout / parse) + `RateLimitError`. Other typed errors (auth, validation, quota, concurrency) propagate immediately.
150
+
151
+ ## Webhook signature verification
152
+
153
+ Stripe-style HMAC-SHA256 over `<unix_seconds>.<raw_body>`. Constant-time comparison via `hmac.compare_digest`. 5-minute default tolerance.
154
+
155
+ ```python
156
+ from driftstack import verify_webhook_signature
157
+
158
+ @app.post("/driftstack-webhook")
159
+ def receive():
160
+ raw = request.get_data() # framework-specific raw body
161
+ ok = verify_webhook_signature(
162
+ body=raw,
163
+ header=request.headers.get("x-driftstack-signature"),
164
+ secret=os.environ["DRIFTSTACK_WEBHOOK_SECRET"],
165
+ )
166
+ if not ok:
167
+ return ("", 401)
168
+ # ... process event ...
169
+ return ("", 204)
170
+ ```
171
+
172
+ A complete stdlib-only receiver lives in [`examples/webhook_receiver.py`](examples/webhook_receiver.py).
173
+
174
+ ## Examples
175
+
176
+ - [`quickstart.py`](examples/quickstart.py) — minimal create/navigate/capture/destroy.
177
+ - [`error_handling.py`](examples/error_handling.py) — granular catch + custom retry loop.
178
+ - [`webhook_receiver.py`](examples/webhook_receiver.py) — stdlib HTTP receiver with signature verify + dispatch.
179
+ - [`langchain_tool.py`](examples/langchain_tool.py) — LangChain `Tool` adapter for AI-agent QA pipelines.
180
+ - [`pytest_fixture.py`](examples/pytest_fixture.py) — drop-in `mock_driftstack` fixture for customer test suites.
181
+
182
+ ## Configuration
183
+
184
+ ```python
185
+ client = Driftstack(
186
+ api_key="ds_live_…", # required
187
+ base_url="https://api.driftstack.dev", # default; override for self-host or test
188
+ timeout_s=30.0, # per-request timeout
189
+ retry=RetryConfig(...), # see above
190
+ http_client=httpx.Client(...) # advanced: BYO httpx.Client
191
+ )
192
+ ```
193
+
194
+ The async client takes the same arguments; pass `httpx.AsyncClient(...)` instead of `httpx.Client(...)`.
195
+
196
+ ## Development
197
+
198
+ ```bash
199
+ # from packages/sdk-python/
200
+ python3.10 -m venv .venv
201
+ source .venv/bin/activate
202
+ pip install -e '.[dev]'
203
+ pytest
204
+ ruff check . && ruff format --check .
205
+ mypy src
206
+ ```
207
+
208
+ Re-generate Pydantic models from a fresh OpenAPI spec:
209
+
210
+ ```bash
211
+ # from the repo root
212
+ npm run sdk:python:dump-spec # writes packages/sdk-python/openapi.json
213
+ npm run sdk:python:generate # runs datamodel-codegen
214
+ ```
215
+
216
+ Build the wheel:
217
+
218
+ ```bash
219
+ # from packages/sdk-python/
220
+ python -m pip install build
221
+ python -m build # → dist/driftstack-X.Y.Z-py3-none-any.whl + sdist
222
+ ```
223
+
224
+ ## License
225
+
226
+ MIT.
@@ -0,0 +1,19 @@
1
+ driftstack/__init__.py,sha256=LNJKiDuftp5bDH2j8UZU9QxVzu6x-fzAbG3Joo5u-zc,1474
2
+ driftstack/_version.py,sha256=SSsD1--zWDGoDKKzXI8AKzNzGe6NPmM1VgsDlcDaIJY,331
3
+ driftstack/client.py,sha256=fI_WcPfeN8rpgOpvbhq8S_Ku5bwdfhMJtw1FyDuup8w,4276
4
+ driftstack/errors.py,sha256=caO__wvZ1TTTscsCiAmgltjISqtglnfrb24u4O_Shts,6938
5
+ driftstack/http.py,sha256=qm6uFXnq6OtAzs0-IA1ofk3pTFtuHpK1XQOCX-jviko,10099
6
+ driftstack/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
+ driftstack/retry.py,sha256=O3ONsIx11NUTLkumxo0wBJit5kVNMy5Vg0GBtaJkOxM,3491
8
+ driftstack/webhook_signature.py,sha256=S__HBpImMcSHz4FvHWRCBtwANkK2JRQQwikY9ZDrJ7c,3214
9
+ driftstack/_generated/__init__.py,sha256=RTXUjfOp7ZVibedHEGqtfr6CPB8h3XKLbz3-KYGcLPU,258
10
+ driftstack/_generated/models.py,sha256=IzOtTzjdDKvn73GEuyDk5D2NnZoDnvvpz0XdX5WGvh0,13615
11
+ driftstack/resources/__init__.py,sha256=PC44R4_TfnLkPAK7Ty9Wy7XfTQq5_GbN7bx3GQeDNXo,1024
12
+ driftstack/resources/_common.py,sha256=DyBQPAQThPz3H3Z0Q6klgd_XgSYrwlH_r5izVS4MI_s,1339
13
+ driftstack/resources/api_keys.py,sha256=7uGiKtq5gaXG2CGgRzfkTP-5R5FgtFTignNMgxLZWQ0,2148
14
+ driftstack/resources/sessions.py,sha256=xsPoxNubJ299bG4wlz1ZRXcMv8va4GQXsZDLPy4WRIo,5913
15
+ driftstack/resources/usage.py,sha256=oegqGhkpeosmcKUzqQPPzTJdyWnEPVjYQ-gPs8Sz8ks,868
16
+ driftstack/resources/webhooks.py,sha256=APLdXHTYS47oXi-166E4KV8DEpIGnqvDk_Ek0mCG2Kk,3635
17
+ driftstack_sdk-0.1.0.dist-info/METADATA,sha256=6UjEjmWygo7nMXWfPg6MpFFgtDI9vqaeyjm_49qNv4U,8104
18
+ driftstack_sdk-0.1.0.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
19
+ driftstack_sdk-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.29.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any