Metadata-Version: 2.5
Name: gmi-sandbox-sdk
Version: 0.2.0b3
Summary: GMI Sandbox SDK for Python.
Project-URL: Homepage, https://www.gmicloud.ai/
Author: GMI
License: MIT
License-File: LICENSE
Keywords: gmi,sandbox,sdk
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3 :: Only
Requires-Python: >=3.9
Provides-Extra: dev
Requires-Dist: build>=1.2; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: twine>=5.0; extra == 'dev'
Description-Content-Type: text/markdown

---
title: "GMI Sandbox SDK Usage"
description: "Install, configure, and use the GMI Sandbox Python SDK."
---

# GMI Sandbox SDK Usage

## Install

```bash
python -m pip install gmi-sandbox-sdk
```

## Configure

Use environment variables or pass values directly.

To get an API key, log in to `https://console.gmicloud.ai/`, click **API keys**, select **compute**, and click **Create API key**.

```bash
export GMI_SANDBOX_API_KEY="your-api-key"
```

`GMI_SANDBOX_IDC_NAME` is optional. Leave it unset to use your organization's default IDC. Set it only when you want requests to target a non-default IDC:

```bash
export GMI_SANDBOX_IDC_NAME="gmi-sandbox-us"
```

## Create a client

```python
from sandbox_sdk import SandboxClient

client = SandboxClient()
```

You can also pass credentials explicitly:

```python
client = SandboxClient(
    api_key="your-api-key",
)
```

## Create and use a sandbox

```python
sandbox = client.sandboxes.create(
    template_id="template-id",
)

sandbox.connect()
result = sandbox.commands.run("echo hello", wait=True)
print(result.stdout)

sandbox.files.write("/tmp/hello.txt", "hello")
print(sandbox.files.read("/tmp/hello.txt").decode())

sandbox.delete()
```

If you already have a sandbox ID:

```python
sandbox = client.sandboxes.get("sandbox-id")
sandbox.connect()
```

## Files

```python
sandbox.files.read("/tmp/a.txt")
sandbox.files.write("/tmp/a.txt", "hello")
sandbox.files.write("/tmp/a.bin", b"binary-data")
sandbox.files.upload("./local.txt", "/workspace/local.txt")
sandbox.files.download("/workspace/output.txt", "./output.txt")
```

`download()` returns bytes and can also write to a destination path.

## Commands

```python
execution = sandbox.commands.run(
    "python --version",
    cwd="/workspace",
    envs={"PYTHONUNBUFFERED": "1"},
    wait=True,
    wait_timeout_seconds=25,
)

print(execution.status)
print(execution.exit_code)
print(execution.stdout)
print(execution.stderr)
```

You can refresh or cancel a running execution:

```python
execution.refresh()
execution.cancel()
```

## Templates

```python
template = client.templates.get("template-id")
template.update(name="new-name")
template.delete()

builds = template.builds()
build = template.build("build-id")
logs = template.build_logs("build-id", offset=0, limit=100)
```

Creating a template requires an idempotency key:

```python
template = client.templates.create(
    name="demo",
    resources={"type": "preset", "product": "gmi.sandbox.small"},
    build={"source": {"type": "image", "image": "ubuntu:22.04"}},
    idempotency_key="template-1",
)

print(template.template_id)
template.update(name="new-name")
```

## Product specifications

```python
client.product_specifications.list()
client.product_specifications.list(idc_name="gmi-sandbox-us")
```

## Errors

The SDK raises typed exceptions for HTTP failures:

- `BadRequestError`
- `AuthenticationError`
- `PermissionDeniedError`
- `NotFoundError`
- `ConflictError`
- `RateLimitError`
- `ServerError`

Example:

```python
from sandbox_sdk import NotFoundError

try:
    client.sandboxes.get("missing")
except NotFoundError:
    print("sandbox not found")
```
