together-sandbox 1.11.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.
- together_sandbox-1.11.0/.gitignore +43 -0
- together_sandbox-1.11.0/CLAUDE.md +176 -0
- together_sandbox-1.11.0/PKG-INFO +227 -0
- together_sandbox-1.11.0/README.md +208 -0
- together_sandbox-1.11.0/generate.sh +25 -0
- together_sandbox-1.11.0/pyproject.toml +35 -0
- together_sandbox-1.11.0/tests/__init__.py +0 -0
- together_sandbox-1.11.0/tests/e2e/__init__.py +1 -0
- together_sandbox-1.11.0/tests/e2e/conftest.py +10 -0
- together_sandbox-1.11.0/tests/e2e/helpers.py +126 -0
- together_sandbox-1.11.0/tests/e2e/test_sandbox_execs.py +204 -0
- together_sandbox-1.11.0/tests/e2e/test_sandbox_filesystem.py +167 -0
- together_sandbox-1.11.0/tests/e2e/test_sandbox_lifecycle.py +51 -0
- together_sandbox-1.11.0/tests/e2e/test_snapshots.py +98 -0
- together_sandbox-1.11.0/tests/test_call_api.py +535 -0
- together_sandbox-1.11.0/tests/test_sse_streaming.py +89 -0
- together_sandbox-1.11.0/tests/test_utils.py +47 -0
- together_sandbox-1.11.0/tests/test_with_retry.py +262 -0
- together_sandbox-1.11.0/together_sandbox/__init__.py +60 -0
- together_sandbox-1.11.0/together_sandbox/_configuration.py +14 -0
- together_sandbox-1.11.0/together_sandbox/_lifecycle.py +144 -0
- together_sandbox-1.11.0/together_sandbox/_remote_image_builder.py +218 -0
- together_sandbox-1.11.0/together_sandbox/_sandbox.py +720 -0
- together_sandbox-1.11.0/together_sandbox/_sandboxes.py +179 -0
- together_sandbox-1.11.0/together_sandbox/_snapshots.py +509 -0
- together_sandbox-1.11.0/together_sandbox/_streaming.py +110 -0
- together_sandbox-1.11.0/together_sandbox/_together_sandbox.py +82 -0
- together_sandbox-1.11.0/together_sandbox/_utils.py +431 -0
- together_sandbox-1.11.0/together_sandbox/api/__init__.py +8 -0
- together_sandbox-1.11.0/together_sandbox/api/api/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/alias_snapshot.py +196 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/authorize.py +174 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/batch_get_sandboxes.py +183 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/batch_get_snapshots.py +187 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/create_sandbox.py +181 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/create_snapshot.py +181 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/delete_sandbox.py +174 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/delete_sandbox_version.py +175 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/delete_sandbox_version_by_number.py +188 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/delete_snapshot.py +175 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/delete_snapshot_alias.py +175 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/delete_snapshot_alias_by_alias.py +174 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/delete_snapshot_by_alias.py +174 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/get_current_sandbox_version.py +176 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/get_sandbox.py +176 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/get_sandbox_version.py +177 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/get_sandbox_version_by_number.py +190 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/get_snapshot.py +177 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/get_snapshot_alias.py +177 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/get_snapshot_alias_by_alias.py +176 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/get_snapshot_by_alias.py +176 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/issue_container_registry_credential.py +151 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/list_sandboxes.py +181 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/list_snapshots.py +181 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/start_sandbox.py +198 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/stop_sandbox.py +198 -0
- together_sandbox-1.11.0/together_sandbox/api/api/default/wait_for_sandbox.py +176 -0
- together_sandbox-1.11.0/together_sandbox/api/client.py +282 -0
- together_sandbox-1.11.0/together_sandbox/api/errors.py +16 -0
- together_sandbox-1.11.0/together_sandbox/api/models/__init__.py +67 -0
- together_sandbox-1.11.0/together_sandbox/api/models/alias_snapshot_body.py +61 -0
- together_sandbox-1.11.0/together_sandbox/api/models/authorize_body.py +62 -0
- together_sandbox-1.11.0/together_sandbox/api/models/container_registry_credential.py +104 -0
- together_sandbox-1.11.0/together_sandbox/api/models/create_sandbox_body.py +123 -0
- together_sandbox-1.11.0/together_sandbox/api/models/create_snapshot_body.py +81 -0
- together_sandbox-1.11.0/together_sandbox/api/models/create_snapshot_body_architecture.py +9 -0
- together_sandbox-1.11.0/together_sandbox/api/models/error.py +91 -0
- together_sandbox-1.11.0/together_sandbox/api/models/error_errors_item.py +101 -0
- together_sandbox-1.11.0/together_sandbox/api/models/error_errors_item_details.py +47 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox.py +656 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_recovery_status_type_1.py +11 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_recovery_status_type_2_type_1.py +11 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_recovery_status_type_3_type_1.py +11 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_requested_stop_type_type_1.py +9 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_requested_stop_type_type_2_type_1.py +9 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_requested_stop_type_type_3_type_1.py +9 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_start_type_type_1.py +9 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_start_type_type_2_type_1.py +9 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_start_type_type_3_type_1.py +9 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_status.py +12 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_stop_reason_type_1.py +15 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_stop_reason_type_2_type_1.py +15 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_stop_reason_type_3_type_1.py +15 -0
- together_sandbox-1.11.0/together_sandbox/api/models/sandbox_version.py +96 -0
- together_sandbox-1.11.0/together_sandbox/api/models/snapshot.py +145 -0
- together_sandbox-1.11.0/together_sandbox/api/models/snapshot_alias.py +96 -0
- together_sandbox-1.11.0/together_sandbox/api/models/start_sandbox_body.py +61 -0
- together_sandbox-1.11.0/together_sandbox/api/models/stop_sandbox_body.py +69 -0
- together_sandbox-1.11.0/together_sandbox/api/models/stop_sandbox_body_stop_type.py +9 -0
- together_sandbox-1.11.0/together_sandbox/api/types.py +54 -0
- together_sandbox-1.11.0/together_sandbox/docker.py +172 -0
- together_sandbox-1.11.0/together_sandbox/errors.py +53 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/__init__.py +8 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/directories/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/directories/create_directory.py +177 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/directories/delete_directory.py +182 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/directories/list_directory.py +177 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/connect_to_exec_web_socket.py +212 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/create_exec.py +182 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/delete_exec.py +177 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/exec_exec_stdin.py +203 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/get_exec.py +177 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/get_exec_output.py +203 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/list_execs.py +140 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/start_exec.py +222 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/stream_exec_output.py +198 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/execs/stream_execs_list.py +140 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/files/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/files/create_file.py +197 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/files/delete_file.py +182 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/files/get_file_stat.py +177 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/files/perform_file_action.py +198 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/files/read_file.py +177 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/ports/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/ports/list_ports.py +145 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/ports/stream_ports_list.py +149 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/streams/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/streams/create_watcher.py +217 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/tasks/__init__.py +1 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/tasks/execute_task_action.py +210 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/tasks/get_task.py +177 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/tasks/list_setup_tasks.py +144 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/api/tasks/list_tasks.py +140 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/client.py +282 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/errors.py +16 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/__init__.py +77 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/create_exec_request.py +134 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/create_exec_request_env.py +47 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/directory_list_response.py +83 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/error.py +69 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/exec_delete_response.py +61 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/exec_item.py +121 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/exec_list_response.py +75 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/exec_start.py +50 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/exec_stdin.py +71 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/exec_stdin_type.py +9 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/exec_stdout.py +107 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/exec_stdout_type.py +9 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/file_action_request.py +81 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/file_action_request_action.py +9 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/file_action_response.py +77 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/file_create_request.py +61 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/file_info.py +93 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/file_operation_response.py +69 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/file_read_response.py +79 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/file_read_response_encoding.py +9 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/get_task_response.py +67 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/port_info.py +69 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/ports_list_response.py +75 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/setup_task_item.py +103 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/setup_task_list_response.py +75 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_action_response.py +120 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_action_type.py +10 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_base.py +88 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_config.py +101 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_item.py +109 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_list_response.py +75 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_preview.py +61 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_restart.py +85 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/task_status.py +13 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/watcher_event.py +81 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/models/watcher_event_type.py +12 -0
- together_sandbox-1.11.0/together_sandbox/sandbox/types.py +54 -0
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# Generated code
|
|
2
|
+
together-sandbox-typescript/src/api-clients
|
|
3
|
+
together-sandbox-cli/src/api-clients
|
|
4
|
+
|
|
5
|
+
# Node
|
|
6
|
+
node_modules/
|
|
7
|
+
npm-debug.log*
|
|
8
|
+
test-template
|
|
9
|
+
|
|
10
|
+
# TypeScript SDK build output
|
|
11
|
+
together-sandbox-typescript/dist/
|
|
12
|
+
|
|
13
|
+
# CLI build output (esbuild bundle + compiled binaries)
|
|
14
|
+
together-sandbox-cli/dist/
|
|
15
|
+
|
|
16
|
+
# Python
|
|
17
|
+
__pycache__/
|
|
18
|
+
*.py[cod]
|
|
19
|
+
*.egg-info/
|
|
20
|
+
.eggs/
|
|
21
|
+
dist/
|
|
22
|
+
build/
|
|
23
|
+
.venv/
|
|
24
|
+
venv/
|
|
25
|
+
*.pth
|
|
26
|
+
|
|
27
|
+
# static docs
|
|
28
|
+
api-docs/*.json
|
|
29
|
+
|
|
30
|
+
# Python generation temp dirs
|
|
31
|
+
together-sandbox-python/.tmp-api/
|
|
32
|
+
together-sandbox-python/.tmp-sandbox/
|
|
33
|
+
|
|
34
|
+
# Test scripts
|
|
35
|
+
together-sandbox-typescript/test.ts
|
|
36
|
+
together-sandbox-python/test.py
|
|
37
|
+
|
|
38
|
+
# OS
|
|
39
|
+
.DS_Store
|
|
40
|
+
|
|
41
|
+
# Local env files
|
|
42
|
+
.env
|
|
43
|
+
.env.local
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
# Python SDK — Developer Guide
|
|
2
|
+
|
|
3
|
+
Package: `together-sandbox` (PyPI)
|
|
4
|
+
|
|
5
|
+
## File layout
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
together_sandbox/
|
|
9
|
+
├── __init__.py # Public re-exports — keep in sync with facade.py exports
|
|
10
|
+
├── facade.py # ← hand-written facade (the only file to edit)
|
|
11
|
+
├── _streaming.py # SSE streaming helpers — hand-written
|
|
12
|
+
├── api/ # Generated — management API client (openapi-python-client)
|
|
13
|
+
└── sandbox/ # Generated — in-VM sandbox API client (openapi-python-client)
|
|
14
|
+
```
|
|
15
|
+
|
|
16
|
+
**Only `facade.py`, `_streaming.py`, and `__init__.py` are hand-edited.**
|
|
17
|
+
Everything inside `api/` and `sandbox/` is regenerated by `bash generate.sh`
|
|
18
|
+
(run from the repo root) and must not be modified directly.
|
|
19
|
+
|
|
20
|
+
## Facade patterns
|
|
21
|
+
|
|
22
|
+
### Always `from __future__ import annotations`
|
|
23
|
+
|
|
24
|
+
Every facade Python file must start with `from __future__ import annotations`.
|
|
25
|
+
This enables PEP 563 deferred evaluation so modern union syntax works on all
|
|
26
|
+
supported Python versions (≥3.10).
|
|
27
|
+
|
|
28
|
+
### Modern type annotation style
|
|
29
|
+
|
|
30
|
+
Use `X | None` instead of `Optional[X]`, and `list[X]` instead of `List[X]`.
|
|
31
|
+
Do **not** import `Optional` or `List` from `typing`.
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
# ✅ correct
|
|
35
|
+
def watch(self, path: str, recursive: bool | None = None) -> AsyncIterator[dict[str, Any]]: ...
|
|
36
|
+
|
|
37
|
+
# ❌ wrong — legacy typing imports
|
|
38
|
+
from typing import Optional, List
|
|
39
|
+
def watch(self, path: str, recursive: Optional[bool] = None) -> AsyncIterator[List[dict]]: ...
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### All method names must be snake_case
|
|
43
|
+
|
|
44
|
+
Python method names follow PEP 8. Do not use camelCase even if the equivalent
|
|
45
|
+
TypeScript method is camelCase.
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
# ✅ correct
|
|
49
|
+
async def list_setup(self) -> list[...]: ...
|
|
50
|
+
|
|
51
|
+
# ❌ wrong — camelCase in Python
|
|
52
|
+
async def listSetup(self) -> list[...]: ...
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
### Always return unwrapped data
|
|
56
|
+
|
|
57
|
+
Facade methods return the actual payload value, not the raw response object:
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
# ✅ correct
|
|
61
|
+
result = await read_file_api(path, client=self._client)
|
|
62
|
+
return result.content
|
|
63
|
+
|
|
64
|
+
# ❌ wrong — returns the full response object
|
|
65
|
+
return result
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
### Use typed models for API request bodies
|
|
69
|
+
|
|
70
|
+
Never pass raw `dict` literals as request bodies. Use the typed models
|
|
71
|
+
generated in the `api/` and `sandbox/` packages.
|
|
72
|
+
|
|
73
|
+
```python
|
|
74
|
+
# ✅ correct (when a typed body model exists)
|
|
75
|
+
await stop_sandbox_api(sandbox_id, client=self._api_client,
|
|
76
|
+
body=StopSandboxBody(stop_type="hibernate"))
|
|
77
|
+
|
|
78
|
+
# ❌ wrong — raw dict
|
|
79
|
+
await stop_sandbox_api(sandbox_id, client=self._api_client,
|
|
80
|
+
body={"stop_type": "hibernate"})
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### File uploads use `File(payload=io.BytesIO(bytes))` only
|
|
84
|
+
|
|
85
|
+
String content must be encoded to bytes before wrapping in a `File` object.
|
|
86
|
+
Never pass raw strings to `create_file_api`.
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
if isinstance(content, str):
|
|
90
|
+
content_bytes = content.encode("utf-8")
|
|
91
|
+
else:
|
|
92
|
+
content_bytes = content
|
|
93
|
+
file_obj = File(payload=io.BytesIO(content_bytes))
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
Import `io` at the **top of the module**, not inside the method body.
|
|
97
|
+
|
|
98
|
+
### Do not use `assert` for runtime type checking
|
|
99
|
+
|
|
100
|
+
`assert` statements are stripped in optimised Python (`python -O`). Raise
|
|
101
|
+
explicit exceptions instead.
|
|
102
|
+
|
|
103
|
+
```python
|
|
104
|
+
# ✅ correct
|
|
105
|
+
result = await get_exec_api(id_, client=self._client)
|
|
106
|
+
if result is None:
|
|
107
|
+
raise RuntimeError(f"getExec returned None for id {id_!r}")
|
|
108
|
+
return result
|
|
109
|
+
|
|
110
|
+
# ❌ wrong
|
|
111
|
+
result = await get_exec_api(id_, client=self._client)
|
|
112
|
+
assert result is not None
|
|
113
|
+
return result
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
### Async context manager support
|
|
117
|
+
|
|
118
|
+
Both `TogetherSandbox` and `Sandbox` must support `async with`. The context
|
|
119
|
+
manager closes the HTTP client connection but does **not** shut down the VM —
|
|
120
|
+
callers must call `.shutdown()` explicitly.
|
|
121
|
+
|
|
122
|
+
### Always unwrap API responses with `_unwrap_or_raise`
|
|
123
|
+
|
|
124
|
+
Every call to a generated API endpoint function must have its return value
|
|
125
|
+
checked through `_unwrap_or_raise` — never check `None`/`Error` inline.
|
|
126
|
+
Import the helper from `._utils`, not from `._sandbox`.
|
|
127
|
+
|
|
128
|
+
Even void-returning endpoints (delete, stop, alias) must capture and unwrap
|
|
129
|
+
their result — the generated clients can return an `Error` model on failure.
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
# ✅ correct
|
|
133
|
+
_unwrap_or_raise(
|
|
134
|
+
await delete_snapshot_api(UUID(id), client=self._api_client),
|
|
135
|
+
op="deleteSnapshot",
|
|
136
|
+
context=f"for id {id!r}"
|
|
137
|
+
)
|
|
138
|
+
|
|
139
|
+
# ❌ wrong — inline check, misses Error model, inconsistent
|
|
140
|
+
result = await delete_snapshot_api(UUID(id), client=self._api_client)
|
|
141
|
+
if result is None:
|
|
142
|
+
raise RuntimeError("deleteSnapshot returned None")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Section dividers
|
|
146
|
+
|
|
147
|
+
Use the established ASCII box-drawing style:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
# ─── Section Name ─────────────────────────────────────────────────────────────
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
## Build and test
|
|
154
|
+
|
|
155
|
+
```bash
|
|
156
|
+
# From repo root — regenerate generated clients first
|
|
157
|
+
bash generate.sh
|
|
158
|
+
|
|
159
|
+
# Install package with dev extras
|
|
160
|
+
cd together-sandbox-python
|
|
161
|
+
pip install ".[dev]"
|
|
162
|
+
|
|
163
|
+
# Run tests
|
|
164
|
+
pytest tests/ -v
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
## Testing conventions
|
|
168
|
+
|
|
169
|
+
- Tests live in `together-sandbox-python/tests/`.
|
|
170
|
+
- Use `pytest` with `asyncio_mode = "auto"` (set in `pyproject.toml`).
|
|
171
|
+
- Use `unittest.mock.AsyncMock` + `patch` for API call mocking.
|
|
172
|
+
- Use class-based test organisation (`class TestFoo:`).
|
|
173
|
+
- The `_make_sandbox_model(**overrides)` helper pattern (see `test_facade.py`)
|
|
174
|
+
should be used to build minimal valid fixture `SandboxModel` mocks.
|
|
175
|
+
- Mirror the TypeScript SDK's test coverage: verify namespace delegation,
|
|
176
|
+
renamed/removed methods, public API surface, and factory classmethods.
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: together-sandbox
|
|
3
|
+
Version: 1.11.0
|
|
4
|
+
Summary: Together Sandbox Python SDK
|
|
5
|
+
License: MIT
|
|
6
|
+
Requires-Python: >=3.10
|
|
7
|
+
Requires-Dist: attrs>=23.0.0
|
|
8
|
+
Requires-Dist: cattrs>=23.0.0
|
|
9
|
+
Requires-Dist: httpx-sse>=0.4.0
|
|
10
|
+
Requires-Dist: httpx>=0.20.0
|
|
11
|
+
Requires-Dist: pathspec>=0.11.0
|
|
12
|
+
Requires-Dist: python-dateutil>=2.8.0
|
|
13
|
+
Provides-Extra: dev
|
|
14
|
+
Requires-Dist: openapi-python-client>=0.28.0; extra == 'dev'
|
|
15
|
+
Requires-Dist: pytest-asyncio>=0.21.0; extra == 'dev'
|
|
16
|
+
Requires-Dist: pytest-timeout>=2.0.0; extra == 'dev'
|
|
17
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
18
|
+
Description-Content-Type: text/markdown
|
|
19
|
+
|
|
20
|
+
# together-sandbox (Python)
|
|
21
|
+
|
|
22
|
+
Developer guide for the `together-sandbox` Python SDK.
|
|
23
|
+
|
|
24
|
+
[SDK Docs](../docs/python-sdk.md)
|
|
25
|
+
|
|
26
|
+
> **Note:** The generated OpenAPI clients (`together_sandbox/api/` and
|
|
27
|
+
> `together_sandbox/sandbox/`) are committed to the repository temporarily until
|
|
28
|
+
> the package is published to PyPI. Once published they will be removed from
|
|
29
|
+
> version control and regenerated as part of the install/build step instead.
|
|
30
|
+
|
|
31
|
+
## Generating the OpenAPI clients
|
|
32
|
+
|
|
33
|
+
The SDK wraps two auto-generated OpenAPI clients. Regenerate them whenever an
|
|
34
|
+
OpenAPI spec changes (both specs live in the repo root):
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
# From the repo root
|
|
38
|
+
bash generate.sh
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
This runs `together-sandbox-python/generate.sh` which invokes
|
|
42
|
+
`openapi-python-client` against `api-openapi.json` and `sandbox-openapi.json`
|
|
43
|
+
and writes the output to:
|
|
44
|
+
|
|
45
|
+
- `together_sandbox/api/` — management API client
|
|
46
|
+
- `together_sandbox/sandbox/` — in-VM sandbox API client
|
|
47
|
+
|
|
48
|
+
**Never edit those directories by hand** — they are overwritten on every run.
|
|
49
|
+
|
|
50
|
+
## Tests
|
|
51
|
+
|
|
52
|
+
## Prerequisites
|
|
53
|
+
|
|
54
|
+
1. Together AI API key
|
|
55
|
+
2. Python 3.10 or higher
|
|
56
|
+
3. Install dev dependencies:
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
cd together-sandbox-python
|
|
60
|
+
pip install .[dev]
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
4. Set up a virtual environment (optional but recommended):
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
python -m venv .venv
|
|
67
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
5. Create a snapshot to run the tests with
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
node ./together-sandbox-cli/dist/together-sandbox.mjs snapshots create --context ./test-template
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Environment Variables
|
|
77
|
+
|
|
78
|
+
Set the following environment variables before running e2e tests:
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
# Required
|
|
82
|
+
export TOGETHER_API_KEY="your-api-key-here"
|
|
83
|
+
|
|
84
|
+
# Optional
|
|
85
|
+
export TOGETHER_SNAPSHOT_ID="snapshot-id" # If you want to test with a specific snapshot
|
|
86
|
+
export TOGETHER_BASE_URL="https://api.codesandbox.io" # Override default base URL
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Running Tests
|
|
90
|
+
|
|
91
|
+
**Note:** All `pytest` commands must be run from the `together-sandbox-python/` directory.
|
|
92
|
+
|
|
93
|
+
### Unit tests
|
|
94
|
+
|
|
95
|
+
```bash
|
|
96
|
+
pytest tests/ -v
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### Run all e2e tests
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
pytest tests/e2e/ -v
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Run specific e2e test file
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pytest tests/e2e/test_sandbox_filesystem.py -v
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### Run specific test class or function
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
# Run a specific test class
|
|
115
|
+
pytest tests/e2e/test_sandbox_filesystem.py::TestSandboxFilesystem -v
|
|
116
|
+
|
|
117
|
+
# Run a specific test function
|
|
118
|
+
pytest tests/e2e/test_sandbox_filesystem.py::TestSandboxFilesystem::test_write_and_read_text_file -v
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
### Run with output from print statements
|
|
122
|
+
|
|
123
|
+
```bash
|
|
124
|
+
pytest tests/e2e/ -v -s
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
## Test Structure
|
|
128
|
+
|
|
129
|
+
### Fixtures (e2e/helpers.py)
|
|
130
|
+
|
|
131
|
+
The `helpers.py` module provides pytest fixtures that handle sandbox lifecycle:
|
|
132
|
+
|
|
133
|
+
- `sdk`: Provides a configured `TogetherSandbox` instance
|
|
134
|
+
- `sandbox`: Creates a sandbox instance and automatically cleans it up after tests
|
|
135
|
+
- `retry_until`: Helper function for polling operations
|
|
136
|
+
|
|
137
|
+
Example usage in tests:
|
|
138
|
+
|
|
139
|
+
```python
|
|
140
|
+
@pytest.mark.asyncio
|
|
141
|
+
async def test_something(sandbox: Sandbox):
|
|
142
|
+
# sandbox is automatically created and will be cleaned up
|
|
143
|
+
await sandbox.files.create_file("/test.txt", "content")
|
|
144
|
+
result = await sandbox.files.read_file("/test.txt")
|
|
145
|
+
assert result.content == "content"
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
## Test Patterns
|
|
149
|
+
|
|
150
|
+
### Using the sandbox fixture
|
|
151
|
+
|
|
152
|
+
Most tests should use the `sandbox` fixture which handles creation and cleanup:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
async def test_my_feature(sandbox: Sandbox):
|
|
156
|
+
# Your test code here
|
|
157
|
+
# Sandbox will be automatically cleaned up
|
|
158
|
+
pass
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Manual sandbox management
|
|
162
|
+
|
|
163
|
+
For lifecycle tests that need explicit control:
|
|
164
|
+
|
|
165
|
+
```python
|
|
166
|
+
async def test_lifecycle():
|
|
167
|
+
sdk = TogetherSandbox(api_key=get_api_key())
|
|
168
|
+
try:
|
|
169
|
+
sandbox = await sdk.sandboxes.start(template_id)
|
|
170
|
+
# Test code
|
|
171
|
+
finally:
|
|
172
|
+
await sdk.sandboxes.shutdown(sandbox.id)
|
|
173
|
+
await sdk.close()
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Retry polling pattern
|
|
177
|
+
|
|
178
|
+
For operations that may take time:
|
|
179
|
+
|
|
180
|
+
```python
|
|
181
|
+
from .helpers import retry_until
|
|
182
|
+
|
|
183
|
+
result = await retry_until(
|
|
184
|
+
lambda: sandbox.files.read_file("/path"),
|
|
185
|
+
lambda r: r.content == "expected",
|
|
186
|
+
timeout=5.0,
|
|
187
|
+
interval=0.1
|
|
188
|
+
)
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Notes
|
|
192
|
+
|
|
193
|
+
- E2E tests connect to real sandbox instances and may incur API costs
|
|
194
|
+
- Tests automatically clean up sandboxes, but interrupted tests may leave orphaned sandboxes
|
|
195
|
+
- Some exec tests are placeholders and may need implementation based on the actual API structure
|
|
196
|
+
- Binary file tests verify the application/octet-stream content type handling
|
|
197
|
+
- Timeout for sandbox cleanup is set to 10 seconds to prevent hanging
|
|
198
|
+
|
|
199
|
+
## Troubleshooting
|
|
200
|
+
|
|
201
|
+
### Tests skip with "TOGETHER_API_KEY environment variable not set"
|
|
202
|
+
|
|
203
|
+
Make sure you've exported the `TOGETHER_API_KEY` environment variable:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
export TOGETHER_API_KEY="your-api-key"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Tests fail with timeout errors
|
|
210
|
+
|
|
211
|
+
The sandbox may be taking longer to start or respond. You can:
|
|
212
|
+
|
|
213
|
+
1. Check your network connection
|
|
214
|
+
2. Verify the API service status
|
|
215
|
+
3. Increase timeout values in the tests if needed
|
|
216
|
+
|
|
217
|
+
### Tests fail with authentication errors
|
|
218
|
+
|
|
219
|
+
Verify your API key is valid and has the necessary permissions for:
|
|
220
|
+
|
|
221
|
+
- Creating sandboxes
|
|
222
|
+
- Reading/writing files
|
|
223
|
+
- Managing sandbox lifecycle
|
|
224
|
+
|
|
225
|
+
### Orphaned sandboxes
|
|
226
|
+
|
|
227
|
+
If tests are interrupted, sandboxes may not be cleaned up. You can manually delete them using the API or wait for automatic cleanup policies.
|
|
@@ -0,0 +1,208 @@
|
|
|
1
|
+
# together-sandbox (Python)
|
|
2
|
+
|
|
3
|
+
Developer guide for the `together-sandbox` Python SDK.
|
|
4
|
+
|
|
5
|
+
[SDK Docs](../docs/python-sdk.md)
|
|
6
|
+
|
|
7
|
+
> **Note:** The generated OpenAPI clients (`together_sandbox/api/` and
|
|
8
|
+
> `together_sandbox/sandbox/`) are committed to the repository temporarily until
|
|
9
|
+
> the package is published to PyPI. Once published they will be removed from
|
|
10
|
+
> version control and regenerated as part of the install/build step instead.
|
|
11
|
+
|
|
12
|
+
## Generating the OpenAPI clients
|
|
13
|
+
|
|
14
|
+
The SDK wraps two auto-generated OpenAPI clients. Regenerate them whenever an
|
|
15
|
+
OpenAPI spec changes (both specs live in the repo root):
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# From the repo root
|
|
19
|
+
bash generate.sh
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
This runs `together-sandbox-python/generate.sh` which invokes
|
|
23
|
+
`openapi-python-client` against `api-openapi.json` and `sandbox-openapi.json`
|
|
24
|
+
and writes the output to:
|
|
25
|
+
|
|
26
|
+
- `together_sandbox/api/` — management API client
|
|
27
|
+
- `together_sandbox/sandbox/` — in-VM sandbox API client
|
|
28
|
+
|
|
29
|
+
**Never edit those directories by hand** — they are overwritten on every run.
|
|
30
|
+
|
|
31
|
+
## Tests
|
|
32
|
+
|
|
33
|
+
## Prerequisites
|
|
34
|
+
|
|
35
|
+
1. Together AI API key
|
|
36
|
+
2. Python 3.10 or higher
|
|
37
|
+
3. Install dev dependencies:
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
cd together-sandbox-python
|
|
41
|
+
pip install .[dev]
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
4. Set up a virtual environment (optional but recommended):
|
|
45
|
+
|
|
46
|
+
```bash
|
|
47
|
+
python -m venv .venv
|
|
48
|
+
source .venv/bin/activate # On Windows: .venv\Scripts\activate
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
5. Create a snapshot to run the tests with
|
|
52
|
+
|
|
53
|
+
```bash
|
|
54
|
+
node ./together-sandbox-cli/dist/together-sandbox.mjs snapshots create --context ./test-template
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Environment Variables
|
|
58
|
+
|
|
59
|
+
Set the following environment variables before running e2e tests:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
# Required
|
|
63
|
+
export TOGETHER_API_KEY="your-api-key-here"
|
|
64
|
+
|
|
65
|
+
# Optional
|
|
66
|
+
export TOGETHER_SNAPSHOT_ID="snapshot-id" # If you want to test with a specific snapshot
|
|
67
|
+
export TOGETHER_BASE_URL="https://api.codesandbox.io" # Override default base URL
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Running Tests
|
|
71
|
+
|
|
72
|
+
**Note:** All `pytest` commands must be run from the `together-sandbox-python/` directory.
|
|
73
|
+
|
|
74
|
+
### Unit tests
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
pytest tests/ -v
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### Run all e2e tests
|
|
81
|
+
|
|
82
|
+
```bash
|
|
83
|
+
pytest tests/e2e/ -v
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Run specific e2e test file
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
pytest tests/e2e/test_sandbox_filesystem.py -v
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
### Run specific test class or function
|
|
93
|
+
|
|
94
|
+
```bash
|
|
95
|
+
# Run a specific test class
|
|
96
|
+
pytest tests/e2e/test_sandbox_filesystem.py::TestSandboxFilesystem -v
|
|
97
|
+
|
|
98
|
+
# Run a specific test function
|
|
99
|
+
pytest tests/e2e/test_sandbox_filesystem.py::TestSandboxFilesystem::test_write_and_read_text_file -v
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### Run with output from print statements
|
|
103
|
+
|
|
104
|
+
```bash
|
|
105
|
+
pytest tests/e2e/ -v -s
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## Test Structure
|
|
109
|
+
|
|
110
|
+
### Fixtures (e2e/helpers.py)
|
|
111
|
+
|
|
112
|
+
The `helpers.py` module provides pytest fixtures that handle sandbox lifecycle:
|
|
113
|
+
|
|
114
|
+
- `sdk`: Provides a configured `TogetherSandbox` instance
|
|
115
|
+
- `sandbox`: Creates a sandbox instance and automatically cleans it up after tests
|
|
116
|
+
- `retry_until`: Helper function for polling operations
|
|
117
|
+
|
|
118
|
+
Example usage in tests:
|
|
119
|
+
|
|
120
|
+
```python
|
|
121
|
+
@pytest.mark.asyncio
|
|
122
|
+
async def test_something(sandbox: Sandbox):
|
|
123
|
+
# sandbox is automatically created and will be cleaned up
|
|
124
|
+
await sandbox.files.create_file("/test.txt", "content")
|
|
125
|
+
result = await sandbox.files.read_file("/test.txt")
|
|
126
|
+
assert result.content == "content"
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
## Test Patterns
|
|
130
|
+
|
|
131
|
+
### Using the sandbox fixture
|
|
132
|
+
|
|
133
|
+
Most tests should use the `sandbox` fixture which handles creation and cleanup:
|
|
134
|
+
|
|
135
|
+
```python
|
|
136
|
+
async def test_my_feature(sandbox: Sandbox):
|
|
137
|
+
# Your test code here
|
|
138
|
+
# Sandbox will be automatically cleaned up
|
|
139
|
+
pass
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
### Manual sandbox management
|
|
143
|
+
|
|
144
|
+
For lifecycle tests that need explicit control:
|
|
145
|
+
|
|
146
|
+
```python
|
|
147
|
+
async def test_lifecycle():
|
|
148
|
+
sdk = TogetherSandbox(api_key=get_api_key())
|
|
149
|
+
try:
|
|
150
|
+
sandbox = await sdk.sandboxes.start(template_id)
|
|
151
|
+
# Test code
|
|
152
|
+
finally:
|
|
153
|
+
await sdk.sandboxes.shutdown(sandbox.id)
|
|
154
|
+
await sdk.close()
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### Retry polling pattern
|
|
158
|
+
|
|
159
|
+
For operations that may take time:
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
from .helpers import retry_until
|
|
163
|
+
|
|
164
|
+
result = await retry_until(
|
|
165
|
+
lambda: sandbox.files.read_file("/path"),
|
|
166
|
+
lambda r: r.content == "expected",
|
|
167
|
+
timeout=5.0,
|
|
168
|
+
interval=0.1
|
|
169
|
+
)
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
## Notes
|
|
173
|
+
|
|
174
|
+
- E2E tests connect to real sandbox instances and may incur API costs
|
|
175
|
+
- Tests automatically clean up sandboxes, but interrupted tests may leave orphaned sandboxes
|
|
176
|
+
- Some exec tests are placeholders and may need implementation based on the actual API structure
|
|
177
|
+
- Binary file tests verify the application/octet-stream content type handling
|
|
178
|
+
- Timeout for sandbox cleanup is set to 10 seconds to prevent hanging
|
|
179
|
+
|
|
180
|
+
## Troubleshooting
|
|
181
|
+
|
|
182
|
+
### Tests skip with "TOGETHER_API_KEY environment variable not set"
|
|
183
|
+
|
|
184
|
+
Make sure you've exported the `TOGETHER_API_KEY` environment variable:
|
|
185
|
+
|
|
186
|
+
```bash
|
|
187
|
+
export TOGETHER_API_KEY="your-api-key"
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### Tests fail with timeout errors
|
|
191
|
+
|
|
192
|
+
The sandbox may be taking longer to start or respond. You can:
|
|
193
|
+
|
|
194
|
+
1. Check your network connection
|
|
195
|
+
2. Verify the API service status
|
|
196
|
+
3. Increase timeout values in the tests if needed
|
|
197
|
+
|
|
198
|
+
### Tests fail with authentication errors
|
|
199
|
+
|
|
200
|
+
Verify your API key is valid and has the necessary permissions for:
|
|
201
|
+
|
|
202
|
+
- Creating sandboxes
|
|
203
|
+
- Reading/writing files
|
|
204
|
+
- Managing sandbox lifecycle
|
|
205
|
+
|
|
206
|
+
### Orphaned sandboxes
|
|
207
|
+
|
|
208
|
+
If tests are interrupted, sandboxes may not be cleaned up. You can manually delete them using the API or wait for automatic cleanup policies.
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Regenerate both OpenAPI clients from the specs in the parent directory.
|
|
3
|
+
# Run from the repo root: bash together-sandbox-python/generate.sh
|
|
4
|
+
set -e
|
|
5
|
+
|
|
6
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
7
|
+
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
8
|
+
|
|
9
|
+
mkdir -p "$SCRIPT_DIR/together_sandbox"
|
|
10
|
+
|
|
11
|
+
echo "Generating API client from api-openapi.json..."
|
|
12
|
+
python3 -m openapi_python_client generate \
|
|
13
|
+
--path "$REPO_ROOT/api-openapi.json" \
|
|
14
|
+
--meta none \
|
|
15
|
+
--output-path "$SCRIPT_DIR/together_sandbox/api" \
|
|
16
|
+
--overwrite
|
|
17
|
+
|
|
18
|
+
echo "Generating Sandbox client from sandbox-openapi.json..."
|
|
19
|
+
python3 -m openapi_python_client generate \
|
|
20
|
+
--path "$REPO_ROOT/sandbox-openapi.json" \
|
|
21
|
+
--meta none \
|
|
22
|
+
--output-path "$SCRIPT_DIR/together_sandbox/sandbox" \
|
|
23
|
+
--overwrite
|
|
24
|
+
|
|
25
|
+
echo "Done. Both clients available via: from together_sandbox import ApiClient, SandboxClient"
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "together-sandbox"
|
|
7
|
+
version = "1.11.0"
|
|
8
|
+
description = "Together Sandbox Python SDK"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"httpx>=0.20.0",
|
|
13
|
+
"httpx-sse>=0.4.0",
|
|
14
|
+
"cattrs>=23.0.0",
|
|
15
|
+
"attrs>=23.0.0",
|
|
16
|
+
"python-dateutil>=2.8.0",
|
|
17
|
+
"pathspec>=0.11.0",
|
|
18
|
+
]
|
|
19
|
+
license = { text = "MIT" }
|
|
20
|
+
|
|
21
|
+
[project.optional-dependencies]
|
|
22
|
+
dev = [
|
|
23
|
+
"openapi-python-client>=0.28.0",
|
|
24
|
+
"pytest>=7.0.0",
|
|
25
|
+
"pytest-asyncio>=0.21.0",
|
|
26
|
+
"pytest-timeout>=2.0.0",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
[tool.hatch.build.targets.wheel]
|
|
30
|
+
packages = ["together_sandbox"]
|
|
31
|
+
|
|
32
|
+
[tool.pytest.ini_options]
|
|
33
|
+
asyncio_mode = "auto"
|
|
34
|
+
markers = ["e2e: end-to-end tests that require TOGETHER_API_KEY"]
|
|
35
|
+
norecursedirs = ["e2e"]
|