makers-sdk 0.1.0__tar.gz
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.
- makers_sdk-0.1.0/PKG-INFO +436 -0
- makers_sdk-0.1.0/README.md +425 -0
- makers_sdk-0.1.0/pyproject.toml +24 -0
- makers_sdk-0.1.0/setup.cfg +4 -0
- makers_sdk-0.1.0/src/makers_sdk/__init__.py +26 -0
- makers_sdk-0.1.0/src/makers_sdk/_artifacts.py +361 -0
- makers_sdk-0.1.0/src/makers_sdk/client.py +1735 -0
- makers_sdk-0.1.0/src/makers_sdk/errors.py +54 -0
- makers_sdk-0.1.0/src/makers_sdk.egg-info/PKG-INFO +436 -0
- makers_sdk-0.1.0/src/makers_sdk.egg-info/SOURCES.txt +13 -0
- makers_sdk-0.1.0/src/makers_sdk.egg-info/dependency_links.txt +1 -0
- makers_sdk-0.1.0/src/makers_sdk.egg-info/requires.txt +4 -0
- makers_sdk-0.1.0/src/makers_sdk.egg-info/top_level.txt +1 -0
- makers_sdk-0.1.0/tests/test_client.py +1799 -0
- makers_sdk-0.1.0/tests/test_smoke_harness.py +261 -0
|
@@ -0,0 +1,436 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: makers-sdk
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Synchronous Python client for the EdgeOne Makers SDK
|
|
5
|
+
License-Expression: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Description-Content-Type: text/markdown
|
|
8
|
+
Requires-Dist: cos-python-sdk-v5==1.9.44
|
|
9
|
+
Provides-Extra: test
|
|
10
|
+
Requires-Dist: jsonschema[format]>=4.18; extra == "test"
|
|
11
|
+
|
|
12
|
+
# EdgeOne Makers Python SDK
|
|
13
|
+
|
|
14
|
+
[English](README.md) | [中文](README.zh-CN.md)
|
|
15
|
+
|
|
16
|
+
Synchronous Python 3.10+ client for EdgeOne Makers projects, environment variables, artifact deployments, and tenant tokens. There is no async Makers.
|
|
17
|
+
|
|
18
|
+
PyPI package: `makers-sdk` · `import makers_sdk` · Version `0.1.0` · Contract `0.1.39` · MIT License
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
pip install makers-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```python
|
|
27
|
+
from makers_sdk import Makers
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
---
|
|
31
|
+
|
|
32
|
+
## Makers
|
|
33
|
+
|
|
34
|
+
### Constructor
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
import os
|
|
38
|
+
from makers_sdk import Makers
|
|
39
|
+
|
|
40
|
+
makers = Makers(
|
|
41
|
+
token=os.environ["MAKERS_API_TOKEN"],
|
|
42
|
+
region="china",
|
|
43
|
+
)
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
| Parameter | Type | Required | Default | Description |
|
|
47
|
+
|-----------|------|:--------:|---------|-------------|
|
|
48
|
+
| `token` | `str` | Yes | — | EdgeOne Makers API Token |
|
|
49
|
+
| `region` | `str` | No | auto-detect | `"china"` → `pages-api.cloud.tencent.com/v1`; `"global"` → `pages-api.edgeone.ai/v1` |
|
|
50
|
+
| `timeout` | `float` | No | `30` | Per-request timeout in **seconds** |
|
|
51
|
+
| `retries` | `int` | No | `3` | Max retry count for queries; writes do not retry |
|
|
52
|
+
| `logger` | `Logger` | No | — | Must implement `debug`, `info`, `warn`, `error` |
|
|
53
|
+
|
|
54
|
+
Auto-detection probes china then global and caches the result per Makers instance.
|
|
55
|
+
|
|
56
|
+
### Public members
|
|
57
|
+
|
|
58
|
+
| Member | Type | Description |
|
|
59
|
+
|--------|------|-------------|
|
|
60
|
+
| `makers.projects` | `Projects` | Project and environment variable operations |
|
|
61
|
+
| `makers.deployments` | `Deployments` | Deployment operations |
|
|
62
|
+
| `makers.tokens` | `Tokens` | Issue a tenant token (`tokens.create`) |
|
|
63
|
+
| `makers.region` | `str \| None` | Read-only; configured or detected region |
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## Tokens
|
|
68
|
+
|
|
69
|
+
Issue a tenant token with a **master API Token**, then construct a new `Makers` with the returned `token` to manage that tenant's projects. `tokens.create` requires `tenant_id`, `name`, and `expires_in`. It returns `{ "token", "token_id", "expired" }`.
|
|
70
|
+
|
|
71
|
+
`expires_in` is relative seconds, not a unix timestamp. The returned `expired` is the backend expiry time as a unix-seconds number.
|
|
72
|
+
|
|
73
|
+
Call `tokens.create` with a master API Token. The SDK does not inspect whether the current token is a master Token or a tenant token, and will not block a tenant token from calling `tokens.create`. v1 does not provide list, get, or delete token methods.
|
|
74
|
+
|
|
75
|
+
Repeating `tokens.create` with the same `tenant_id` is idempotent: the same `token` and `token_id` are returned, and only `expired` may refresh.
|
|
76
|
+
|
|
77
|
+
### `tokens.create(*, tenant_id, name, expires_in)`
|
|
78
|
+
|
|
79
|
+
```python
|
|
80
|
+
platform = Makers(
|
|
81
|
+
token=os.environ["MAKERS_API_TOKEN"],
|
|
82
|
+
)
|
|
83
|
+
created = platform.tokens.create(
|
|
84
|
+
tenant_id="user-open-id",
|
|
85
|
+
name="user-open-id",
|
|
86
|
+
expires_in=86400,
|
|
87
|
+
)
|
|
88
|
+
user = Makers(token=created["token"])
|
|
89
|
+
created_project = user.projects.create(name="my-site")
|
|
90
|
+
project_id = created_project["project_id"]
|
|
91
|
+
user.deployments.deploy(
|
|
92
|
+
project_id=project_id,
|
|
93
|
+
artifact={"files": {"index.html": "<h1>Hello</h1>"}},
|
|
94
|
+
)
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
| Parameter | Type | Required | Description |
|
|
98
|
+
|-----------|------|:--------:|-------------|
|
|
99
|
+
| `tenant_id` | `str` | Yes | Tenant identifier; non-empty, max 64 characters |
|
|
100
|
+
| `name` | `str` | Yes | Token name; 1–128 characters |
|
|
101
|
+
| `expires_in` | `int` | Yes | Lifetime in relative seconds (integer 10–315360000), not a unix timestamp |
|
|
102
|
+
|
|
103
|
+
**Returns** `dict`: `{ "token", "token_id", "expired" }`. `expired` is the backend expiry time as unix seconds. Invalid input raises `ValidationError` before any network request.
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## Projects
|
|
108
|
+
|
|
109
|
+
All return values are `dict` with `snake_case` keys. Optional fields may be absent — always use `.get()`.
|
|
110
|
+
|
|
111
|
+
### `projects.create(*, name, area?, initial_env_vars?)`
|
|
112
|
+
|
|
113
|
+
Creates a project. Returns `{"project_id": ...}` only — query `get` for the full model.
|
|
114
|
+
|
|
115
|
+
```python
|
|
116
|
+
created = makers.projects.create(
|
|
117
|
+
name="docs-site",
|
|
118
|
+
area="overseas",
|
|
119
|
+
initial_env_vars=[{"key": "API_URL", "value": "https://example.com"}],
|
|
120
|
+
)
|
|
121
|
+
project_id = created["project_id"]
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
| Parameter | Type | Required | Description |
|
|
125
|
+
|-----------|------|:--------:|-------------|
|
|
126
|
+
| `name` | `str` | Yes | Unique per account; duplicate raises `ConflictError` |
|
|
127
|
+
| `area` | `str` | No | `"mainland"` / `"overseas"` / `"global"`; omitted = not sent |
|
|
128
|
+
| `initial_env_vars` | `list[dict]` | No | Set env vars at creation time |
|
|
129
|
+
|
|
130
|
+
### `projects.list(**options)`
|
|
131
|
+
|
|
132
|
+
```python
|
|
133
|
+
page = makers.projects.list(
|
|
134
|
+
name="docs",
|
|
135
|
+
page=0,
|
|
136
|
+
page_size=20,
|
|
137
|
+
order={"field": "created_on", "direction": "desc"},
|
|
138
|
+
)
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
| Parameter | Type | Default | Description |
|
|
142
|
+
|-----------|------|---------|-------------|
|
|
143
|
+
| `project_ids` | `list[str]` | — | Filter by ID list |
|
|
144
|
+
| `name` | `str` | — | Filter by name |
|
|
145
|
+
| `status` | `str` | — | Filter by status |
|
|
146
|
+
| `provider` | `str` | — | Filter by provider |
|
|
147
|
+
| `page` | `int` | `0` | Zero-based page index |
|
|
148
|
+
| `page_size` | `int` | `20` | 1–100 |
|
|
149
|
+
| `order` | `dict` | — | `field`: `"created_on"` or `"modified_on"`; `direction`: `"asc"` or `"desc"` |
|
|
150
|
+
|
|
151
|
+
**Returns** `dict`: `{ "items", "page", "page_size", "total", "has_next" }`.
|
|
152
|
+
|
|
153
|
+
### `projects.list_all(**options)`
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
for project in makers.projects.list_all():
|
|
157
|
+
print(project["project_id"], project["name"])
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Same options as `list` except no `page`. Returns `Iterator[dict]`.
|
|
161
|
+
|
|
162
|
+
### `projects.get(*, project_id)`
|
|
163
|
+
|
|
164
|
+
Returns the full project dict. This is the only way to obtain `preset_domain`.
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
project = makers.projects.get(project_id=project_id)
|
|
168
|
+
print(project.get("preset_domain"))
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
### `projects.update(*, project_id, **fields)`
|
|
172
|
+
|
|
173
|
+
Updates project settings. Only provided fields are sent; omitted fields are not cleared.
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
makers.projects.update(
|
|
177
|
+
project_id=project_id,
|
|
178
|
+
name="new-name",
|
|
179
|
+
root_dir=".",
|
|
180
|
+
output_dir="dist",
|
|
181
|
+
build_cmd="npm run build",
|
|
182
|
+
install_cmd="npm install",
|
|
183
|
+
framework="other",
|
|
184
|
+
nodejs_version="20",
|
|
185
|
+
)
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
| Parameter | Type | Description |
|
|
189
|
+
|-----------|------|-------------|
|
|
190
|
+
| `project_id` | `str` | Required |
|
|
191
|
+
| `name` | `str` | Project name |
|
|
192
|
+
| `root_dir` | `str` | Root directory |
|
|
193
|
+
| `output_dir` | `str` | Output directory |
|
|
194
|
+
| `build_cmd` | `str` | Build command |
|
|
195
|
+
| `install_cmd` | `str` | Install command |
|
|
196
|
+
| `framework` | `str` | Framework identifier |
|
|
197
|
+
| `nodejs_version` | `str` | Node.js version |
|
|
198
|
+
|
|
199
|
+
### `projects.delete(*, project_id)`
|
|
200
|
+
|
|
201
|
+
Deletes a project. **Irreversible.**
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Environment variables
|
|
206
|
+
|
|
207
|
+
Methods live on `makers.projects`. Public fields: `key`, `value`, optional `comment`. Change project variables with `set_envs`; `deploy` does not accept env vars.
|
|
208
|
+
|
|
209
|
+
### `projects.list_envs(*, project_id)`
|
|
210
|
+
|
|
211
|
+
Returns `list[dict]`. Values are automatically added to the redaction list.
|
|
212
|
+
|
|
213
|
+
### `projects.set_envs(*, project_id, env_vars)`
|
|
214
|
+
|
|
215
|
+
Batch upsert. Internally reads existing vars first, then writes. Not atomic. Duplicate keys raise `ValidationError` before any network request.
|
|
216
|
+
|
|
217
|
+
```python
|
|
218
|
+
makers.projects.set_envs(
|
|
219
|
+
project_id=project_id,
|
|
220
|
+
env_vars=[
|
|
221
|
+
{"key": "API_URL", "value": "https://example.com", "comment": "origin"},
|
|
222
|
+
],
|
|
223
|
+
)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
### `projects.delete_envs(*, project_id, keys)`
|
|
227
|
+
|
|
228
|
+
Deletes env vars by key. Duplicate keys raise `ValidationError`.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Deployments
|
|
233
|
+
|
|
234
|
+
### `deployments.deploy(*, project_id, artifact, **options)`
|
|
235
|
+
|
|
236
|
+
Deploys an artifact. Accepts exactly one variant:
|
|
237
|
+
|
|
238
|
+
| Variant | Type | Behavior |
|
|
239
|
+
|---------|------|----------|
|
|
240
|
+
| `"files"` | `dict[str, str \| bytes]` | SDK zips in memory |
|
|
241
|
+
| `"directory"` | `str` (+ optional `"exclude_patterns": list[str]`) | SDK zips the directory |
|
|
242
|
+
| `"archive"` | `str` (zip file path) | Uploaded directly after safety validation |
|
|
243
|
+
|
|
244
|
+
```python
|
|
245
|
+
# Inline files
|
|
246
|
+
makers.deployments.deploy(
|
|
247
|
+
project_id=project_id,
|
|
248
|
+
artifact={"files": {"index.html": "<h1>ok</h1>"}},
|
|
249
|
+
wait=True,
|
|
250
|
+
)
|
|
251
|
+
|
|
252
|
+
# Application source (project root)
|
|
253
|
+
makers.deployments.deploy(
|
|
254
|
+
project_id=project_id,
|
|
255
|
+
artifact={"directory": "."},
|
|
256
|
+
wait=True,
|
|
257
|
+
)
|
|
258
|
+
|
|
259
|
+
# Static build output
|
|
260
|
+
makers.deployments.deploy(
|
|
261
|
+
project_id=project_id,
|
|
262
|
+
artifact={"directory": "./dist", "exclude_patterns": ["**/*.map"]},
|
|
263
|
+
)
|
|
264
|
+
|
|
265
|
+
# Prebuilt CLI output
|
|
266
|
+
makers.deployments.deploy(
|
|
267
|
+
project_id=project_id,
|
|
268
|
+
artifact={"directory": "./.edgeone"},
|
|
269
|
+
wait=True,
|
|
270
|
+
)
|
|
271
|
+
|
|
272
|
+
# Zip archive
|
|
273
|
+
makers.deployments.deploy(
|
|
274
|
+
project_id=project_id,
|
|
275
|
+
artifact={"archive": "./site.zip"},
|
|
276
|
+
)
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
| Parameter | Type | Default | Description |
|
|
280
|
+
|-----------|------|---------|-------------|
|
|
281
|
+
| `project_id` | `str` | — | Required |
|
|
282
|
+
| `artifact` | `dict` | — | Required; exactly one variant |
|
|
283
|
+
| `env` | `str` | `"Production"` | `"Preview"` requires an existing production deployment |
|
|
284
|
+
| `wait` | `bool` | `False` | Poll until terminal status |
|
|
285
|
+
| `timeout` | `float` | `900` | Max wait time in **seconds** (15 min) |
|
|
286
|
+
| `poll_interval` | `float` | `5` | Poll interval in **seconds** |
|
|
287
|
+
| `upload_progress` | callable | — | Fires once after upload completes |
|
|
288
|
+
| `status_change` | callable | — | Fires on each status transition |
|
|
289
|
+
|
|
290
|
+
**Returns** `dict`. With `wait=False`, only `deployment_id`, `project_id`, and `env` are populated — that is not an openable site URL. After `wait=True` reaches `Success`, `preview_url` is an openable link and **expires**.
|
|
291
|
+
|
|
292
|
+
**Note**: `timeout` here is the overall wait budget (default 900s), distinct from the per-request `Makers(timeout=30)`.
|
|
293
|
+
|
|
294
|
+
**Directory input**: pass one directory. Typical inputs are application source (project root), static build output (`index.html` must be at that directory root), or prebuilt Makers/SSR output (`./.edgeone` after a local CLI build). Application source is the usual SDK path: the SDK zips the tree with default ignores and uploads it. It does not compile locally and does not itself run `npm run build` or `edgeone makers build`. For Upload projects, Pages may then run `edgeone makers build`. The SDK does not run framework adapters. Default ignores are a fixed list; the SDK does not read `.gitignore`. A caller-provided `archive` is uploaded as-is.
|
|
295
|
+
|
|
296
|
+
**Directory safety**: rejects symlinks; ignores `.git`, `node_modules`, the artifact-root `.edgeone` directory, `.env`, logs, temp and system files. Non-`.edgeone` directories also ignore any path segment that starts with `.`; `.well-known` is kept. Nested `.edgeone` paths are kept. Passing a directory named `.edgeone` packs CLI layout (`<parent>/.edgeone/...`, plus sibling `edgeone.json` when present), keeps nested `node_modules`, and keeps hidden files. Other directories still drop `node_modules` at any depth. These defaults are a fixed list, not `.gitignore`. `exclude_patterns` appends POSIX globs; negation (`!`) is rejected.
|
|
297
|
+
|
|
298
|
+
### `deployments.wait(*, project_id, deployment_id, **options)`
|
|
299
|
+
|
|
300
|
+
Polls until a terminal status: `Success`, `Failed`, `Timeout`, `Cancelled`, or `Invalid`. After `Success`, `preview_url` is an openable site URL (signed for default upload projects) and **expires**. `get` / `list` / `wait=False` do not sign.
|
|
301
|
+
|
|
302
|
+
```python
|
|
303
|
+
result = makers.deployments.wait(
|
|
304
|
+
project_id=project_id,
|
|
305
|
+
deployment_id=deployment_id,
|
|
306
|
+
timeout=900,
|
|
307
|
+
poll_interval=5,
|
|
308
|
+
status_change=lambda e: print(e["deployment"].get("status")),
|
|
309
|
+
)
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
| Parameter | Type | Default | Description |
|
|
313
|
+
|-----------|------|---------|-------------|
|
|
314
|
+
| `project_id` | `str` | — | Required |
|
|
315
|
+
| `deployment_id` | `str` | — | Required |
|
|
316
|
+
| `timeout` | `float` | `900` | Raises `DeploymentTimeoutError` on expiry; **does not cancel the deployment** |
|
|
317
|
+
| `poll_interval` | `float` | `5` | |
|
|
318
|
+
| `status_change` | callable | — | |
|
|
319
|
+
|
|
320
|
+
### `deployments.list(*, project_id, **options)`
|
|
321
|
+
|
|
322
|
+
| Parameter | Type | Default | Description |
|
|
323
|
+
|-----------|------|---------|-------------|
|
|
324
|
+
| `project_id` | `str` | — | Required |
|
|
325
|
+
| `status` | `list[str]` | — | Filter by status |
|
|
326
|
+
| `time_range` | `dict` | — | `{"start": ..., "end": ...}` ISO 8601 |
|
|
327
|
+
| `repo_branch` | `list[str]` | — | Filter by branch |
|
|
328
|
+
| `page` | `int` | `0` | |
|
|
329
|
+
| `page_size` | `int` | `20` | |
|
|
330
|
+
| `order` | `dict` | — | |
|
|
331
|
+
|
|
332
|
+
### `deployments.list_all(*, project_id, **options)`
|
|
333
|
+
|
|
334
|
+
Same as `list` without `page`. Returns `Iterator[dict]`.
|
|
335
|
+
|
|
336
|
+
### `deployments.get(*, project_id, deployment_id)`
|
|
337
|
+
|
|
338
|
+
Returns a single deployment dict. Raises `NotFoundError` if not found.
|
|
339
|
+
|
|
340
|
+
### `deployments.get_log(*, project_id, deployment_id)`
|
|
341
|
+
|
|
342
|
+
Returns `{"log_url": ...}` — the build log URL.
|
|
343
|
+
|
|
344
|
+
---
|
|
345
|
+
|
|
346
|
+
## Data models
|
|
347
|
+
|
|
348
|
+
All values are plain `dict`. Optional fields may be absent — use `.get()` to access them.
|
|
349
|
+
|
|
350
|
+
### Project
|
|
351
|
+
|
|
352
|
+
| Field | Type | Always present | Description |
|
|
353
|
+
|-------|------|:--------------:|-------------|
|
|
354
|
+
| `project_id` | `str` | Yes | |
|
|
355
|
+
| `name` | `str` | Yes | Unique per account |
|
|
356
|
+
| `status` | `str` | Yes | |
|
|
357
|
+
| `area` | `str` | No | `"mainland"` / `"overseas"` / `"global"` |
|
|
358
|
+
| `preset_domain` | `str` | No | Production domain; may be absent for new projects |
|
|
359
|
+
| `created_on` | `str` | Yes | ISO 8601 |
|
|
360
|
+
| `modified_on` | `str` | Yes | ISO 8601 |
|
|
361
|
+
|
|
362
|
+
### Deployment
|
|
363
|
+
|
|
364
|
+
| Field | Type | Always present | Description |
|
|
365
|
+
|-------|------|:--------------:|-------------|
|
|
366
|
+
| `deployment_id` | `str` | Yes | |
|
|
367
|
+
| `project_id` | `str` | Yes | |
|
|
368
|
+
| `env` | `str` | Yes | `"Production"` or `"Preview"` |
|
|
369
|
+
| `status` | `str` | No | Terminal: `Success` / `Failed` / `Timeout` / `Cancelled` / `Invalid` |
|
|
370
|
+
| `preview_url` | `str` | No | After wait Success: openable site URL (expires). `get` / `wait=False` may expose the raw backend URL, which is not openable. |
|
|
371
|
+
| `code` | `str` | No | |
|
|
372
|
+
| `created_on` | `str` | No | Not returned with `wait=False` |
|
|
373
|
+
| `modified_on` | `str` | No | Not returned with `wait=False` |
|
|
374
|
+
|
|
375
|
+
### Token
|
|
376
|
+
|
|
377
|
+
| Field | Type | Always present | Description |
|
|
378
|
+
|-------|------|:--------------:|-------------|
|
|
379
|
+
| `token` | `str` | Yes | Tenant API token; use it to construct a user-side `Makers` |
|
|
380
|
+
| `token_id` | `str` | Yes | Token identifier |
|
|
381
|
+
| `expired` | `int` | Yes | Backend expiry time as unix seconds |
|
|
382
|
+
|
|
383
|
+
### EnvVar
|
|
384
|
+
|
|
385
|
+
| Field | Type | Always present |
|
|
386
|
+
|-------|------|:--------------:|
|
|
387
|
+
| `key` | `str` | Yes |
|
|
388
|
+
| `value` | `str` | Yes |
|
|
389
|
+
| `comment` | `str` | No |
|
|
390
|
+
|
|
391
|
+
### Callbacks
|
|
392
|
+
|
|
393
|
+
**upload_progress event**: `{"uploaded_bytes", "total_bytes", "completed_files", "total_files"}`
|
|
394
|
+
|
|
395
|
+
**status_change event**: `{"deployment": dict, "previous_status": str | None}`
|
|
396
|
+
|
|
397
|
+
---
|
|
398
|
+
|
|
399
|
+
## Errors
|
|
400
|
+
|
|
401
|
+
All errors extend `MakersError` with fields: `code`, `message`, `request_id`, `http_status`, `cause`.
|
|
402
|
+
|
|
403
|
+
| Error class | Trigger |
|
|
404
|
+
|-------------|---------|
|
|
405
|
+
| `AuthError` | Code 105 or HTTP 401 |
|
|
406
|
+
| `ValidationError` | Code contains "Invalid" or HTTP 400 |
|
|
407
|
+
| `NotFoundError` | Code contains "NotFound" or HTTP 404 |
|
|
408
|
+
| `ConflictError` | Code contains "Conflict" or HTTP 409 |
|
|
409
|
+
| `RateLimitError` | Code 110 or HTTP 429 |
|
|
410
|
+
| `UploadError` | COS upload failure |
|
|
411
|
+
| `TimeoutError` | Request timeout |
|
|
412
|
+
| `DeploymentTimeoutError` | Wait timeout (extends `TimeoutError`) |
|
|
413
|
+
|
|
414
|
+
```python
|
|
415
|
+
from makers_sdk import MakersError, NotFoundError, DeploymentTimeoutError
|
|
416
|
+
|
|
417
|
+
try:
|
|
418
|
+
makers.projects.get(project_id="missing")
|
|
419
|
+
except NotFoundError as error:
|
|
420
|
+
print(error.code, error.request_id, error.http_status)
|
|
421
|
+
except MakersError:
|
|
422
|
+
raise
|
|
423
|
+
```
|
|
424
|
+
|
|
425
|
+
### Retry behavior
|
|
426
|
+
|
|
427
|
+
Queries retry on network errors, HTTP 408/429/5xx, and outer `Code: 110`, up to `retries` times (default 3). Exponential backoff with full jitter, capped at 10 seconds. `Retry-After` header is respected when present. Creates, updates, and COS credential requests do not retry.
|
|
428
|
+
|
|
429
|
+
---
|
|
430
|
+
|
|
431
|
+
## Development
|
|
432
|
+
|
|
433
|
+
```sh
|
|
434
|
+
python -m pip install -e ".[test]"
|
|
435
|
+
python -m unittest discover -s tests -v
|
|
436
|
+
```
|