Skip to main content

Python bindings to the processkit Rust crate — asyncio-native, no-orphan process containment

Project description

processkit

Async-and-sync child-process management for Python with a kernel-backed no-orphan guarantee: every process you start — and everything it spawns — lives in a kill-on-exit container (a Windows Job Object, a Linux cgroup v2, or a POSIX process group), so no descendant ever outlives your program.

Beyond spawning a subprocess: run-and-capture, line streaming, interactive stdin, shell-free pipelines, readiness probes, timeouts & cancellation, supervision with restart/backoff, resource-limited sandboxes, and a mockable runner seam for subprocess-free tests — each in a synchronous and an asyncio-native form.

CI CodeQL Python License: MIT

from processkit import Command

# Require success and get trimmed stdout; a failure raises a typed exception.
version = Command("python", ["--version"]).run()
print(version)

Cover

Why processkit?

subprocess and asyncio.subprocess reach (at most) the direct child. The processes it spawned — a build tool's compiler children, the real payload behind a wrapper (cmd /c …, sh -c …), a test's helper servers — survive a timeout, an exception, or a cancelled task, and keep running as orphans.

processkit spawns every child into the operating system's own containment primitive — a Job Object on Windows, a cgroup v2 on Linux (with a process-group fallback), a POSIX process group on macOS/BSD — so teardown is a kernel operation over the whole tree, not a best-effort signal to one pid:

  • Nothing escapes silently. Exiting a with / async with block reaps every descendant, grandchildren included. Where a mechanism has a genuine weakness (a setsid child can escape a POSIX process group), ProcessGroup.mechanism reports the active backend instead of pretending — never a silent downgrade.
  • Sync and async, first-class. The run-&-capture verbs, pipelines, and supervision each exist as a plain synchronous call and an a-prefixed asyncio coroutine, sharing one set of types. The inherently-streaming surfaces — live line streaming, interactive stdin, readiness probes — are asyncio-native (awaited on a started process), not duplicated as blocking calls.
  • Honest results. A non-zero exit is data (ProcessResult) until you ask for success; a timeout is captured in the result; a cancellation is always an error; every platform divergence raises Unsupported or is documented. Raised exceptions carry structured fields and alias the stdlib's (Timeout is a TimeoutError, ProcessNotFound a FileNotFoundError, PermissionDenied a PermissionError).
  • Testable. One runner seam swaps the real spawner for scripted doubles or record/replay cassettes — no subprocess in your tests.

How it compares

whole-tree kill-on-exit async sync limits / stats streaming · pipelines · supervision
subprocess
asyncio.subprocess
processkit

The first column is the differentiator: a child's descendants are contained and reaped as a unit (Job Object / cgroup v2 / process group), not just the direct child.

Status: 1.0 — API frozen. The public API follows Semantic Versioning: breaking changes land only in a new major version, so 1.x upgrades are backward-compatible. See CHANGELOG.md, and ROADMAP.md for how it was built.

The hard platform work — Job Object containment, cgroup v2, race-free spawn, POSIX process groups — runs in a compiled native core, so the Python layer stays a thin, typed, asyncio-native surface with context-manager teardown.

Install

pip install processkit-py   # the import name is `processkit`

Distributed as abi3 wheels for CPython 3.10+ (one wheel per OS/arch runs on every supported minor version, 3.14 included), plus a version-specific free-threaded wheel for CPython 3.14t (PEP 703 — importing the extension does not re-enable the GIL). (Until the first PyPI release lands, build from source — see below.)

Picking a verb

Every run starts with the same Command builder; the verb you finish with decides what you get back. Each has an a-prefixed asyncio twin (run/arun, …):

You want Call You get
stdout, success required .run() trimmed str; non-zero exit / timeout / kill → typed exception
the full outcome, exit code as data .output() / .output_bytes() ProcessResult / BytesResult — code, stdout, stderr, timed_out; never raises on a non-zero exit
just the exit code .exit_code() int (a timed-out / killed run raises instead of inventing -1)
a yes/no answer .probe() bool — exit 0 → True, 1 → False, anything else raises
a live handle — streaming, stdin, probes .start() / .astart() RunningProcess

The run-to-completion verbs repeat on the Runner and CliClient layers too (start / astart live on Command and Runner). Deeper: Running commands.

Quick start

from processkit import Command, ProcessGroup

# Capture output; a non-zero exit does not raise on its own.
result = Command("git", ["rev-parse", "HEAD"]).output()
print("HEAD is", result.stdout.strip(), "·", result.code)

# Require success and get trimmed stdout directly.
version = Command("python", ["--version"]).run()

