Worked examples
Task-shaped job sheets with complete code, expected output, and the failure path.
Philadelphia Command Plumbing · Night shift
subprocess like an emergency plumber.Cuprum runs external commands from Python without handing strings to a shell. Programs come from an approved catalogue, arguments become an exact argv, and every run returns a structured result.
Python 3.12+ · no runtime dependencies · ISC licence · Cuprum 0.2.0-beta2, a beta release on PyPI
Plate 01 Copper takes the night shift at the dispatch desk: every line on the board is a job that knows where it is going.
Work order 00-CU
The shell accepts whatever string it is handed. Cuprum starts from programs you have approved, builds the argument vector in one place, and hands back a job sheet you can inspect.
Commands are built from a curated catalogue of Program values. A program outside the catalogue raises UnknownProgramError before anything runs.
sh.make(ECHO)
Builders produce an exact argv tuple. No shell parses it, so a stray quote or semicolon is just a character.
echo("-n", "hello")
Await a command or a pipeline, or call run_sync() in a small script. Both return the same structured result.
await cmd.run()
Cancellation and timeouts send SIGTERM, wait out a grace period (0.5 s by default), then send SIGKILL and reap the child. Opt in to owning its process group and the descendants go too.
SIGTERM → grace → SIGKILL
Field manual · page 12
Make a builder from a catalogued program, call it with arguments,
and run the command. RunOutputOptions(echo=True)
tees the output to your terminal while Cuprum still captures it.
Use run_sync() when the job is small and the kettle
is already on.
pip install cuprum==0.2.0b2
Cuprum 0.2.0-beta2 is a beta: the API documented here is settling towards 0.2.0 and may still change. pip installs a pre-release only when it is named, so the command pins the exact version these pages were checked against.
Run your first commandimport asyncio
from cuprum import ECHO, RunOutputOptions, sh
async def main() -> None:
# Pick a known fitting from the catalogue.
echo = sh.make(ECHO)
cmd = echo("-n", "hello, cuprum!")
result = await cmd.run(output=RunOutputOptions(echo=True))
if result.ok:
print()
print(f"exit {result.exit_code}, captured {result.stdout!r}")
asyncio.run(main())
Completed works
Every run returns a CommandResult. These are its fields.
okexit_codestdoutstderrpiddurationThe rest of the office
The front window shows what Cuprum is for. The drawers hold the detail: runnable examples, the engineering plans, the optional native annex, and a public works board.
Task-shaped job sheets with complete code, expected output, and the failure path.
How a command is constructed, authorized, run, observed, and torn down, with the invariants that hold throughout.
An optional native pathway for inter-stage pipeline pumping. Python remains the reference behaviour.
What is shipped, what is in progress, and what is only proposed, each with its evidence.
A proposed companion that generates typed adapters returning Cuprum commands. Design only; nothing to install.
Wanted by the authorities
Somewhere between Bash and a full orchestration platform there was a perfectly reasonable Python program trying to get out. Cuprum is for that program.
“I keep a spare tee behind the filing cabinet. You’d be amazed.”
Copper, senior pipeline dispatcher
No call-out charge
Typed command execution for Python. The pipes have suffered enough.