Skip to main content

Tiny Modal-shaped job harness — one declaration, multiple backends (local Docker / Brev / Modal)

Project description

runplz

PyPI

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's Image chain, 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, drives brev search --gpu-name X --min-vcpu Y ... --sort price to pick the cheapest matching instance.
  • Three backends:
    • localdocker build + docker run. Auto-detects NVIDIA runtime via docker info.
    • brevbrev create + rsync + ssh'd docker build/docker run OR inline install ("container mode"). Supports both mode="vm" and mode="container" on BrevConfig.
    • modal — generates a module-scope modal.App file and shells to modal run. Skips serialized=True so 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:

  • localdocker
  • brevbrev, docker, ssh, rsync
  • modalmodal>=1.1,<2 Python 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._bootstrap reads RUNPLZ_SCRIPT/RUNPLZ_FUNCTION from env and imports the user's file with importlib.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_OUT inside the container; the runner collects that directory back to ./out/ on the host.

Common gotchas

  • Brev GPU + docker --gpus all has been flaky in the past (see docs/brev-notes.md). If a run stalls, try BrevConfig(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 to modal.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


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

runplz-1.4.0.tar.gz (47.1 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

runplz-1.4.0-py3-none-any.whl (34.2 kB view details)

Uploaded Python 3

File details

Details for the file runplz-1.4.0.tar.gz.

File metadata

  • Download URL: runplz-1.4.0.tar.gz
  • Upload date:
  • Size: 47.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for runplz-1.4.0.tar.gz
Algorithm Hash digest
SHA256 da65faf18e95dcc6b1c14af58303784c029ce8c61be710a9927c880a9d69462a
MD5 a38e38e8da7ce382097476e52239f248
BLAKE2b-256 e4e68d94c2f56dd1e73df3f7e829df8daa88889455fcc77772e309fe3535ebb2

See more details on using hashes here.

File details

Details for the file runplz-1.4.0-py3-none-any.whl.

File metadata

  • Download URL: runplz-1.4.0-py3-none-any.whl
  • Upload date:
  • Size: 34.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.6

File hashes

Hashes for runplz-1.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 972ea84fcb24fd6c8d2479b4bc577b09e4a992e7521969d37d05792ecc971157
MD5 ebe555b9c3cca35ad4713afceb9d25ad
BLAKE2b-256 2a3512d8ae213884fc354f6cce76aef21c41e0e4dc6dd3f885344a100c0a523e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page