# Feed stdin.
sorted_out = Command("sort").stdin_text("banana\napple\n").run()

# Share one kill-on-exit group across several children; the block exit reaps the
# whole tree, grandchildren included.
with ProcessGroup() as group:
    group.start(Command("dev-server"))
    # ... work ...
# graceful teardown on exit

The asyncio surface mirrors it with the a prefix and adds streaming:

import asyncio
from processkit import Command, ProcessGroup

async def main():
    result = await Command("git", ["rev-parse", "HEAD"]).aoutput()

    # Stream a child's stdout; the context manager reaps the tree on exit.
    async with await Command("my-build", ["--watch"]).astart() as proc:
        async for line in proc.stdout_lines():
            print(line)

    async with ProcessGroup() as group:
        await group.astart(Command("dev-server"))

asyncio.run(main())

Documentation

This README is the quick tour. The docs/ guide set goes deeper on every capability, with more examples and the platform fine print in one place. New here? Skim the Cookbook first — it maps "I want to …" tasks to working snippets — then read Running commands end to end:

Guide Covers
Cookbook Task → snippet recipes for everything below; the fastest way in
Coming from subprocess Translating your subprocess / asyncio.subprocess code, and what containment adds
Running commands The full Command builder and every consuming verb, with error semantics
Process groups Containment, teardown, signals, suspend/resume, members, limits, stats
Streaming & interactive I/O Line streaming, conversational stdin, readiness probes, per-run profiling
Pipelines Shell-free a | b | c, pipefail attribution, chain timeouts
Timeouts & cancellation Captured vs raised deadlines, Ctrl+C, asyncio cancellation
Supervision Restart policies, backoff & jitter, stop conditions, outcomes
Testing your code The runner seam, scripted/record-replay doubles, CliClient
Platform support Mechanisms, all capability matrices, every caveat

Prefer whole programs to snippets? The examples/ directory has runnable, self-contained scripts — one per niche (no-orphan teardown, a readiness-gated server, supervision, a resource-limited sandbox). Each runs on Windows, Linux, and macOS and is exercised in CI.

A tour of the capabilities

Each section below is a taste with a pointer to its full guide.

Containing a process tree

Everything started in a ProcessGroup — and everything those processes spawn — is reaped when the block exits:

from processkit import Command, ProcessGroup

with ProcessGroup() as group:
    group.start(Command("dev-server"))
    group.start(Command("worker"))
    print(group.mechanism)        # "job_object" | "cgroup_v2" | "process_group"
    print(group.members())        # live member pids
# the whole tree, grandchildren included, is gone here

The with / async with exit (and ordinary GC) reaps the tree on every platform; surviving a hard kill of the Python process itself is a Windows-only property. Lean on the context managers, not __del__ / atexit. Deeper: Process groups · Platform support.

Sandboxing with resource limits

Bound a whole tree's memory, process count, and CPU at creation, so a runaway or untrusted child tree can't exhaust the host:

from processkit import Command, ProcessGroup

tool = (
    Command("untrusted-tool")
    .env_clear().inherit_env(["PATH"])     # locked-down environment
    .output_limit(max_bytes=8 * 1024 * 1024)
)
with ProcessGroup(max_memory=512 * 1024 * 1024, max_processes=64, cpu_quota=1.0) as group:
    group.start(tool)
    print(group.stats().active_process_count)

Limits need a Windows Job Object or a Linux cgroup-v2 root; under a container, systemd session, or other non-root cgroup the kernel forbids them and ResourceLimit is raised — never a silently-unbounded group. Deeper: Process groups → resource limits.

Signalling and pausing the whole tree

with ProcessGroup() as group:
    group.start(Command("my-server"))
    group.signal("hup")        # term | kill | int | hup | quit | usr1 | usr2
    group.suspend()            # freeze the whole tree…
    group.resume()             # …and let it run again

Signals are POSIX-real; on Windows only kill is deliverable (it maps to the Job Object terminate) and every other name — including term — raises Unsupported. Deeper: Process groups.

Running many at once

output_all runs a whole batch with a concurrency cap, so fanning out hundreds of commands can't exhaust file descriptors or the process table:

from processkit import Command, ProcessResult, output_all

cmds = [Command("convert", [f"{i}.png", f"{i}.jpg"]) for i in range(200)]
results = output_all(cmds, concurrency=8)            # never >8 alive at once
failed = sum(not (isinstance(r, ProcessResult) and r.is_success) for r in results)

It is collect-all: each slot is one command's ProcessResult, or a ProcessError for a spawn/I/O failure — a non-zero exit never short-circuits the batch. aoutput_all / output_all_bytes / aoutput_all_bytes round out the set. Deeper: Cookbook → run many at once.

Supervising a long-lived child

A Supervisor keeps a child alive: it restarts the command per policy whenever it exits, with bounded restarts and exponential, jittered backoff:

from processkit import Command, Supervisor

outcome = Supervisor(
    Command("my-server", ["--port", "8080"]),
    restart="on_crash",           # always | on_crash | never
    max_restarts=5,
    backoff_initial=0.2, backoff_factor=2.0, max_backoff=30.0,
    stop_when=lambda r: r.code == 0,   # a clean exit ends supervision
).run()                                # or: await ....arun()
print(outcome.restarts, outcome.stopped)

Deeper: Supervision.

Waiting for a child to be ready

"Start a server, then use it" needs the server to be ready, not merely started. Three async probes replace the arbitrary sleep:

from processkit import Command, wait_for, wait_for_port, wait_for_line

proc = await Command("my-server").astart()
lines = proc.stdout_lines()
await wait_for_line(lines, lambda l: "listening on" in l, timeout=10)   # a log line
await wait_for_port("127.0.0.1", 8080, timeout=10)                      # a TCP port
await wait_for(lambda: health_check(), timeout=10, interval=0.1)        # any condition

A probe that doesn't pass in time raises TimeoutError and does not kill the child — you decide what happens next. Deeper: Streaming → readiness probes.

Pipelines without a shell

a | b | c without a shell string — stages connected in-process (a relay, not a shell), so no quoting or injection surface, and every stage lives in one shared kill-on-exit group:

authors = (
    Command("git", ["log", "--format=%an"])
    | Command("sort")
    | Command("uniq", ["-c"])
).run()

The outcome is pipefail: stdout is the last stage's, while the exit code, stderr, and reported program come from the first stage that didn't exit cleanly. .timeout(d) bounds the whole chain. Deeper: Pipelines.

Environment and privileges

Command("worker").inherit_env(["PATH", "HOME", "LANG"]).run()        # allow-list on a cleared env
Command("worker").gid(1000).groups([1000]).uid(1000).setsid().run()  # POSIX: drop privileges, new session
Command("helper").create_no_window().run()                           # Windows: no console window
Command("daemonish").kill_on_parent_death().start()                  # die with a hard-killed parent

uid/gid/groups/setsid are POSIX-only — on Windows the run raises Unsupported rather than silently skipping a privilege drop. When dropping privileges, set all three of gid/groups/uiduid alone leaves the child holding the parent's (often root's) supplementary groups. Deeper: Running commands → privileges.

Cancelling a run

A blocked sync call honors Ctrl+C (raises KeyboardInterrupt and reaps the tree). Cancelling an awaited async run — directly, or via asyncio.wait_for / asyncio.timeout — tears down the whole tree and raises asyncio.CancelledError:

import asyncio

task = asyncio.ensure_future(Command("long-job").aoutput())
task.cancel()        # the process tree is reaped; CancelledError propagates

Unlike a timeout — whose expiry is captured in the result as timed_out — cancellation is always terminal. Deeper: Timeouts & cancellation.

Async streaming and interactive stdin

The one-shot verbs buffer the whole output. For long-running or conversational children, astart() returns a live RunningProcess:

# Conversational stdin: write a request, read the response.
proc = await Command("bc").keep_stdin_open().astart()
stdin = proc.take_stdin()
await stdin.write_line("2 + 2")
print(await anext(proc.stdout_lines()))   # 4
await stdin.close()

Deeper: Streaming & interactive I/O.

Wrapping a CLI tool

CliClient binds a program to default timeout/env, so repeated calls pass only their args:

from processkit import CliClient

git = CliClient("git", default_timeout=30.0)
head = git.run(["rev-parse", "HEAD"])     # or: await git.arun([...])
clean = git.probe(["diff", "--quiet"])

For testable code, inject a Runner / ScriptedRunner at the Command level instead — CliClient always uses the real runner. Deeper: Testing your code.

Testing without spawning processes

Write your code against a runner, then inject a ScriptedRunner in tests (the test doubles live in the processkit.testing submodule):

from processkit import Command
from processkit.testing import Reply, ScriptedRunner

scripted = ScriptedRunner()
scripted.on(["git", "rev-parse"], Reply.ok("deadbeef"))
assert scripted.run(Command("git", ["rev-parse", "HEAD"])) == "deadbeef"

RecordReplayRunner captures real tool output once and replays it offline, and RecordingRunner spies on what your code ran. Deeper: Testing your code.

Seeing what ran (observability)

Opt in once and processkit forwards its internal run events to Python's logging — useful when a spawn or teardown misbehaves in production:

import logging
from processkit import Command, enable_logging

logging.basicConfig(level=logging.DEBUG)
enable_logging()                          # idempotent; off by default

Command("git", ["rev-parse", "HEAD"]).run()
# DEBUG:processkit:child spawned program=git pid=Some(12345) mechanism=…

Records land on the processkit logger (filter it like any other); argv and env are never logged (they routinely carry secrets). Deeper: the logging recipe.

Stability

processkit follows Semantic Versioning. As of 1.0 the public API — everything re-exported from import processkit and declared in the type stubs — is stable: breaking changes land only in a new major version, so 1.x upgrades are backward-compatible. Anything underscore-prefixed is internal.

Requirements

  • Python 3.10 or later (abi3 wheel), including CPython 3.14 and the free-threaded (PEP 703) build 3.14t.
  • See platform support & caveats for per-OS behaviour and the wheel/architecture matrix.

Building from source

The first release to PyPI is pending (pip install processkit-py is the supported path once published; the import name is processkit). Until then — or on a platform without a prebuilt wheel (Windows on ARM, 32-bit) — build from source (see CONTRIBUTING.md for the build prerequisites):

git clone https://github.com/ZelAnton/processkit-py
cd processkit-py
pip install .

Contributing

See CONTRIBUTING.md for build/test instructions and conventions. To report a security issue, follow SECURITY.md.

License

This project is licensed under the MIT 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

processkit_py-1.0.0.tar.gz (191.2 kB view details)

Uploaded Source

Built Distributions

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

processkit_py-1.0.0-cp314-cp314t-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.14tWindows x86-64

processkit_py-1.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.14tmusllinux: musl 1.2+ x86-64

processkit_py-1.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl (1.8 MB view details)

Uploaded CPython 3.14tmusllinux: musl 1.2+ ARM64

processkit_py-1.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.28+ x86-64

