This release is a pre-release and may not be stable for production use.
FissionPlane Python SDK
Use FissionPlane to create and control isolated sandboxes on your own infrastructure. This package connects Python applications to an FissionPlane installation.
The SDK can:
- create, list, pause, resume, and delete sandboxes;
- run commands, stream process output, and use PTYs;
- read, write, and watch sandbox files;
- make a sandbox port private or public;
- build templates from OCI images; and
- use synchronous or asynchronous Python.
FissionPlane requires an existing on-premises installation. See the FissionPlane repository for the platform source and deployment information.
Requirements
- Python 3.10 or later
- An FissionPlane control plane URL
- An API key or OIDC bearer token
- A template alias or template artifact ID
Install
Install the package with pip:
pip install fissionplane
You can also use uv:
uv add fissionplane
Configure the client
Set the control plane URL and API key:
export FISSIONPLANE_API_URL="https://api.sandbox.example.com"
export FISSIONPLANE_API_KEY="your-api-key"
FissionPlane() reads both variables. You can also pass the values directly:
from fissionplane import FissionPlane
client = FissionPlane(
base_url="https://api.sandbox.example.com",
api_key="your-api-key",
)
Use access_token instead of api_key for an OIDC bearer token. An explicit
API key takes precedence over an access token. The client rejects an empty
credential, or one containing whitespace, when you construct it.
Timeouts, retries, and logging
The client applies a 60 second timeout to every request. Change the default
with request_timeout. Pass 0 or None to disable the timeout.
client = FissionPlane(request_timeout=30)
Every operation also accepts request_timeout for one call:
sandbox = client.sandboxes.get("sbx-123", request_timeout=5)
result = sandbox.commands.run("make", args=["build"], request_timeout=0)
The client retries a failed request twice by default, with exponential
backoff and jitter. Set max_retries=0 to disable retries. The SDK only
retries a request that is safe to send again:
- reads, such as
get(),list(), andfiles.read(); sandboxes.create()when you pass anidempotency_key; and- responses the server marks
retryable, or status 429 and 5xx responses that the server does not markretryable: false.
client = FissionPlane(max_retries=4)
sandbox = client.sandboxes.create("base", idempotency_key="example-job-1")
Pass headers to add or replace headers on one call:
client.sandboxes.list(headers={"X-Request-Source": "nightly-job"})
The SDK reports retries, capability token re-mints, and page fetches at debug
level on the fissionplane logger. Pass your own logger to redirect them:
import logging
logging.basicConfig(level=logging.DEBUG)
client = FissionPlane(logger=logging.getLogger("my-app.sandboxes"))
Anything you pass in httpx_args wins over the SDK defaults, including
timeout and headers.
Create a sandbox and run a command
Sandbox creation is synchronous. The call returns after a node acknowledges the sandbox.
from fissionplane import FissionPlane
client = FissionPlane()
sandbox = client.sandboxes.create(
"base",
name="example-job",
deadline_seconds=600,
idempotency_key="example-job-1",
)
try:
result = sandbox.commands.run(
"python",
args=["-c", "print('hello from FissionPlane')"],
timeout_seconds=30,
)
print(result.stdout)
print(result.exit_code)
finally:
sandbox.delete()
commands.run() waits for the command to exit. It returns the exit code,
standard output, standard error, and an optional truncation flag.
Use sandbox.commands.list_processes() to list supervised processes. Use
sandbox.commands.kill(pid, "SIGTERM") to signal one process.
Start a background process when output must be followed or stdin stays open:
from fissionplane import PtySize
process = sandbox.commands.start("bash", pty=PtySize(cols=120, rows=40))
attachment = process.attach()
attachment.send_input("pwd\n")
for event in attachment:
if event.type == "stdout":
print(event.data, end="")
elif event.type == "exit":
break
Filesystem operations use the sandbox data plane directly:
sandbox.files.make_dir("/workspace")
sandbox.files.write("/workspace/input.txt", b"hello")
entries = sandbox.files.list("/workspace")
watch = sandbox.files.watch("/workspace", recursive=True)
Manage the sandbox lifecycle
A sandbox has one of four visible states: running, paused, terminated,
or failed.
sandbox.pause()
sandbox.resume(deadline_seconds=600)
sandbox.extend_deadline(900)
sandbox.delete()
pause() saves a snapshot and releases node capacity. resume() restores the
snapshot on a node. A resumed sandbox has a new epoch.
Capability tokens belong to one sandbox epoch. The SDK replaces the token on
the handle after resume(). A handle returned by sandboxes.get() or
sandboxes.iterate() has no token. Call sandbox.mint_token() before you use
commands on such a handle.
A capability token also expires on its own schedule. When the sandbox data plane rejects one, the handle mints a replacement and sends the request again. This applies to command, file, and streaming calls alike, so long-lived handles keep working without your code refreshing anything.
Use an idempotency key when your application can retry sandbox creation. The same key returns the sandbox from the first successful request.
Expose a port
Every port is private by default. Private access requires a capability token. Make one port public only when anonymous access is required.
exposure = sandbox.ports.expose(3000, "public")
print(exposure.url)
records = sandbox.ports.list()
sandbox.ports.unexpose(3000)
unexpose() removes the exposure record. The port then returns to private
access.
Build and use a template
Template builds run asynchronously on the FissionPlane installation.
from fissionplane import BuildStep
build = client.templates.build(
"python:3.12",
alias="python-tools",
steps=[BuildStep(command="pip install httpx")],
)
template = build.wait(timeout=600)
sandbox = client.sandboxes.create("python-tools")
Use build.logs(offset) to read build output. Pass the returned offset to the
next call. Use client.templates.get_build(build_id) to reconnect to an
existing build.
Use the asynchronous client
AsyncFissionPlane has the same operations as the synchronous client. Await
each network operation.
import asyncio
from fissionplane import AsyncFissionPlane
async def main() -> None:
client = AsyncFissionPlane()
sandbox = await client.sandboxes.create("base")
try:
result = await sandbox.commands.run("python", args=["-V"])
print(result.stdout)
finally:
await sandbox.delete()
asyncio.run(main())
Use async for with client.sandboxes.iterate() to read all matching pages.
Read every page
sandboxes.list() returns one page and its next_cursor. Use iterate()
when you want every match instead. It fetches one page at a time and follows
the cursor until the collection ends.
for sandbox in client.sandboxes.iterate(state=SandboxState.RUNNING, limit=50):
print(sandbox.sandbox_id)
The asynchronous client returns an async generator:
async for sandbox in client.sandboxes.iterate(metadata={"run": "42"}):
print(sandbox.sandbox_id)
Handle errors
All SDK errors inherit from FissionPlaneError. HTTP errors include status,
code, retryable, and request_id when the server returns those fields.
from fissionplane import FissionPlaneError, RateLimitError
try:
sandbox = client.sandboxes.create("base")
except RateLimitError as error:
if error.retryable:
print(f"retry later; request ID: {error.request_id}")
except FissionPlaneError as error:
print(error.code, error)
The package also exports errors for authentication, authorization, missing resources, lifecycle conflicts, expired snapshots, command timeouts, and failed template builds.
Control plane and data plane
The control plane manages sandboxes, ports, tokens, and templates. The sandbox data plane runs commands, streams process I/O, and accesses files.
The SDK sends your API key or OIDC token to the control plane. It sends a short-lived capability token to the sandbox data plane. The SDK stores that token on the sandbox handle.
The data-plane agent uses port 50000 by default. Pass agent_port to the
client only when your installation uses a different port.
Build the API reference
The package documents its public surface with pdoc. Run it from
src/sdks/python:
uv run pdoc fissionplane -o docs
The command writes browsable HTML to docs/, which is not committed. Add
module names to document them on their own pages, for example
uv run pdoc fissionplane fissionplane.sandboxes -o docs. Do not point pdoc
at fissionplane._api or fissionplane._dataplane: those are generated cores,
and the OpenAPI files below are their reference.
Use uv run pdoc fissionplane without -o to preview the reference on a local
web server.
API status
This package is version 0.0.1. Treat its public API as unstable until the
project publishes a stable release.
The control-plane and data-plane OpenAPI files define the HTTP contracts:
License
FissionPlane uses the Apache License 2.0.
Metadata
Release files for fissionplane 0.0.1b0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| fissionplane-0.0.1b0.tar.gz | 102.4 kB | Without provenance | Details for fissionplane-0.0.1b0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| fissionplane-0.0.1b0-py3-none-any.whl | Python 3 | none | any | Details for fissionplane-0.0.1b0-py3-none-any.whl |
Total release size: 231.3 kB
Release files / fissionplane-0.0.1b0.tar.gz
| Download URL | fissionplane-0.0.1b0.tar.gz |
|---|---|
| Size | 102.4 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
6b0e5bc150bb802b3c9f8aeb50fb79630748ce26d5f9bb7c8d8d91df5b91e79d
|
|
BLAKE2b-256 checksum How to use checksums |
692adea481f4bf67a1385ca6c66ddc41c55c7a545168c1eb33f21a522babc63b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Release files / fissionplane-0.0.1b0-py3-none-any.whl
| Download URL | fissionplane-0.0.1b0-py3-none-any.whl |
|---|---|
| Size | 129.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
53fdab5f0aeb7cef0c7aedbd93611a7a3b936e1e5bde79a1fb333ceda883451b
|
|
BLAKE2b-256 checksum How to use checksums |
45ee49b2e31b34b5856dadc87d3c931aa54c2ea99435c072cf66cbe7ad0d082b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
uv/0.9.24 {"installer":{"name":"uv","version":"0.9.24","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
|
Security for fissionplane 0.0.1b0
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.