Python sandbox powered by WebAssembly
Project description
PyEryx - Python Bindings for Eryx
Python bindings for the Eryx sandbox - execute Python code securely inside WebAssembly.
Installation
pip install pyeryx
Note: The package is installed as
pyeryxbut imported aseryx.
Or build from source using maturin:
cd crates/eryx-python
maturin develop
Quick Start
import eryx
# Create a sandbox with the embedded Python runtime
sandbox = eryx.Sandbox()
# Execute Python code in complete isolation
result = sandbox.execute('''
print("Hello from the sandbox!")
x = 2 + 2
print(f"2 + 2 = {x}")
''')
print(result.stdout)
# Output:
# Hello from the sandbox!
# 2 + 2 = 4
print(f"Execution took {result.duration_ms:.2f}ms")
Features
- Complete Isolation: Sandboxed code runs in WebAssembly with no host access by default
- Controlled Network Access: Optional TCP/TLS networking with host filtering and policies
- Host Callbacks: Expose async Python functions for controlled host interaction
- Resource Limits: Configure timeouts, memory limits, and callback restrictions
- Fast Startup: Pre-initialized Python runtime embedded for ~1-5ms sandbox creation
- Pre-initialization: Custom snapshots with packages for even faster specialized sandboxes
- Package Support: Load Python packages (.whl, .tar.gz) including native extensions
- Persistent Sessions: Maintain Python state across executions with
Session - Virtual Filesystem: Sandboxed file storage with
VfsStorage - Type Safe: Full type stubs for IDE support and static analysis
Python Version
The sandbox runs CPython 3.14 compiled to WebAssembly (WASI). This is the same Python build used by componentize-py from the Bytecode Alliance.
Performance
The pyeryx package ships with a pre-initialized Python runtime embedded in the binary.
This means Python's interpreter initialization (~450ms) has already been done at build time,
so creating a sandbox is very fast:
import eryx
import time
# First sandbox - fast! (~1-5ms)
start = time.perf_counter()
sandbox = eryx.Sandbox()
print(f"Sandbox created in {(time.perf_counter() - start) * 1000:.1f}ms")
# Execution is also fast
start = time.perf_counter()
result = sandbox.execute('print("Hello!")')
print(f"Execution took {(time.perf_counter() - start) * 1000:.1f}ms")
For repeated sandbox creation with custom packages, see
SandboxFactory below.
API Reference
Core Classes:
Sandbox- Main class for isolated Python executionSession- Persistent state across executionsExecuteResult- Execution results with stdout and statsResourceLimits- Configure execution constraintsNetConfig- Configure network access and policiesCallbacks- Expose host functions to sandboxed codeSandboxFactory- Pre-initialize sandboxes with packagesVfsStorage- Virtual filesystem for sessions
Sandbox vs Session
| Feature | Sandbox |
Session |
|---|---|---|
| State persistence | No - fresh each execute() | Yes - variables persist |
| Virtual filesystem | No | Yes (optional) |
| Use case | One-off execution | REPL, multi-step workflows |
| Isolation | Complete per-call | Complete from host |
Use Sandbox when:
- Running untrusted code that should start fresh each time
- Each execution is independent
- You want maximum isolation between executions
Use Session when:
- Building up state across multiple executions
- You need file persistence (VFS)
- Implementing a REPL or notebook-like experience
- Performance matters (no re-initialization per call)
Sandbox
The main class for executing Python code in isolation.
sandbox = eryx.Sandbox(
resource_limits=eryx.ResourceLimits(
execution_timeout_ms=5000, # 5 second timeout
max_memory_bytes=100_000_000, # 100MB memory limit
),
network=eryx.NetConfig( # Optional: enable networking
allowed_hosts=["api.example.com"]
),
callbacks=[ # Optional: host functions
{"name": "get_data", "fn": get_data_fn, "description": "Fetch data"}
]
)
result = sandbox.execute("print('Hello!')")
Loading Packages
To use custom packages, use SandboxFactory which bundles packages into a reusable
runtime snapshot:
import eryx
# Create a factory with your packages (one-time, takes 3-5 seconds)
factory = eryx.SandboxFactory(
packages=[
"/path/to/jinja2-3.1.2-py3-none-any.whl",
"/path/to/markupsafe-2.1.3-wasi.tar.gz", # WASI-compiled native extension
],
imports=["jinja2"], # Optional: pre-import for faster first execution
)
# Create sandboxes with packages already loaded (~10-20ms each)
sandbox = factory.create_sandbox()
result = sandbox.execute('''
from jinja2 import Template
template = Template("Hello, {{ name }}!")
print(template.render(name="World"))
''')
For packages with native extensions (like markupsafe), you need WASI-compiled versions. These are automatically late-linked into the WebAssembly component.
ExecuteResult
Returned by sandbox.execute() with execution results:
stdout: str- Captured standard outputduration_ms: float- Execution time in millisecondscallback_invocations: int- Number of callback invocationspeak_memory_bytes: Optional[int]- Peak memory usage (if available)
ResourceLimits
Configure execution constraints:
limits = eryx.ResourceLimits(
execution_timeout_ms=30000, # Max script runtime (default: 30s)
callback_timeout_ms=10000, # Max single callback time (default: 10s)
max_memory_bytes=134217728, # Max memory (default: 128MB)
max_callback_invocations=1000, # Max callbacks (default: 1000)
)
# Or create unlimited (use with caution!)
unlimited = eryx.ResourceLimits.unlimited()
NetConfig
Configure network access for sandboxed code. By default, all network access is disabled.
Enable networking by creating a NetConfig and passing it to the sandbox.
import eryx
# Default config - allows external hosts, blocks localhost/private networks
config = eryx.NetConfig(
max_connections=10, # Max concurrent connections
connect_timeout_ms=30000, # Connection timeout (30s)
io_timeout_ms=60000, # I/O timeout (60s)
allowed_hosts=["api.example.com"], # Whitelist specific hosts
blocked_hosts=[] # Override default blocks
)
sandbox = eryx.Sandbox(network=config)
result = sandbox.execute("""
import urllib.request
response = urllib.request.urlopen("https://api.example.com/data")
print(response.read().decode())
""")
Security Defaults
By default, NetConfig blocks localhost and private networks to prevent SSRF attacks:
localhost,127.*,[::1]- Private networks:
10.*,172.16.*-172.31.*,192.168.*,169.254.*
Permissive Configuration
For testing or development, use .permissive() to allow all hosts including localhost:
# WARNING: Allows sandbox to access local services
config = eryx.NetConfig.permissive()
sandbox = eryx.Sandbox(network=config)
Host Filtering
Control which hosts sandboxed code can connect to using patterns with wildcards:
config = eryx.NetConfig(
allowed_hosts=[
"api.example.com", # Exact host
"*.googleapis.com", # Wildcard subdomain
"api.*.com", # Wildcard in middle
]
)
When allowed_hosts is non-empty, only matching hosts are allowed. Blocked hosts are checked first.
Builder Methods
Chain methods for convenient configuration:
config = (eryx.NetConfig()
.allow_host("api.example.com")
.allow_host("*.openai.com")
.allow_localhost() # Remove localhost from blocked list
.with_root_cert(cert_der_bytes)) # Add custom CA cert for self-signed certs
Custom Certificates
Add custom root certificates for testing with self-signed certificates:
# Load certificate in DER format
with open("ca-cert.der", "rb") as f:
cert_der = f.read()
config = eryx.NetConfig().with_root_cert(cert_der)
sandbox = eryx.Sandbox(network=config)
Supported Protocols
Network-enabled sandboxes support:
- HTTP/HTTPS via
urllib.request,http.client - Raw TCP/TLS via
socketmodule - Async networking via
asynciostreams - Third-party libraries like
requests,httpx(when loaded viaSandboxFactory)
Callbacks
Expose host functions to sandboxed code as async Python functions. Callbacks enable controlled interaction between sandboxed code and the host environment.
Dict-Based API
Simple and explicit, good for dynamic callback registration:
import eryx
def get_time():
import time
return {"timestamp": time.time()}
def fetch_user(user_id: int):
# Call database, API, etc. from host
return {"id": user_id, "name": "Alice", "email": "alice@example.com"}
sandbox = eryx.Sandbox(
callbacks=[
{
"name": "get_time",
"fn": get_time,
"description": "Returns current Unix timestamp"
},
{
"name": "fetch_user",
"fn": fetch_user,
"description": "Fetches user data from database"
}
]
)
result = sandbox.execute("""
# Callbacks are available as async functions
t = await get_time()
print(f"Time: {t['timestamp']}")
user = await fetch_user(user_id=42)
print(f"User: {user['name']} ({user['email']})")
""")
Decorator-Based API
More Pythonic, uses CallbackRegistry:
import eryx
registry = eryx.CallbackRegistry()
@registry.callback(description="Greets a person by name")
def greet(name: str, formal: bool = False):
if formal:
return {"greeting": f"Good day, {name}"}
return {"greeting": f"Hey {name}!"}
@registry.callback(name="calc", description="Performs calculation")
def calculate(op: str, a: float, b: float):
ops = {"add": a + b, "sub": a - b, "mul": a * b, "div": a / b}
return {"result": ops[op]}
sandbox = eryx.Sandbox(callbacks=registry)
result = sandbox.execute("""
greeting = await greet(name="Alice", formal=True)
print(greeting['greeting'])
result = await calc(op="add", a=10, b=32)
print(f"10 + 32 = {result['result']}")
""")
Callback Requirements
- Must accept JSON-serializable arguments
- Must return JSON-serializable values (typically a dict)
- Can be sync or async (both work the same from Python's perspective)
- Are called as
await callback_name(...)from sandboxed code
Discovering Callbacks
Sandboxed code can introspect available callbacks:
result = sandbox.execute("""
import _callbacks
callbacks = _callbacks.list()
for cb in callbacks:
print(f"{cb['name']}: {cb['description']}")
""")
Error Handling
Callbacks can raise exceptions that propagate to sandboxed code:
def may_fail(should_fail: bool):
if should_fail:
raise ValueError("Operation failed!")
return {"status": "ok"}
sandbox = eryx.Sandbox(
callbacks=[{"name": "may_fail", "fn": may_fail, "description": "May fail"}]
)
result = sandbox.execute("""
try:
await may_fail(should_fail=True)
except Exception as e:
print(f"Caught: {e}")
""")
SandboxFactory
For use cases with custom packages, SandboxFactory lets you create a
reusable factory with your packages pre-loaded and pre-imported.
Note: For basic usage without packages,
eryx.Sandbox()is already fast (~1-5ms) because the base runtime ships pre-initialized. UseSandboxFactoryonly when you need to bundle custom packages.
Use cases for SandboxFactory:
- Load packages (jinja2, numpy, etc.) once and create many sandboxes from the factory
- Pre-import modules to eliminate import overhead on first execution
- Save/load factory state to disk for persistence across process restarts
import eryx
# One-time factory creation with packages (takes 3-5 seconds)
factory = eryx.SandboxFactory(
packages=[
"/path/to/jinja2-3.1.2-py3-none-any.whl",
"/path/to/markupsafe-2.1.3-wasi.tar.gz",
],
imports=["jinja2"], # Pre-import modules
)
# Create sandboxes with packages already loaded (~10-20ms each)
sandbox = factory.create_sandbox()
result = sandbox.execute('''
from jinja2 import Template
print(Template("Hello {{ name }}").render(name="World"))
''')
# Create many sandboxes from the same factory
for i in range(100):
sandbox = factory.create_sandbox()
sandbox.execute(f"print('Sandbox {i}')")
Saving and Loading
Save factories to disk for instant startup across process restarts:
# Save the factory (includes pre-compiled WASM state + package state)
factory.save("/path/to/jinja2-factory.bin")
# Later, in another process - loads in ~10ms (vs 3-5s to recreate)
factory = eryx.SandboxFactory.load("/path/to/jinja2-factory.bin")
sandbox = factory.create_sandbox()
Properties and Methods
factory.size_bytes- Size of the pre-compiled factory in bytesfactory.create_sandbox(resource_limits=...)- Create a new sandboxfactory.save(path)- Save factory to a filefactory.to_bytes()- Get factory as bytesSandboxFactory.load(path)- Load factory from a file
Session
Unlike Sandbox which runs each execution in isolation, Session maintains
persistent Python state across multiple execute() calls. This is useful for:
- Interactive REPL-style execution
- Building up state incrementally
- Faster subsequent executions (no Python initialization overhead per call)
import eryx
session = eryx.Session()
# State persists across executions
session.execute("x = 42")
session.execute("y = x * 2")
result = session.execute("print(f'{x} * 2 = {y}')")
print(result.stdout) # "42 * 2 = 84"
# Functions and classes persist too
session.execute("""
def greet(name):
return f"Hello, {name}!"
""")
result = session.execute("print(greet('World'))")
print(result.stdout) # "Hello, World!"
Session with Virtual Filesystem
Sessions can optionally use a virtual filesystem (VFS) for persistent file storage that survives across executions and even session resets:
import eryx
# Create shared storage
storage = eryx.VfsStorage()
# Create session with VFS enabled
session = eryx.Session(vfs=storage)
# Write files to the virtual filesystem
session.execute("""
with open('/data/config.json', 'w') as f:
f.write('{"setting": "value"}')
""")
# Files persist across executions
result = session.execute("""
import json
with open('/data/config.json') as f:
config = json.load(f)
print(config['setting'])
""")
print(result.stdout) # "value"
# Files even persist across session.reset()
session.reset()
result = session.execute("print(open('/data/config.json').read())")
# File still exists!
Sharing Storage Between Sessions
Multiple sessions can share the same VfsStorage for inter-session communication:
import eryx
# Shared storage instance
storage = eryx.VfsStorage()
# Session 1 writes data
session1 = eryx.Session(vfs=storage)
session1.execute("open('/data/shared.txt', 'w').write('from session 1')")
# Session 2 reads it
session2 = eryx.Session(vfs=storage)
result = session2.execute("print(open('/data/shared.txt').read())")
print(result.stdout) # "from session 1"
Custom Mount Path
By default, VFS files are accessible under /data. You can customize this:
session = eryx.Session(vfs=storage, vfs_mount_path="/workspace")
session.execute("open('/workspace/file.txt', 'w').write('custom path')")
State Snapshots
Capture and restore Python state for checkpointing:
session = eryx.Session()
session.execute("x = 42")
session.execute("data = [1, 2, 3]")
# Capture state as bytes (uses pickle internally)
snapshot = session.snapshot_state()
# Clear state
session.clear_state()
# Restore from snapshot
session.restore_state(snapshot)
result = session.execute("print(x, data)")
print(result.stdout) # "42 [1, 2, 3]"
# Snapshots can be saved to disk and restored in new sessions
with open("state.bin", "wb") as f:
f.write(snapshot)
Session Properties and Methods
session.execute(code)- Execute code, returnsExecuteResultsession.reset()- Reset Python state (VFS persists)session.clear_state()- Clear variables without full resetsession.snapshot_state()- Capture state as bytessession.restore_state(snapshot)- Restore from snapshotsession.execution_count- Number of executions performedsession.execution_timeout_ms- Get/set timeout in millisecondssession.vfs- Get theVfsStorage(if enabled)session.vfs_mount_path- Get the VFS mount path (if enabled)
VfsStorage
In-memory virtual filesystem storage. Files written to the VFS are completely isolated from the host filesystem - sandboxed code cannot access real files.
import eryx
# Create storage (can be shared across sessions)
storage = eryx.VfsStorage()
# Use with Session
session = eryx.Session(vfs=storage)
The VFS supports standard Python file operations:
open(),read(),write()- File I/Oos.makedirs(),os.listdir(),os.remove()- Directory operationsos.path.exists(),os.path.isfile()- Path checkspathlib.Path- Full pathlib support
Exceptions
eryx.EryxError- Base exception for all Eryx errorseryx.ExecutionError- Python code raised an exceptioneryx.InitializationError- Sandbox failed to initializeeryx.ResourceLimitError- Resource limit exceedederyx.TimeoutError- Execution timed out
Package Loading
Supported Formats
.whl- Standard Python wheels (zip archives).tar.gz/.tgz- Tarballs (used by wasi-wheels project)- Directories - Pre-extracted package directories
Native Extensions
Packages containing native Python extensions (.so files compiled for WASI)
are automatically detected and late-linked into the WebAssembly component.
This allows packages like numpy, markupsafe, and others to work in the sandbox.
Note: You need WASI-compiled versions of native extensions, not regular Linux/macOS/Windows binaries.
Error Handling
import eryx
sandbox = eryx.Sandbox()
try:
result = sandbox.execute("raise ValueError('oops')")
except eryx.ExecutionError as e:
print(f"Code failed: {e}")
try:
sandbox = eryx.Sandbox(
resource_limits=eryx.ResourceLimits(execution_timeout_ms=100)
)
result = sandbox.execute("while True: pass")
except eryx.TimeoutError as e:
print(f"Timed out: {e}")
Development
Building
# Install maturin
pip install maturin
# Build and install in development mode
maturin develop
# Build release wheel
maturin build --release
Testing
pip install pytest
pytest
License
MIT OR Apache-2.0
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
Built Distributions
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file pyeryx-0.4.3.tar.gz.
File metadata
- Download URL: pyeryx-0.4.3.tar.gz
- Upload date:
- Size: 16.8 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
4edc234a8ec983b4cbd2b5151c963c5660dfc77f95fa35956734c90bd43af0b4
|
|
| MD5 |
1952cafc2891a89b20eed97d7d455ba5
|
|
| BLAKE2b-256 |
c11bbc2995fc7b6e93a63df3c3a0cda2b1c6134137a2d9ebbf430ae7347139cc
|
Provenance
The following attestation bundles were made for pyeryx-0.4.3.tar.gz:
Publisher:
python-release.yml on eryx-org/eryx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyeryx-0.4.3.tar.gz -
Subject digest:
4edc234a8ec983b4cbd2b5151c963c5660dfc77f95fa35956734c90bd43af0b4 - Sigstore transparency entry: 937717966
- Sigstore integration time:
-
Permalink:
eryx-org/eryx@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/eryx-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
python-release.yml@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pyeryx-0.4.3-cp312-abi3-win_amd64.whl.
File metadata
- Download URL: pyeryx-0.4.3-cp312-abi3-win_amd64.whl
- Upload date:
- Size: 48.4 MB
- Tags: CPython 3.12+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
8214d7398c9f4bdb66bc7c86e6ad6dbb7c85ff154fc2878abbfcdddcab6ba1b2
|
|
| MD5 |
392f6d9c518ee46acf407a4f68e83c11
|
|
| BLAKE2b-256 |
613473e8b54b653f130226dcc05d84c387bc5de39eceef47a13bffa304d206cb
|
Provenance
The following attestation bundles were made for pyeryx-0.4.3-cp312-abi3-win_amd64.whl:
Publisher:
python-release.yml on eryx-org/eryx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyeryx-0.4.3-cp312-abi3-win_amd64.whl -
Subject digest:
8214d7398c9f4bdb66bc7c86e6ad6dbb7c85ff154fc2878abbfcdddcab6ba1b2 - Sigstore transparency entry: 937717991
- Sigstore integration time:
-
Permalink:
eryx-org/eryx@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/eryx-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
python-release.yml@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pyeryx-0.4.3-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: pyeryx-0.4.3-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 49.6 MB
- Tags: CPython 3.12+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
56f08b05b62601afb272726953ae487e69896e78fbed185c22695c42076ab50e
|
|
| MD5 |
cf9f1eb27c7e9e578dc12da85ceb1a21
|
|
| BLAKE2b-256 |
2eec975817ba25da7acea7b4dbe099c1810c39b488a3efd2c3a144b329679e70
|
Provenance
The following attestation bundles were made for pyeryx-0.4.3-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
python-release.yml on eryx-org/eryx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyeryx-0.4.3-cp312-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
56f08b05b62601afb272726953ae487e69896e78fbed185c22695c42076ab50e - Sigstore transparency entry: 937717970
- Sigstore integration time:
-
Permalink:
eryx-org/eryx@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/eryx-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
python-release.yml@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pyeryx-0.4.3-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: pyeryx-0.4.3-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 48.5 MB
- Tags: CPython 3.12+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ca2b7f38e408b16bc4c8a5a4b6aa30e8d27b7169a6f7130feb17598f52a396a7
|
|
| MD5 |
22b620ed7a68ef29f493a64f0bc50290
|
|
| BLAKE2b-256 |
f592ff56b9050d5db62980a1ddd4eaa5ac36bea03de3922d6a8166836a514507
|
Provenance
The following attestation bundles were made for pyeryx-0.4.3-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
python-release.yml on eryx-org/eryx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyeryx-0.4.3-cp312-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
ca2b7f38e408b16bc4c8a5a4b6aa30e8d27b7169a6f7130feb17598f52a396a7 - Sigstore transparency entry: 937717983
- Sigstore integration time:
-
Permalink:
eryx-org/eryx@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/eryx-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
python-release.yml@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pyeryx-0.4.3-cp312-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: pyeryx-0.4.3-cp312-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 48.5 MB
- Tags: CPython 3.12+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f8f8c129bd2fbd27e1ddbaf18396325250f8a3b6e1c6f42643722476ee2497ed
|
|
| MD5 |
7b7e884b84dc8bf74fe69e5d9d5f885d
|
|
| BLAKE2b-256 |
ba095365ce45395160d86a739a389ce13d76424016f9e1da8423e02f5a515c9b
|
Provenance
The following attestation bundles were made for pyeryx-0.4.3-cp312-abi3-macosx_11_0_arm64.whl:
Publisher:
python-release.yml on eryx-org/eryx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyeryx-0.4.3-cp312-abi3-macosx_11_0_arm64.whl -
Subject digest:
f8f8c129bd2fbd27e1ddbaf18396325250f8a3b6e1c6f42643722476ee2497ed - Sigstore transparency entry: 937717976
- Sigstore integration time:
-
Permalink:
eryx-org/eryx@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/eryx-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
python-release.yml@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Trigger Event:
workflow_dispatch
-
Statement type:
File details
Details for the file pyeryx-0.4.3-cp312-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: pyeryx-0.4.3-cp312-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 49.0 MB
- Tags: CPython 3.12+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a2ec23a998bf45b0a8dc536a1a84f8cc70b71a28b85c7f531c58cd17bc4d6ff9
|
|
| MD5 |
208c8173fb360956cc6c4f3f4543f07f
|
|
| BLAKE2b-256 |
ba0093bab1b582271f1256d58151c8de280e4d83802a62df178315934be065be
|
Provenance
The following attestation bundles were made for pyeryx-0.4.3-cp312-abi3-macosx_10_12_x86_64.whl:
Publisher:
python-release.yml on eryx-org/eryx
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
pyeryx-0.4.3-cp312-abi3-macosx_10_12_x86_64.whl -
Subject digest:
a2ec23a998bf45b0a8dc536a1a84f8cc70b71a28b85c7f531c58cd17bc4d6ff9 - Sigstore transparency entry: 937717995
- Sigstore integration time:
-
Permalink:
eryx-org/eryx@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Branch / Tag:
refs/heads/main - Owner: https://github.com/eryx-org
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
self-hosted -
Publication workflow:
python-release.yml@55576285e0ba2d45000caef0a9b0da427cfe79d0 -
Trigger Event:
workflow_dispatch
-
Statement type: