Skip to main content

peno

A JS sandbox for AI agents

peno = python + deno: a Python-embeddable JavaScript sandbox built on deno_core and V8.

Run untrusted, LLM-generated JavaScript safely in Python — real V8, real isolation, real tool-calling.


Publish PyPI License Docs

Documentation · Examples · Issues

16-18x faster repeat execution via context-isolated isolate pooling — ~3 ms cold Runtime() start vs. ~167-185 µs per pooled IsolatePool checkout+eval, measured with Criterion and pytest-benchmark, with a dedicated test proving no state leaks between checkouts. Proven, not claimed — see BENCHMARKS.md.

For tool-calling workloads, retain one Runtime per session instead: a warm Runtime does a full host tool call in ~13.4 µs — ~12x faster than a pool checkout, which cannot host tool calls at all. See docs/tool-calling-at-pool-speed.md.

What this is

Agent frameworks and tool-execution runtimes increasingly need to run JavaScript the model itself wrote — a code-generation step, a small data transform, a "call this JS snippet to compute the answer" tool. That code is untrusted by construction. peno embeds a real V8 isolate per runtime (via Rust/PyO3) so that code runs with no filesystem, no network, and no ambient Node.js APIs by default, with heap and wall-clock limits you set, and a real way to kill it if it doesn't stop on its own.

It is not a general "embed any JS anywhere" library and not a JS interpreter reimplemented in Python — it's V8, the same engine behind Chrome and Node.js, so the JS your model writes actually behaves like JS.

import peno

peno.bind_function("add", lambda a, b: a + b)
print(peno.eval("add(2, 3)"))  # 5

Why it's different

  • Real V8, not a toy interpreter. Every language quirk, every standard library method, every performance characteristic your model expects from "JavaScript" is the real thing.

  • Cross-thread termination that actually works. A watchdog thread calling .terminate() on a runaway while(true){} used to panic instead of stopping the code (pyo3_runtime.PanicException: Runtime is unsendable, but sent to another thread) — a real bug in the upstream design that meant a stuck agent tool call couldn't be killed from outside. TerminationHandle fixes this: it exposes only the Send + Sync part of V8's isolate handle, so a watchdog on a separate thread can interrupt execution safely. See PATCH.md for the full root cause and proof; tests/test_termination_handle.py is the regression test.

    As of 0.2.0 this works on every shape of stuck script, not just runaway loops. terminate() used to be a no-op against a runtime parked on a pending promise — V8 only acts on a termination when it next enters JavaScript, and new Promise(() => {}) never does, so it was unkillable. The dispatcher now reads the termination flag between polls, killing all such shapes in ~1.7 ms, while while(true){} still dies the cheap way at ~0.12 ms and a killed runtime keeps its bound functions. See BENCHMARKS.md and tests/test_parked_termination.py.

  • Context-isolated pooling, so speed doesn't cost you isolation. A cold V8 isolate costs ~3 ms to create; IsolatePool keeps a small set of them warm and hands out a brand-new, empty V8 Context on every checkout — the isolate is reused, but no JS-visible global state (globalThis, etc.) ever survives from one caller to the next, even when they land on the same underlying isolate. Measured: ~3 ms cold-start → ~170-185 µs pooled, ~16-18x, with a dedicated test proving a globalThis value set in one checkout is gone (typeof x === 'undefined') in the next. See BENCHMARKS.md and src/runtime/pool.rs for the numbers and the reasoning.

  • A host-callback bridge for tool-calling from JS. bind_function/ bind_object let the sandboxed JS call back into Python — the primitive an agent needs when the model's JS wants to invoke a real tool, not just compute a value. ToolBridge builds the product shape on top: hand it a dict of callables and get a call budget, fail-closed name checking, and JS-catchable typed errors, instead of hand-rolling all three.

  • Tool errors JS can branch on. A Python exception raised inside a bound tool reaches JavaScript as a real Error whose name is the exception's class name, so the model's JS can tell "bad arguments" from "rate limited" from "tool not found" with a plain catch (e) { if (e.name === ...) } — rather than string-matching one flattened TypeError. The same name/message shape a JS exception already carries into Python, so the two directions are symmetric.

  • console.log you can actually read. Sandboxed console.* output can be routed back to a Python callback with RuntimeConfig(on_console=...), receiving structured (level, args) — the single most common thing you want when showing a model what its own script printed. Composes with enable_console rather than replacing it.

Get Started

pip install peno  # or uv pip install peno

Requires Python 3.10+ on macOS or Linux. peno is experimental — expect breaking changes between versions.

Quickstart: sandboxed eval, tool-calling, and a timeout

import asyncio

from peno import Runtime, RuntimeConfig

