Skip to content

ExecHandle

@final
class ExecHandle

One exec, addressed by its caller-minted id.

The id is the idempotency key, so a handle survives a process restart: rebuild it through Session.exec(exec_id) and every method still addresses the same server-side exec.

ExecHandle declares no __new__ or __init__, so it is not constructed directly: an instance comes back from another call in this package.

exec_id: str
def ack() -> ExecResult

Releases the buffered output and starts the TTL clock.

def ack_async() -> ExecResult

The awaitable twin of ack.

def close_stdin() -> StdinAck

Sends EOF. Nothing else closes stdin: the daemon’s copy of the pipe outlives the child’s wait, so a child blocked reading stdin hangs until its timeout otherwise.

def close_stdin_async() -> StdinAck

The awaitable twin of close_stdin.

def kill() -> bool

Signals the whole process group. False means nothing was signalled because the child had already been reaped — which is the outcome a kill wanted.

def kill_async() -> bool

The awaitable twin of kill.

def poll() -> ExecResult

Reads current status and output. Read-only server-side; safe to spin on.

def poll_async() -> ExecResult

The awaitable twin of poll.

def stream(
*,
offset: SupportsIndex = 0,
reconnect: bool = True,
max_reconnects: SupportsIndex | None = None,
error_on_gap: bool = False,
idle_timeout: SupportsFloat | SupportsIndex | None = None,
) -> ExecStream

An iterator over output as it arrives, reconnecting at the last good offset.

error_on_gap=True turns an evicted byte range into an exception instead of a Gap event, which is what a caller that must have complete output wants. reconnect=False ends the iterator at a cut instead, for a caller doing its own reconnection.

def wait(timeout: SupportsFloat | SupportsIndex = ...) -> ExecResult

Polls until the exec is done, or raises TimeoutError.

A timeout has not touched the exec — polling is read-only and output lives until it is acked — so a caller that gives up can come back and poll again.

def wait_and_ack(timeout: SupportsFloat | SupportsIndex = ...) -> ExecResult

Wait, then ack, returning the result that carries the output.

Which result comes back matters: the ack response carries the released output and a poll issued after the ack reports acked with none, so returning the wrong one is a silent empty-output bug. The core sequences it.

def wait_and_ack_async(timeout: SupportsFloat | SupportsIndex = ...) -> ExecResult

The awaitable twin of wait_and_ack. Cancelled during the wait it leaves the exec untouched; cancelled during the ack, the ack may have landed.

def wait_async(timeout: SupportsFloat | SupportsIndex = ...) -> ExecResult

The awaitable twin of wait. Cancelling it is giving up as a timeout does: the exec is untouched.

def write_stdin(data: bytes, *, eof: bool = False) -> StdinAck

Writes to the child’s stdin. Requires the exec to have been started with stdin=True, or the daemon answers 409.

eof in the same call is the common case for feeding a prompt: two round trips would leave a window where the child has the bytes but not the EOF that says the input is complete.

def write_stdin_async(data: bytes, *, eof: bool = False) -> StdinAck

The awaitable twin of write_stdin.

def __repr__() -> str

This page is generated from bindings/microvms-py/microvms.pyi by Griffe 2.3.0, run from site/scripts/gen-reference.mjs on every pnpm run sync, so an edit made here is overwritten by the next run.

To change the page, change the doc comment in the binding’s Rust source, then regenerate the declarations with mise run stubs. mise run stubs:check fails when the committed file no longer matches the source.