Tiny Modal-shaped job harness — one declaration, multiple backends (local Docker / Brev / Modal)
Project description
runplz
Tiny Modal-shaped job harness — one Python decoration, multiple backends.
from runplz import App, BrevConfig, Image
app = App("my-job", brev=BrevConfig(instance_type="g2-standard-4:nvidia-l4:1"))
image = (
Image.from_registry("pytorch/pytorch:2.4.0-cuda12.1-cudnn9-runtime")
.apt_install("rsync", "build-essential")
.pip_install("pandas>=2.0", "scikit-learn")
.pip_install_local_dir(".", editable=True)
)
@app.function(
image=image,
gpu="T4",
min_cpu=4, min_memory=26, min_gpu_memory=16, min_disk=100,
timeout=60 * 60,
)
def train():
import subprocess
subprocess.run(["bash", "scripts/train.sh"], check=True)
@app.local_entrypoint()
def main():
train.remote()
Run on whichever backend you like:
runplz local path/to/job.py
runplz brev --instance my-box path/to/job.py
runplz modal path/to/job.py
What it does
- User-facing API mirrors
modal.Image+@app.function+.remote(). Learn it once; it works on all backends. - Image DSL:
from_registry(...)→apt_install(...)→pip_install(...)→pip_install_local_dir(...)→run_commands(...). Translates to Modal'sImagechain, a synthesized Dockerfile, or inline install commands over ssh depending on the backend. - Resource requests in GB:
gpu="T4",min_cpu=4,min_memory=26,min_gpu_memory=16,min_disk=100. Forwarded directly to Modal; on Brev, drivesbrev search --gpu-name X --min-vcpu Y ... --sort priceto pick the cheapest matching instance. - Three backends:
local—docker build+docker run. Auto-detects NVIDIA runtime viadocker info.brev—brev create+ rsync + ssh'ddocker build/docker runOR inline install ("container mode"). Supports bothmode="vm"andmode="container"onBrevConfig.modal— generates a module-scopemodal.Appfile and shells tomodal run. Skipsserialized=Trueso local/remote Python versions don't have to match.
Install
pip install runplz # core only (local + brev backends)
pip install 'runplz[modal]' # add Modal support
The core dependency set is empty. Backends shell out to system CLIs:
local→dockerbrev→brev,docker,ssh,rsyncmodal→modal>=1.1,<2Python package
Design notes
.remote()args must be JSON-serializable. No closures, no custom objects. Deliberate: it keeps the remote dispatch mechanism small and portable (env vars + a path to the user's script).- Function bodies are imported by path, not installed. The in-container
runplz._bootstrapreadsRUNPLZ_SCRIPT/RUNPLZ_FUNCTIONfrom env and imports the user's file withimportlib.util.spec_from_file_location. So your job files can live anywhere in the repo and don't need to be a Python package. - Backend-agnostic output convention. Write to
$RUNPLZ_OUTinside the container; the runner collects that directory back to./out/on the host.
Common gotchas
- Brev GPU + docker
--gpus allhas been flaky in the past (seedocs/brev-notes.md). If a run stalls, tryBrevConfig(mode="container", ...)— that path bypasses Brev's VM docker runtime entirely. - Modal function return values max at ~256 MB. runplz's modal backend
tar-returns
/out; if your run writes more than that you'll hit the cap. (TODO: switch tomodal.Volume.)
Example
See examples/simple_job.py for the smallest working thing.
Tests
pytest tests/
25 offline tests — DSL rendering, BrevConfig validation, Modal → Brev GPU label translation, instance picker with mocked subprocess, CLI guards.
License
Apache 2.0 — see LICENSE.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file runplz-1.2.0.tar.gz.
File metadata
- Download URL: runplz-1.2.0.tar.gz
- Upload date:
- Size: 46.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
b6726ec3d7811d174d0ecd50c03a1867ef392d08f74b74c1b58274aed1f8ace8
|
|
| MD5 |
ec900bf76b4d90a918f512ff208d712d
|
|
| BLAKE2b-256 |
bc1cbe2df6f77a27a79790ebfc9d44f859967a62afdbfbcb8c079581057e0a57
|
File details
Details for the file runplz-1.2.0-py3-none-any.whl.
File metadata
- Download URL: runplz-1.2.0-py3-none-any.whl
- Upload date:
- Size: 33.8 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.6
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
48813548d85f4aa193d93a053cdbb9a4fe95d9bc9fd51165d9d2ef9bcf225bce
|
|
| MD5 |
838205be7324aa60bccf8d4abbf89c77
|
|
| BLAKE2b-256 |
075561de17ba542cab5f05373e678722723143b1b90c28e84b172202f0f1c6e8
|