# Cap memory; the runtime terminates itself if JS tries to exceed it.
config = RuntimeConfig(max_heap_size=10 * 1024 * 1024)  # 10 MB


async def main():
    with Runtime(config) as runtime:
        # The tool-calling primitive: expose a Python function to the sandboxed JS.
        def get_weather(city: str) -> str:
            return f"72F and sunny in {city}"

        runtime.bind_function("getWeather", get_weather)

        # Model-generated JS calling back into your tool.
        result = runtime.eval("getWeather('Zurich')")
        print(result)  # "72F and sunny in Zurich"

        # Enforce a wall-clock timeout on code that might not terminate.
        try:
            await runtime.eval_async("while (true) {}", timeout=2.0)
        except Exception as exc:
            print(f"killed a runaway eval after 2s: {exc}")


asyncio.run(main())

Running an untrusted sync eval() you can't await? Grab a TerminationHandle before the call and .terminate() it from a watchdog thread — see tests/test_termination_handle.py for the exact pattern (and the bug it fixed, in PATCH.md).

Many tools, one budget

When the model gets more than one tool, ToolBridge gives you the whole surface — budget, name checking, typed errors — in one object:

from peno import Runtime, ToolBridge

bridge = ToolBridge(
    {"get_weather": get_weather, "send_email": send_email},
    max_calls=50,  # total tool calls this agent turn may make
)

with Runtime() as runtime:
    bridge.attach(runtime)
    runtime.eval("tools.get_weather('Zurich')")

The call that exceeds max_calls never reaches your Python function — JS gets a catchable ToolBudgetError. Note ToolBridge needs a full Runtime: pooled isolates have no op registry to bind tools into, which is a permanent architectural boundary, not a todo — see the bindings guide for why.

For a fast path when you're running many short-lived, independent snippets (e.g. one per agent turn) and don't need bind_function/modules for that particular call, check out an isolate from a warm IsolatePool instead of paying full cold-start cost each time:

from peno import IsolatePool

pool = IsolatePool(size=4)
with pool.checkout() as isolate:
    print(isolate.eval("1 + 41"))  # 42

Integrations

  • FastMCP tool bridge - expose FastMCP tools to sandboxed JS via bind_function and an in-process fastmcp.Client
  • pydantic-ai "code mode" agent - an agent tool where the model submits one JS batch script instead of many separate tool calls, run safely with a timeout
  • ToolBridge - hand a sandbox several Python tools with a total call budget, typed errors the model's JS can branch on, and console.log routed back to Python
  • Vendored npm libraries - run real npm document-generation libraries (pptxgenjs, pdf-lib) from their browser bundles inside the sandbox; see the guide for what makes a library a good candidate
  • Arrow IPC dataframes - move 100k+ row tables into the sandbox as Arrow IPC bytes instead of JSON objects (5 ms vs 253 ms, and it works at the default 10 MB serialization limit that rejects the JSON payload); see the guide

Documentation

  • Quick Start
  • Concepts: runtimes, type conversion, resource controls
  • Guides: binding functions, module loading, snapshots
  • Use cases: AI agent sandboxes, workflow runners, plugin systems
  • API reference
  • Benchmarks — measured, reproducible numbers, including the pooling comparison above

Metadata

Release files for peno 0.2.1

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for peno 0.2.1
File Size Uploaded Provenance Actions
peno-0.2.1.tar.gz 737.2 kB With provenance Details for peno-0.2.1.tar.gz

Built distributions (wheels)

Table of built distributions (wheels) for peno 0.2.1
File Actions
peno-0.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl PyPy 3.11 PyPy 3.11 7.3 Linux glibc 2.28+ x86-64 Details for peno-0.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl
peno-0.2.1-cp314-cp314t-manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 free-threading Linux glibc 2.28+ x86-64 Details for peno-0.2.1-cp314-cp314t-manylinux_2_28_x86_64.whl
peno-0.2.1-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details for peno-0.2.1-cp314-cp314-win_amd64.whl
peno-0.2.1-cp314-cp314-manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.28+ x86-64 Details for peno-0.2.1-cp314-cp314-manylinux_2_28_x86_64.whl
peno-0.2.1-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details for peno-0.2.1-cp314-cp314-macosx_11_0_arm64.whl
peno-0.2.1-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details for peno-0.2.1-cp313-cp313-win_amd64.whl
peno-0.2.1-cp313-cp313-manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64 Details for peno-0.2.1-cp313-cp313-manylinux_2_28_x86_64.whl
peno-0.2.1-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details for peno-0.2.1-cp313-cp313-macosx_11_0_arm64.whl
peno-0.2.1-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details for peno-0.2.1-cp312-cp312-win_amd64.whl
peno-0.2.1-cp312-cp312-manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ x86-64 Details for peno-0.2.1-cp312-cp312-manylinux_2_28_x86_64.whl
peno-0.2.1-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details for peno-0.2.1-cp312-cp312-macosx_11_0_arm64.whl
peno-0.2.1-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details for peno-0.2.1-cp311-cp311-win_amd64.whl
peno-0.2.1-cp311-cp311-manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.28+ x86-64 Details for peno-0.2.1-cp311-cp311-manylinux_2_28_x86_64.whl
peno-0.2.1-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details for peno-0.2.1-cp311-cp311-macosx_11_0_arm64.whl
peno-0.2.1-cp310-cp310-win_amd64.whl CPython 3.10 CPython 3.10 Windows x86-64 Details for peno-0.2.1-cp310-cp310-win_amd64.whl
peno-0.2.1-cp310-cp310-manylinux_2_28_x86_64.whl CPython 3.10 CPython 3.10 Linux glibc 2.28+ x86-64 Details for peno-0.2.1-cp310-cp310-manylinux_2_28_x86_64.whl

