Lightweight process sandbox using Landlock, seccomp, and seccomp user notification
Project description
sandlock Python SDK
Python bindings for sandlock, a lightweight process sandbox using Landlock and seccomp. No root, no Docker, no namespaces required.
Requires Linux 6.7+ with Landlock ABI v6.
pip install sandlock
Quick start
from sandlock import Sandbox
sandbox = Sandbox(
fs_readable=["/usr", "/lib", "/lib64", "/bin", "/etc", "/proc", "/dev"],
fs_writable=["/tmp"],
)
result = sandbox.run(["echo", "hello"], timeout=10)
assert result.success
print(result.stdout) # b"hello\n"
API reference
Platform
sandlock.landlock_abi_version() -> int
Return the Landlock ABI version supported by the running kernel. Returns -1 if Landlock is unavailable.
sandlock.min_landlock_abi() -> int
Return the minimum Landlock ABI version required by sandlock (currently 6).
Confine
Apply a Sandbox's Landlock rules to the current process, in
place. No fork, no exec.
from sandlock import Sandbox, confine
confine(Sandbox(
fs_readable=["/usr", "/lib"],
fs_writable=["/tmp"],
))
sandlock.confine(sandbox) -> None
Set PR_SET_NO_NEW_PRIVS and install the sandbox's Landlock ruleset
on the live process. The confinement is irreversible.
Only Landlock fields are honored (fs_readable, fs_writable,
fs_denied); IPC and signal scoping are always applied. Sandbox
config that requires a supervisor or a fresh child (seccomp, network,
resource limits, COW, env, policy_fn, etc.) is rejected rather than
silently ignored. Raises ConfinementError on failure.
Sandbox
sandlock.Sandbox(**kwargs)
Sandbox configuration and runtime handle. Holds both the policy (filesystem,
network, resource limits, etc.) and runtime state. Construct once, then call
run() (blocking) or spawn() + lifecycle methods, or use as a context manager.
All config fields are optional. Unset fields mean "no restriction" unless
noted otherwise. Runtime kwargs (name, policy_fn, init_fn, work_fn)
are set at construction time alongside config fields.
A single Sandbox instance holds at most one running process at a time.
For concurrent execution, create multiple instances.
Runtime kwargs:
name-- sandbox name (also its virtual hostname inside the sandbox). Auto-generated assandbox-{pid}when omitted.policy_fn-- optional callback for dynamic per-event policy decisions (see Dynamic policy).init_fn/work_fn-- callbacks for COW fork mode (see Fork).
Sandbox is a context manager:
with Sandbox(fs_readable=["/usr", "/lib"]) as sb:
result = sb.run(["echo", "hello"])
Filesystem (Landlock)
| Parameter | Type | Default | Description |
|---|---|---|---|
fs_readable |
list[str] |
[] |
Paths the sandbox can read |
fs_writable |
list[str] |
[] |
Paths the sandbox can write |
fs_denied |
list[str] |
[] |
Paths explicitly denied |
workdir |
str | None |
None |
Working directory; enables COW protection |
chroot |
str | None |
None |
Path to chroot into before confinement |
fs_mount |
dict[str, str] |
{} |
Map virtual paths to host directories inside chroot |
cwd |
str | None |
None |
Child working directory |
Network
| Parameter | Type | Default | Description |
|---|---|---|---|
net_allow |
list[str] |
[] |
Outbound endpoint rules. Bare host:port is TCP; protocol prefixes opt others in: tcp://host:port, udp://host:port (or udp://*:* for any UDP), icmp://host (or icmp://* for any ICMP echo via the kernel ping socket — gated by net.ipv4.ping_group_range on the host). Empty = deny all. Raw ICMP is not exposed. |
net_bind |
list[int | str] |
[] |
TCP ports the sandbox may bind (empty = deny all) |
port_remap |
bool |
False |
Transparent TCP port virtualization |
HTTP ACL
Enforce method + host + path rules on HTTP traffic via a transparent
MITM proxy. When http_allow is set, all non-matching HTTP requests are
denied by default. Block rules are checked first and take precedence.
| Parameter | Type | Default | Description |
|---|---|---|---|
http_allow |
list[str] |
[] |
Allow rules in "METHOD host/path" format |
http_deny |
list[str] |
[] |
Block rules in "METHOD host/path" format |
http_ports |
list[int] |
[80] |
TCP ports to intercept (443 added when http_ca is set) |
http_ca |
str | None |
None |
CA certificate for HTTPS MITM |
http_key |
str | None |
None |
CA private key for HTTPS MITM |
Rule format: "METHOD host/path" where method and host can be * for
wildcard, and path supports trailing * for prefix matching. Paths are
normalized (percent-decoding, .. resolution, // collapsing) before
matching to prevent bypasses.
sandbox = Sandbox(
fs_readable=["/usr", "/lib", "/etc"],
http_allow=[
"GET docs.python.org/*",
"POST api.openai.com/v1/chat/completions",
],
http_deny=["* */admin/*"],
)
result = sandbox.run(["python3", "agent.py"])
Chroot with mount mapping
Map host directories into a chroot — like Docker's -v /host:/container
but without kernel bind mounts or root privileges. Each sandbox gets its
own persistent workspace while sharing a read-only rootfs.
sandbox = Sandbox(
chroot="/opt/rootfs",
fs_mount={"/work": "/tmp/sandbox-1/work"},
fs_readable=["/usr", "/bin", "/lib", "/etc"],
cwd="/work",
)
result = sandbox.run(["python3", "task.py"])
Combine with workdir + max_disk for quota-enforced writes:
sandbox = Sandbox(
chroot="/opt/rootfs",
fs_mount={"/work": "/tmp/sandbox-1/work"},
workdir="/tmp/sandbox-1/work",
fs_storage="/tmp/sandbox-1/cow",
max_disk="100M",
on_exit="commit",
fs_readable=["/usr", "/bin", "/lib", "/etc"],
)
Resource limits
| Parameter | Type | Default | Description |
|---|---|---|---|
max_memory |
str | int | None |
None |
Memory limit, e.g. "512M" or int bytes |
max_processes |
int |
64 |
Peak concurrent process limit |
max_open_files |
int | None |
None |
Max file descriptors (RLIMIT_NOFILE) |
max_cpu |
int | None |
None |
CPU throttle as percentage of one core (1-100) |
cpu_cores |
list[int] | None |
None |
CPU cores to pin sandbox to |
num_cpus |
int | None |
None |
Visible CPU count in /proc/cpuinfo |
Syscall filtering (seccomp)
| Parameter | Type | Default | Description |
|---|---|---|---|
extra_deny_syscalls |
list[str] |
[] |
Extra syscall names to block in addition to Sandlock defaults |
extra_allow_syscalls |
list[str] |
[] |
Syscall groups to allow that are blocked by default (e.g. "sysv_ipc" to enable SysV shared memory, semaphores, and message queues) |
Sandlock always applies its default syscall blocklist.
Deterministic execution
| Parameter | Type | Default | Description |
|---|---|---|---|
random_seed |
int | None |
None |
Seed for deterministic getrandom() |
time_start |
datetime | float | str | None |
None |
Start timestamp for time virtualization |
no_randomize_memory |
bool |
False |
Disable ASLR |
no_huge_pages |
bool |
False |
Disable Transparent Huge Pages |
deterministic_dirs |
bool |
False |
Sort directory entries lexicographically |
Environment
| Parameter | Type | Default | Description |
|---|---|---|---|
clean_env |
bool |
False |
Start with minimal environment |
env |
dict[str, str] |
{} |
Variables to set/override in the child |
GPU access
| Parameter | Type | Default | Description |
|---|---|---|---|
gpu_devices |
list[int] | None |
None |
GPU device indices to expose ([] = all) |
Misc
| Parameter | Type | Default | Description |
|---|---|---|---|
uid |
int | None |
None |
Map to given UID inside a user namespace (e.g. 0 for fake root) |
no_coredump |
bool |
False |
Disable core dumps |
COW filesystem isolation
| Parameter | Type | Default | Description |
|---|---|---|---|
fs_storage |
str | None |
None |
Storage directory for the seccomp COW upper layer / deltas |
max_disk |
str | None |
None |
Disk quota for COW storage (e.g. "1G") |
on_exit |
BranchAction |
COMMIT |
COMMIT, ABORT, or KEEP |
on_error |
BranchAction |
ABORT |
COMMIT, ABORT, or KEEP |
sandbox.run(cmd, timeout=None) -> Result
Run a command, capturing stdout and stderr.
cmd-- list of strings (command and arguments).timeout-- max execution time in seconds (float).None= no timeout.
result = sandbox.run(["python3", "-c", "print(42)"], timeout=10.0)
sandbox.spawn(cmd) -> None
Spawn cmd without waiting. Use pid, pause(), resume(), kill(),
and wait() to manage the process lifecycle.
Raises RuntimeError if a process is already running.
Sugar for create(cmd) + start(); use those directly when you need the
fork-park-exec split (e.g. starting several sandboxes in lockstep, or
attaching external tracing to the parked PID before the child execs).
sandbox.create(cmd) -> None
Fork the sandboxed child and install policy. The child is parked between
policy install and execve; call start() to release it. pid is
available after this call but the child is not yet running user code.
Raises RuntimeError if a process is already running.
sandbox.start() -> None
Release a previously create()d child to execve.
Raises RuntimeError if no child has been created.
sandbox.wait() -> Result
Wait for the running process to finish and return its Result.
sandbox.dry_run(cmd, timeout=None) -> DryRunResult
Run a command in a temporary COW layer, then discard all writes. Returns the list of filesystem changes that would have been made.
result = sandbox.dry_run(["sh", "-c", "echo hi > /tmp/out.txt"])
for change in result.changes:
print(change.kind, change.path) # "A /tmp/out.txt"
sandbox.run_interactive(cmd) -> int
Run with inherited stdio (no capture). Returns the exit code.
sandbox.name -> str | None
The sandbox name.
sandbox.pid -> int | None
The child PID while running, None otherwise.
sandbox.is_running -> bool
True if a process is currently running in this sandbox.
sandbox.ports() -> dict[int, int]
Current port mappings {virtual_port: real_port} while running.
Only contains entries where port remapping occurred. Requires port_remap=True.
sandbox.pause() / sandbox.resume() / sandbox.kill()
Send SIGSTOP / SIGCONT / SIGKILL to the sandbox process group.
Raises RuntimeError if the sandbox is not running.
sandbox.checkpoint(save_fn=None) -> Checkpoint
Capture a checkpoint of the running sandbox. See Checkpoint.
Result
Returned by sandbox.run().
| Attribute | Type | Description |
|---|---|---|
success |
bool |
True if exit code is 0 |
exit_code |
int |
Process exit code |
stdout |
bytes |
Captured standard output |
stderr |
bytes |
Captured standard error |
error |
str | None |
Error message on failure |
DryRunResult
Returned by sandbox.dry_run().
Same attributes as Result, plus:
| Attribute | Type | Description |
|---|---|---|
changes |
list[Change] |
Filesystem changes detected |
Change
| Attribute | Type | Description |
|---|---|---|
kind |
str |
"A" (added), "M" (modified), or "D" (deleted) |
path |
str |
Path relative to workdir |
Stage and Pipeline
Chain sandboxed commands with pipes using the | operator:
result = (
sandbox_a.cmd(["echo", "hello"])
| sandbox_b.cmd(["tr", "a-z", "A-Z"])
).run()
assert result.stdout == b"HELLO\n"
sandbox.cmd(args) -> Stage
Create a lazy Stage bound to this sandbox.
pipeline.run(stdout=None, timeout=None) -> Result
Run the pipeline. Each stage's stdout feeds the next stage's stdin.
Gather
Fan multiple producers into one consumer via named pipes. Each
producer's stdout is delivered to the consumer under a label the
consumer reads from a sandlock.inputs dict. This is the structural
primitive behind the XOA pattern: producers and consumer are
independent sandboxes, and the consumer never executes producer code
inside its own LLM call.
from sandlock import Sandbox
planner = Sandbox(...) # writes code
searcher = Sandbox(...) # produces data
executor = Sandbox(...) # consumes both
result = (
searcher.cmd(["python3", "-c", "..."]).as_("data")
+ planner.cmd(["python3", "-c", "..."]).as_("code")
| executor.cmd(["python3", "consume.py"])
).run()
Inside consume.py:
from sandlock import inputs
code = inputs["code"]
data = inputs["data"]
exec(compile(code, "<planner>", "exec"), {"data": data})
stage.as_(name) -> NamedStage
Label a Stage's stdout so the consumer can address it by name.
named_stage + named_stage_or_gather -> Gather
Combine two or more NamedStage values into a Gather. Repeated +
extends the gather:
g = a.as_("x") + b.as_("y") + c.as_("z")
gather | consumer_stage -> GatherPipeline
Compose a Gather with a consumer Stage to form the runnable
pipeline.
gather_pipeline.run(timeout=None) -> Result
Run all producers in parallel; each producer's stdout is wired to a
pipe the consumer reads via inputs[name]. Returns the consumer's
Result.
sandlock.inputs
Lazy dict-like accessor available inside the consumer process. Reads each producer's pipe on first access and caches the value.
from sandlock import inputs
inputs["code"] # str: the producer's full stdout, decoded as utf-8
"data" in inputs # bool
list(inputs.keys()) # ["data", "code"]
The pipe fds are passed via the _SANDLOCK_GATHER env var
(name:fd,name:fd,...); the inputs object parses it on first
access. Users do not interact with the env var directly.
Dynamic policy
Use policy_fn to make per-syscall decisions at runtime:
from sandlock import Sandbox, SyscallEvent, PolicyContext
def my_policy(event: SyscallEvent, ctx: PolicyContext):
if event.category == "network" and event.host == "evil.com":
return True # deny
if event.category == "file" and "/secrets" in (event.path or ""):
ctx.deny_path("/secrets")
return True # deny
return False # allow
sb = Sandbox(..., policy_fn=my_policy)
SyscallEvent
| Attribute | Type | Description |
|---|---|---|
syscall |
str |
Syscall name (e.g. "openat", "connect") |
category |
str |
"file", "network", "process", or "memory" |
pid |
int |
Process ID |
parent_pid |
int |
Parent process ID |
path |
str | None |
File path (for file events) |
host |
str | None |
Hostname (for network events) |
port |
int |
Port number (for network events) |
argv |
tuple[str, ...] | None |
Command arguments (for execve) |
denied |
bool |
Whether this event was already denied by static policy |
Helper methods:
event.path_contains(s)-- True if path contains substring sevent.argv_contains(s)-- True if any argv element contains s
PolicyContext
Methods available inside policy_fn:
| Method | Description |
|---|---|
ctx.restrict_network(ips) |
Restrict to given IP addresses |
ctx.grant_network(ips) |
Allow additional IP addresses |
ctx.restrict_max_memory(bytes) |
Lower memory limit |
ctx.restrict_max_processes(n) |
Lower process limit |
ctx.restrict_pid_network(pid, ips) |
Per-PID network restriction |
ctx.deny_path(path) |
Deny access to a path |
ctx.allow_path(path) |
Remove a previously denied path |
Callback return values:
| Return | Meaning |
|---|---|
None, False, 0 |
Allow |
True, -1 |
Deny (EPERM) |
positive int |
Deny with that errno |
"audit", -2 |
Allow but flag for audit |
Fork
COW fork for parallel execution with shared initialization:
sb = Sandbox(
fs_readable=[...],
init_fn=lambda: load_model(),
work_fn=lambda clone_id: process(clone_id),
)
clones = sb.fork(4) # returns ForkResult with .pids
sandbox.reduce(cmd, fork_result) -> Result
Pipe combined clone output into a reducer command:
result = sandbox.reduce(["python3", "sum.py"], clones)
Checkpoint
Save and restore sandbox state:
sb = Sandbox(...)
# ... start a long-running process ...
cp = sb.checkpoint(save_fn=lambda: my_state_bytes())
cp.save("my-snapshot")
# Later:
cp2 = Checkpoint.load("my-snapshot")
Checkpoint.restore("my-snapshot", restore_fn=lambda data: rebuild(data))
| Method | Description |
|---|---|
cp.save(name, store=None) |
Persist checkpoint to disk |
Checkpoint.load(name, store=None) |
Load from disk |
Checkpoint.restore(name, restore_fn, store=None) |
Load and call restore_fn with app_state |
Checkpoint.list(store=None) |
List saved checkpoint names |
Checkpoint.delete(name, store=None) |
Delete a saved checkpoint |
Properties: cp.name (str), cp.app_state (bytes or None).
Default store: ~/.sandlock/checkpoints/.
Profiles
Load sandbox configuration from TOML files:
Profiles contain sandbox config only; pass the sandbox name at construction: Sandbox(..., name=...).
from sandlock import load_profile, list_profiles
sandbox = load_profile("web-scraper")
names = list_profiles()
Exceptions
SandlockError (base)
+-- SandboxError invalid sandbox configuration
+-- SandboxRuntimeError sandbox lifecycle errors
+-- ForkError fork failed
+-- ChildError child exited abnormally
+-- BranchError COW branch operation failed
| +-- BranchConflictError sibling branch committed (ESTALE)
+-- ConfinementError Landlock/seccomp setup failed
+-- LandlockUnavailableError no Landlock support
+-- SeccompError seccomp filter failed
+-- NotifError notif supervisor error
+-- MemoryProtectError mprotect failed
All exceptions are importable from sandlock.exceptions or directly from
sandlock:
from sandlock import SandlockError, SandboxError, SandboxRuntimeError
Enums
BranchAction
BranchAction.COMMIT-- merge writes on exitBranchAction.ABORT-- discard writesBranchAction.KEEP-- leave branch as-is
MCP integration
Sandboxed tool execution for AI agents. Each tool runs in a per-call sandbox with deny-by-default permissions.
pip install 'sandlock[mcp]'
McpSandbox
from sandlock.mcp import McpSandbox
mcp = McpSandbox(workspace="/tmp/agent", timeout=30.0)
workspace-- directory the sandbox can read (default:"/tmp/sandlock").timeout-- default timeout in seconds per tool call (default:30.0).
mcp.add_tool(name, func, *, description="", capabilities=None, input_schema=None)
Register a local tool. func must be a top-level function in an import-safe
module: the worker imports that module by name and calls the function in a
fresh per-call sandbox. Module-level imports, helpers, constants, and state
are all fine; lambdas, methods, and nested functions are rejected. Guard any
module startup logic under if __name__ == "__main__":.
A tool that declares a parameter named workspace receives the sandbox's
workspace path automatically (injected at call time, hidden from the LLM
schema, and not overridable by the model). No env wiring needed.
# tools.py (an importable module)
import os
def read_file(path: str, *, workspace: str) -> str:
with open(os.path.join(workspace, path)) as f:
return f.read()
import tools
mcp.add_tool("read_file", tools.read_file,
description="Read a file from the workspace",
)
No capabilities = read-only, clean environment, no network. Grant permissions explicitly:
| Capability | Example | Description |
|---|---|---|
fs_writable |
["/tmp/agent"] |
Paths the tool can write to |
net_allow |
["api.example.com:443", "udp://1.1.1.1:53"] |
Outbound endpoints. Bare host:port is TCP; udp://... / icmp://... schemes opt UDP / ICMP echo in. |
env |
{"KEY": "val"} |
Environment variables to pass |
max_memory |
"256M" |
Memory limit |
Any Sandbox field name is accepted as a capability key.
await mcp.add_mcp_session(session)
Discover tools from a remote MCP server. Capabilities are read from
sandlock:* keys in the tool's annotations or meta dict.
await mcp.call_tool(name, arguments=None, *, timeout=None) -> str
Call a tool by name. Local tools run in a per-call sandbox. MCP tools are forwarded to their server session.
result = await mcp.call_tool("read_file", {"path": "data.txt"})
mcp.get_policy(tool_name) -> Sandbox
Return the computed Sandbox for a registered tool.
mcp.tool_definitions_openai() -> list[dict]
Tool definitions in OpenAI function-calling format, for use with chat completion APIs.
mcp.tools -> dict[str, Any]
All registered tools (local and MCP).
MCP server
A standalone MCP server with built-in sandboxed tools (shell, python, read_file, write_file, list_files):
# stdio (for Claude Desktop / Cursor)
sandlock-mcp --workspace /tmp/sandbox
# SSE (remote)
pip install 'sandlock[mcp-remote]'
sandlock-mcp --transport sse --host 0.0.0.0 --port 8080 --workspace /tmp/sandbox
Claude Desktop configuration:
{
"mcpServers": {
"sandlock": {
"command": "sandlock-mcp",
"args": ["--workspace", "/tmp/sandbox"]
}
}
}
policy_for_tool(*, workspace, capabilities=None) -> Sandbox
Build a deny-by-default Sandbox from explicit capabilities. Used
internally by McpSandbox but available for direct use.
capabilities_from_mcp_tool(tool) -> dict
Extract sandlock:* capabilities from an MCP tool's annotations/meta.
License
Apache-2.0
Project details
Release history Release notifications | RSS feed
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 sandlock-0.8.2.tar.gz.
File metadata
- Download URL: sandlock-0.8.2.tar.gz
- Upload date:
- Size: 99.2 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
eb6c6eab366cc76ec4d68efe68336dc4539e635fba16a4750d5a3415de27475a
|
|
| MD5 |
54f5b68a76e371bed84cd01be5ddc6d7
|
|
| BLAKE2b-256 |
2e158075e1cdf54bc8035d4c82df6bd9d94ff02e5755715c54886cc594c95279
|
File details
Details for the file sandlock-0.8.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: sandlock-0.8.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a7f6dda491ccff33d5452d3d14e36a2e65315556135e04fb9f7859b773074239
|
|
| MD5 |
45e17100ee0526fe631b69dc0c3865a0
|
|
| BLAKE2b-256 |
edf5a266641b5b51cfcae9bf9fcadfef0743d44c36ffade8db8b77388b8bacc7
|
File details
Details for the file sandlock-0.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: sandlock-0.8.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.13, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
98aeb14c69fb1d9cc8be28344a1a469285d56ed6d0772e433365c1db7e062771
|
|
| MD5 |
2aac0ed9c2472154c11951ba1bf091cb
|
|
| BLAKE2b-256 |
1cc11c440d4e6f17fe670de8546677c999e21001114d300c1b8a34ed2b693e5c
|
File details
Details for the file sandlock-0.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: sandlock-0.8.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
0867d5fa2a344e26deaeca25a8162d2c098d7815d1f50c1f657397d29d29abaf
|
|
| MD5 |
9ad890631dd09200d304af6ab25a383b
|
|
| BLAKE2b-256 |
a66ec999380a5ee43f8146182f535b7ce39ec6233b005f7d9a4e16d7b8cbc3c6
|
File details
Details for the file sandlock-0.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: sandlock-0.8.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.12, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
6f074f0f772dbfc8cfa88bb837810a5565d110ec5ae6ac2ed6bf1fc8b9f0f566
|
|
| MD5 |
1517ce092533981d5d8f3a96975a7aa7
|
|
| BLAKE2b-256 |
cd94d076e5605a289e94bf9daab9fffc4b7c6ad532b9667b7f772c836eb1962b
|
File details
Details for the file sandlock-0.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: sandlock-0.8.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a945e34aa11bfc25abcd548475e2745106d6717c61f6fa70d9531d80775a9068
|
|
| MD5 |
6db848af43e37b3daed76fbe1af13fb3
|
|
| BLAKE2b-256 |
8dcca7f6bd5a4e19097544360e56944058b92555539d5e0aec765c1b8229584f
|
File details
Details for the file sandlock-0.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: sandlock-0.8.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.11, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7298fec1519698c3ba212c4cdd6e7db7dbce334f45ba3e743abde840e304d3c5
|
|
| MD5 |
fb3c42aa9679d1ba850e8b57a0a387c2
|
|
| BLAKE2b-256 |
a6369a26cd37ad28c2fdbd12f531bcd1168e981f08e9b877676dff8de9b2b469
|
File details
Details for the file sandlock-0.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: sandlock-0.8.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.3 MB
- Tags: CPython 3.10, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
69189cc4a7416c6acd2fb044c07e0418f7520bffbafc8b2d595a63868b68bb85
|
|
| MD5 |
31e203e1b527321428c8a762192b617a
|
|
| BLAKE2b-256 |
e742b281fa66f90a285b26d0efac65dfce7eab20027443ad1a3155a33146b6a8
|
File details
Details for the file sandlock-0.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: sandlock-0.8.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.2 MB
- Tags: CPython 3.10, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.3
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
09aaef0386264f927518685690e1f8c825ddac28a3c5bc08a8c567a42f0fc22f
|
|
| MD5 |
3703b0abcbb60255a0dbfd71a23d6cc0
|
|
| BLAKE2b-256 |
024faa0a2c8d94923367eff8bba5e4e521c4899caacd9a223baaca5e97763ac1
|