processkit_py-1.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl (1.7 MB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.28+ ARM64

processkit_py-1.0.0-cp314-cp314t-macosx_11_0_arm64.whl (1.6 MB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

processkit_py-1.0.0-cp310-abi3-win_amd64.whl (1.9 MB view details)

Uploaded CPython 3.10+Windows x86-64

processkit_py-1.0.0-cp310-abi3-musllinux_1_2_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ x86-64

processkit_py-1.0.0-cp310-abi3-musllinux_1_2_aarch64.whl (1.8 MB view details)

Uploaded CPython 3.10+musllinux: musl 1.2+ ARM64

processkit_py-1.0.0-cp310-abi3-manylinux_2_28_x86_64.whl (1.8 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ x86-64

processkit_py-1.0.0-cp310-abi3-manylinux_2_28_aarch64.whl (1.7 MB view details)

Uploaded CPython 3.10+manylinux: glibc 2.28+ ARM64

processkit_py-1.0.0-cp310-abi3-macosx_11_0_arm64.whl (1.6 MB view details)

Uploaded CPython 3.10+macOS 11.0+ ARM64

File details

Details for the file processkit_py-1.0.0.tar.gz.

File metadata

  • Download URL: processkit_py-1.0.0.tar.gz
  • Upload date:
  • Size: 191.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.13

File hashes

Hashes for processkit_py-1.0.0.tar.gz
Algorithm Hash digest
SHA256 c200fa9414c5672bd56c8af07380d8e83bf05e8fdc8196601b63e151be8eb01e
MD5 5dd9c8a8cd15f3e8912dcbedf284af05
BLAKE2b-256 870d2d5dfe2cd351b9ff358b5fbf27bef6e981a2a29fc8093f6ce4063a5ea148

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0.tar.gz:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp314-cp314t-win_amd64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp314-cp314t-win_amd64.whl
Algorithm Hash digest
SHA256 0845972979b440c2c1ffa18528d94691915b22f6bf98ff36e9de28f19a8fdf2d
MD5 8d7395b8df1645d7563acd73efeb7957
BLAKE2b-256 4a91aacb0905da1beef993bb3952ccecb359149a69b74bd6099d3b1d54d67dd0

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp314-cp314t-win_amd64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 daa83fac81681688b7a16091fb00abf4527a9744a7a86644e541448e7755d2a5
MD5 4ab25b48e8b38ae51db03b9f14d4cea6
BLAKE2b-256 617faeae69f16b1a56a31fc246172503e2b965abdc6268fd3f0987db7de9becd

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 13b457de73a30e9038e0548a9ee63ed27907ddd14d2426b38f86b26a52fda617
MD5 1db9df73f7aafc5d9d6f2b8d3f6f6da8
BLAKE2b-256 ab85f04abcf883ebddbc5716fff0ca619dee091a4f8ad8adb064ea638ba8b506

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 2694bfbf25b94cb8b8cdb3e77b6251e4a0ccca58dc024547a4aca168455be6d2
MD5 a0d22ac1becc69d05ba641c0e80807ec
BLAKE2b-256 8c6a8743d8af1a9642701d63e611032081244c74932d3e4fad09385c039ea78d

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp314-cp314t-manylinux_2_28_x86_64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 ec226d1ef58eb86616c593103535a93a0b8fbc697512d650d85e8856156d00c6
MD5 a2a4aed7853aca22314bae4b3e692ce0
BLAKE2b-256 797da7b7b11221a14854af761f6a5fc27a58b3ec168d4b8075dd00951b845f38

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp314-cp314t-manylinux_2_28_aarch64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 912131a2eef10a703e8255c19713b53728de462653d70d7c09af68c00485bb8d
MD5 1073ada3914464b19edc3c24a172d488
BLAKE2b-256 2a31f97dd5f86c9a92cfd73ac129b3fb9d2a56eb2987ccfc5a455c80cbe476a9

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp314-cp314t-macosx_11_0_arm64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp310-abi3-win_amd64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp310-abi3-win_amd64.whl
Algorithm Hash digest
SHA256 763692a3d255d9d81c2bbdadc76407291777b6dd9b05c5231f8ad0fb616dc02c
MD5 c1a95994a6bdbefd302e8fc2c44447db
BLAKE2b-256 333f89f313f8dc4916bcef3ae7afaf46ee87b5cfbd1d5cf84a007bd1d1e913a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp310-abi3-win_amd64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp310-abi3-musllinux_1_2_x86_64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp310-abi3-musllinux_1_2_x86_64.whl
Algorithm Hash digest
SHA256 abd0c8a099320947458f14edb4566fd0a54d5eaed891c8b6d2ab084820e9d58f
MD5 6cb615bfe8d8122daf40c6106a0d221d
BLAKE2b-256 0659e0f8ffaf9014e34c37b7160d0709544a18856301f375577386ba699af20b

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp310-abi3-musllinux_1_2_x86_64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp310-abi3-musllinux_1_2_aarch64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp310-abi3-musllinux_1_2_aarch64.whl
Algorithm Hash digest
SHA256 aa3a72b7c7571f72fbd3f8e60f1de131fd0e3528b5fa5f716ef214bf5af3bacc
MD5 421a1b9d1b32c86f3798f9c55a0da782
BLAKE2b-256 b9723c1cd6346bdac513c345853cc3826555c668bab16e0cd2186f85fe037b39

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp310-abi3-musllinux_1_2_aarch64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp310-abi3-manylinux_2_28_x86_64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp310-abi3-manylinux_2_28_x86_64.whl
Algorithm Hash digest
SHA256 7f40d15429b1d85335ec8b25a91557549a5df0bb8b2033e797442d2dad624a59
MD5 4400e7d482767442cc459183df57a1de
BLAKE2b-256 0d9c0305ebcb866a35663e42c7a214b284795ae38232c87c3815de2a28363a1a

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp310-abi3-manylinux_2_28_x86_64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp310-abi3-manylinux_2_28_aarch64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp310-abi3-manylinux_2_28_aarch64.whl
Algorithm Hash digest
SHA256 fd341dc9fc2f7b967586179b75740a60490688e603c3791e71c1a3a5fee42fab
MD5 8c2dc00a180b04f921f7cd769b132897
BLAKE2b-256 3c87c4de6b1687547e052591f3f8ee6fc7dd4afb3fee7918bf7ee5d4b8fe2227

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp310-abi3-manylinux_2_28_aarch64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file processkit_py-1.0.0-cp310-abi3-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for processkit_py-1.0.0-cp310-abi3-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 9950a69e922e17b5fc0d75691d06e35eb553f87a8606375d68b50db72821e467
MD5 c28b7f20978d54c12bada23b2e188bd2
BLAKE2b-256 a6cfec4dff5086abae1208e7f9b398a28eff07768090284a68bd278146f00f03

See more details on using hashes here.

Provenance

The following attestation bundles were made for processkit_py-1.0.0-cp310-abi3-macosx_11_0_arm64.whl:

Publisher: release.yml on ZelAnton/processkit-py

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

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