Total release size: 328.9 MB

Release files / peno-0.2.1.tar.gz

Download URL peno-0.2.1.tar.gz
Size 737.2 kB
Tags Source
SHA-256 checksum
How to use checksums
9713cb1e2c53ddafcae6751a68a0cc9f8f6391ee8605b9532c3092b09c838599
BLAKE2b-256 checksum
How to use checksums
ace13d37226ea899b60736c0cd065e2ceb537e7473e303c831a85ec0c9fbc63d
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl

Download URL peno-0.2.1-pp311-pypy311_pp73-manylinux_2_28_x86_64.whl
Size 21.9 MB
Tags Linux glibc 2.28+ x86-64 PyPy 3.11 PyPy 3.11 7.3
SHA-256 checksum
How to use checksums
3005f2ea3bfed87efe353b69e10ec2b212c42626abb58cf04ba08fd9b5ceb7f4
BLAKE2b-256 checksum
How to use checksums
bf09c790058ec5cc4d79526c126b8de2f76e35e46b22dbb349591de271d1c932
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp314-cp314t-manylinux_2_28_x86_64.whl

Download URL peno-0.2.1-cp314-cp314t-manylinux_2_28_x86_64.whl
Size 21.9 MB
Tags CPython 3.14 CPython 3.14 free-threading Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
d140635931c1ec7c5a5779c4bfa8f8ed444b851a27544afc53dbf518cad202eb
BLAKE2b-256 checksum
How to use checksums
ff2675ce631a33434037e5a25d9cfe462012fcce8a12e94e9b7b287dd137eab6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp314-cp314-win_amd64.whl

Download URL peno-0.2.1-cp314-cp314-win_amd64.whl
Size 19.0 MB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
65d284d88f22b7deb8017e44e904d3f258f2e17d3a2b1a5fb1b49a80c1df2e76
BLAKE2b-256 checksum
How to use checksums
6dca1dfdc8d5c4682e799857889355bec4caf5b9e36800fc3cadf98c6152051e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp314-cp314-manylinux_2_28_x86_64.whl

Download URL peno-0.2.1-cp314-cp314-manylinux_2_28_x86_64.whl
Size 21.9 MB
Tags CPython 3.14 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
607f5c09b9d99db10193ef8b2a4001db4f9416208125938c232e773a3651e4d4
BLAKE2b-256 checksum
How to use checksums
ce0e340060a711934241938370607cc18c2a981d52b3b68f0b9ecf072f36393e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp314-cp314-macosx_11_0_arm64.whl

Download URL peno-0.2.1-cp314-cp314-macosx_11_0_arm64.whl
Size 19.9 MB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
97fa434aaf687071a50104535263aafad7f5ba10018ed45d7cb7b1dea89205f9
BLAKE2b-256 checksum
How to use checksums
8485c7483aa97b217031c742797aa3765814d58c8c769ea32333e7ab989cefdf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp313-cp313-win_amd64.whl

Download URL peno-0.2.1-cp313-cp313-win_amd64.whl
Size 19.0 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
f1d68a0dd55a1704314a8baf421fbbafb1a4011f457701a976156ef5782afa05
BLAKE2b-256 checksum
How to use checksums
7e9b3c3d8dc41db28e2de5dc2be420dc5bc0e4ebcb6ba1c309cabc3feb0ad5f4
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp313-cp313-manylinux_2_28_x86_64.whl

