Metadata-Version: 2.4
Name: zchpc
Version: 0.1.0
Summary: Client for the ZCHPC platform: GPUs, managed databases, caches and media buckets.
Author: Movella Systems
License: MIT
Project-URL: Homepage, https://zchpc.movellasystems.com
Project-URL: Documentation, https://zchpc.movellasystems.com/docs
Keywords: zchpc,gpu,postgres,redis,s3
Requires-Python: >=3.10
Description-Content-Type: text/markdown
Provides-Extra: postgres
Requires-Dist: psycopg[binary]>=3.1; extra == "postgres"
Provides-Extra: mysql
Requires-Dist: PyMySQL>=1.1; extra == "mysql"
Provides-Extra: mongodb
Requires-Dist: pymongo>=4.6; extra == "mongodb"
Provides-Extra: cache
Requires-Dist: redis>=5.0; extra == "cache"
Provides-Extra: buckets
Requires-Dist: boto3>=1.34; extra == "buckets"
Provides-Extra: gpu
Requires-Dist: paramiko>=3.4; extra == "gpu"
Provides-Extra: all
Requires-Dist: psycopg[binary]>=3.1; extra == "all"
Requires-Dist: redis>=5.0; extra == "all"
Requires-Dist: boto3>=1.34; extra == "all"
Requires-Dist: paramiko>=3.4; extra == "all"

# zchpc

The Python client for [ZCHPC](https://zchpc.movellasystems.com): rent GPU
slices, and provision managed databases, caches and S3-compatible media
buckets.

```bash
pip install zchpc
```

Nothing is required to talk to the API itself. The drivers are pulled in only
when you actually connect to a resource, so a bucket user never installs a
Postgres driver:

```bash
pip install "zchpc[postgres]"   # psycopg
pip install "zchpc[cache]"      # redis
pip install "zchpc[buckets]"    # boto3
pip install "zchpc[gpu]"        # paramiko
pip install "zchpc[all]"        # all of them
```

## Rent a GPU

`with` destroys the rental on the way out, including when the code in the
middle raises. A GPU bills by the second, and the usual way a box gets left
running is an exception between renting it and destroying it.

```python
from zchpc import ZCHPC

z = ZCHPC("gpv_YOUR_API_KEY")        # or set ZCHPC_API_KEY

with z.gpus.rent(gpu_mem_gb=8, hours=1).wait() as gpu:
    print(gpu.gpu_info())            # Tesla V100S-PCIE-32GB, 32768 MiB, 0 MiB
    print(gpu.run("nvidia-smi"))
```

`hours` is prepaid, so ask for what you need: the API default of 24 is a full
day of rent.

## Databases

```python
db = z.databases.first_running("postgres") or z.databases.create().wait()

db.sql("CREATE TABLE IF NOT EXISTS notes (id serial PRIMARY KEY, body text)")
db.executemany("INSERT INTO notes (body) VALUES (%s)", [("first",), ("second",)])

print(db.sql("SELECT id, body FROM notes ORDER BY id"))
print(db.tables())
print(db.uri)                        # the raw connection string
```

The client is a convenience, not a wall. `db.uri` is a standard connection
string and `db.connect()` is a real driver connection, so you can drop to plain
SQL whenever the wrapper is in the way.

## Cache

```python
cache = z.cache.first_running() or z.cache.create().wait()

cache.set("session:42", "abc", ttl=60)
print(cache.ttl("session:42"))       # 60  (-1 = no expiry, -2 = no key)
cache.incr("hits")                   # atomic, safe across processes
cache.flush_prefix("session:")       # scoped delete, never FLUSHALL
```

## Buckets

```python
bucket = z.buckets.first() or z.buckets.create("media")

bucket.put("photos/cat.jpg", open("cat.jpg", "rb").read(),
           content_type="image/jpeg")

print(bucket.presign("photos/cat.jpg", expires=300))   # expiring share link
print(bucket.presign_put("uploads/from-browser.png"))  # browser-direct upload
```

Path-style addressing is set for you. Amazon puts the bucket in the hostname
and every SDK defaults to that, but this endpoint serves buckets as a path, so
doing it by hand is the usual first thing to go wrong.

## Errors

Typed by what you can do about them: `AuthError`, `InsufficientCredit`,
`LimitReached`, `NotFoundError`, `ProvisioningError`, `WaitTimeout`,
`MissingDependency`.

## License

MIT
