3torus — Python SDK
Typed Python client for the 3Torus GPU compute marketplace API. The
Python sibling of the 3torus CLI: the same gRPC
core-services surface, exposed as a typed client with Pydantic
models.
Status (CLAUDE.md Rule 39): first leg, Done@L1 — typed client + tests against an in-process fake server. Live-API use (L2) needs the public API gateway active or a
kubectl port-forward; the gateway activation is operator-gated (m3-plan Phase C —M3-GRPC-GATEWAY-REST). Several RPCs are contract-only /Unimplementedserver-side until each handler ships underM3-CORE-SERVICES-SERVER-IMPL.
Install
pip install 3torus # dist name
import threetorus # import name
Quickstart — submit a GPU job in 5 lines
from threetorus import Client
with Client("api.dev.3torus.com:443", api_key="3t_...", secure=True) as c:
job = c.jobs.submit(image="nvidia/cuda-samples:vectoradd", gpu_count=1)
print(job.id, job.status.name) # gpu-vectoradd-019e943b SUBMITTED
result = c.jobs.get(job.id) # poll until terminal
print(result.status.name, result.result and result.result.output_uri)
The API key rides on every RPC as an authorization: Bearer <key> gRPC
metadata header — it is never logged, never placed in the address, and
never echoed in an exception (CLAUDE.md Rule 10). Prefer loading it from
an environment variable or secret store; never hard-code it.
This is the seed for the GitBook SDK Quickstart (
M3-GITBOOK-SDK-QUICKSTART) — keep the 5-line example in sync.
Verb surface
The client mirrors the CLI's verb groups one-to-one. Each sub-client fronts one gRPC core service:
| Sub-client | Service | Methods |
|---|---|---|
client.clusters |
ComputeService |
list, get, list_nodes, capacity |
client.jobs |
JobsService |
submit, get, list, cancel |
client.billing |
BillingService |
usage, quota, invoices, balance |
client.providers |
ProvidersService |
list, get, gpu_skus |
client.health |
HealthService |
check |
client.auth |
AuthService |
validate, whoami |
clusters, page = c.clusters.list(role=ClusterRole.COMPUTE)
cap = c.clusters.capacity("gpu-dev-pool-4")
usage = c.billing.usage("client-acme")
skus, _ = c.providers.gpu_skus(tier="datacenter")
status = c.health.check()
who = c.auth.validate("3t_...")
Typed models
Responses are Pydantic models with native
Python types — datetime for timestamps, Decimal for money, IntEnum
for enums — instead of raw protobuf accessors:
from threetorus import models as m
job: m.Job = c.jobs.get("job-id")
job.status # m.JobStatus.COMPLETED (IntEnum, .name == "COMPLETED")
job.completed_at # datetime | None (UTC; None when unset)
usage.estimated_cost # m.Money(amount=Decimal("4.20"), currency="USD")
Errors
Every gRPC failure is mapped to a typed exception carrying the original
grpc.StatusCode + the server's message verbatim:
from threetorus import NotFoundError, UnimplementedError, UnavailableError
try:
c.clusters.get("does-not-exist")
except NotFoundError as e:
print(e.code, e.message) # StatusCode.NOT_FOUND ...
UNAVAILABLE / DEADLINE_EXCEEDED are retried automatically with capped
exponential backoff before surfacing; permanent codes are never retried.
Override the policy with Client(..., retry=RetryPolicy(max_attempts=5)).
Roadmap (later legs)
- L2 live-API verification against the public gateway / port-forward.
- PyPI publish of the
3torusdistribution — automated byrelease-sdk.yml(see Releasing to PyPI below); the first published version waits on the operator's trusted-publisher registration. - Async client (
grpcioaio) for high-concurrency callers.
See the platform backlog row M3-PYTHON-SDK. Sibling rows:
M3-CLI-3TORUS (the Go CLI), M3-GITBOOK-SDK-QUICKSTART (docs).
Releasing to PyPI
Releases are tag-driven and publish through PyPI trusted publishing
(GitHub OIDC → short-lived upload token). There is no long-lived PyPI token
anywhere — not in a repo secret, not in 1Password. The workflow is
.github/workflows/release-sdk.yml
(M4-RELEASE-AUTOMATION-SDK-CLI batch 1).
-
Bump
[project].versioninpyproject.tomlon a branch, merge tomain. -
Tag that commit on
mainand push the tag:git tag v0.1.1 # MUST equal pyproject.toml [project].version git push origin v0.1.1
-
The workflow asserts the tag equals the declared version (
scripts/sdk-version-from-tag.sh— a mismatch fails the run, nothing is stamped), asserts the tagged commit is reachable frommain, builds the wheel with the canonicalgen/corestubs inside, runstwine check, and publishes the wheel to https://pypi.org/project/3torus/. -
Verify from a clean environment (the row's L2 probe):
pip download 3torus==0.1.1 --no-deps -d ./dl
Dry run (build + twine check + version assert, no publish):
gh workflow run release-sdk.yml --ref main — dry_run defaults to true.
Before the first release the operator registers the workflow as a
trusted publisher on PyPI (operator-actions-register row 29): project
3torus, owner alexperritaz, repository 3-torus, workflow
release-sdk.yml, environment pypi. Until then the publish step fails with
PyPI's "trusted publishing not configured" error — that is the expected
pre-registration state, not a workflow defect.
Wheel only. The sdist hatchling emits omits gen/core (the force-include
is wheel-scoped), so it cannot be built into a working install; publishing
it would be a lie on the index. Tracked as M4-SDK-SDIST-OMITS-GEN-CORE.
Development
pip install -e ".[dev]" # from sdk/python/
ruff check src tests
pytest
The generated protobuf stubs are not vendored here — the wheel
force-includes the repo's canonical gen/core tree (produced by
buf generate) as the core package, so the SDK never drifts from the
proto contracts (scripts/check-proto-codegen-sync.sh).
Metadata
Release files for 3torus 0.1.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| 3torus-0.1.3-py3-none-any.whl | Python 3 | none | any | Details |
Release files / 3torus-0.1.3-py3-none-any.whl
| Download URL | 3torus-0.1.3-py3-none-any.whl |
|---|---|
| Size | 105.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
435301463a54ad8008375daf4a057d9279e0955a612362213bce50c1a10484fa
|
|
BLAKE2b-256 checksum How to use checksums |
4eb3f3e5e62280ab4db315280760cac91b92298204b520c9208d5bc2dc751f9d
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Sep 16, 2026.
Transparency log