Download URL peno-0.2.1-cp313-cp313-manylinux_2_28_x86_64.whl
Size 21.9 MB
Tags CPython 3.13 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
735b5a8edb371c1de447af1336b47386780c8c4ccca83349af4c7cd73ea83a7c
BLAKE2b-256 checksum
How to use checksums
6064baa9fe85b0754fae094dde7fd382ea4fa40c60675a3fde32a5ad9a42d675
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp313-cp313-macosx_11_0_arm64.whl

Download URL peno-0.2.1-cp313-cp313-macosx_11_0_arm64.whl
Size 19.9 MB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
969178dd61aaecdcb75e4d4b5d505cded0947891cdc63c2826c688a03a24fd0c
BLAKE2b-256 checksum
How to use checksums
ebc59f20842bc1ffdc84c413e45aed9a1144f393c0ae000fb00f43336c79063a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp312-cp312-win_amd64.whl

Download URL peno-0.2.1-cp312-cp312-win_amd64.whl
Size 19.0 MB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
33008cb3d07a4c322fd780241072b2569d362d10ddac306620625507ccb5a9b2
BLAKE2b-256 checksum
How to use checksums
e35b3d3c4a09089bf967d930dcc681febec518b8caa923590c7afaace673df08
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp312-cp312-manylinux_2_28_x86_64.whl

Download URL peno-0.2.1-cp312-cp312-manylinux_2_28_x86_64.whl
Size 21.9 MB
Tags CPython 3.12 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
fbcf49646624f72cc242ae8fc201d45d204a4b14c23fde17fe2f88bcaafa8aa9
BLAKE2b-256 checksum
How to use checksums
eb9bb0e526677fb4c5783f05a84e92e0a390955391d8bdba11a6f3ad409e8e71
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp312-cp312-macosx_11_0_arm64.whl

Download URL peno-0.2.1-cp312-cp312-macosx_11_0_arm64.whl
Size 19.9 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
a0dbe2fea471089a8bfeb1a287a23dbf6680d2088e47a32f07259ca61d7c28c6
BLAKE2b-256 checksum
How to use checksums
869d7dbe2ba991b7fbdf1205a0a91bc016bbb460d0f0319a2482e6394684b0b6
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp311-cp311-win_amd64.whl

Download URL peno-0.2.1-cp311-cp311-win_amd64.whl
Size 19.0 MB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
858dc0b5a52689c9a8ed1926010425a45eef99d48c4ce7c4de32fbfae2aee8be
BLAKE2b-256 checksum
How to use checksums
c5c586d295009124870812bfa0e0b9af44657326baacd611fb731ebbf558ceb8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp311-cp311-manylinux_2_28_x86_64.whl

Download URL peno-0.2.1-cp311-cp311-manylinux_2_28_x86_64.whl
Size 21.9 MB
Tags CPython 3.11 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
db2df155393d5d901ffaf2901a0a9ff6fe027404c931af51317c96ea830678f3
BLAKE2b-256 checksum
How to use checksums
fb1083a472b0a7cf0210bd15f517274d9ffa15fe441588f0e831e9e0ae3faa8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp311-cp311-macosx_11_0_arm64.whl

Download URL peno-0.2.1-cp311-cp311-macosx_11_0_arm64.whl
Size 19.9 MB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
0b60957b062b83490570a00c945fcba4ebe8ce2142ca68ed1ef3a6abe8489890
BLAKE2b-256 checksum
How to use checksums
e7b854e949cac27e710ad2694854ca99d59b68e9125f4e6da8ed5eeb9d1ba15e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp310-cp310-win_amd64.whl

Download URL peno-0.2.1-cp310-cp310-win_amd64.whl
Size 19.0 MB
Tags CPython 3.10 Windows x86-64
SHA-256 checksum
How to use checksums
9b51205ede2afc1919c055eedc671cadf64d300d8a8076d72b21295b21fdde94
BLAKE2b-256 checksum
How to use checksums
532d538477801ac18d34ae2a742235c58fc7fc94b0a3e692820261fd01286e35
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Release files / peno-0.2.1-cp310-cp310-manylinux_2_28_x86_64.whl

Download URL peno-0.2.1-cp310-cp310-manylinux_2_28_x86_64.whl
Size 21.9 MB
Tags CPython 3.10 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
6cead3b0e5c7d336c9c0d34c4e555527793e24204bc1a0545a55b2d7a435d3a3
BLAKE2b-256 checksum
How to use checksums
c5330f120b80408733b7a507a752de7e01cbccf92634a7d9a5b7358fdb4ac281
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

Security for peno 0.2.1

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

Full provenance

All 17 files in this release have been uploaded with provenance metadata.

Select from 17 files

Attestation for peno-0.2.1.tar.gz

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 21, 2026.

Transparency log

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

To learn more about protecting yourself from malicious actors, visit our package security documentation.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page