waddle-sdk (Python)
The Python frontend for Waddle — supervision for real-world robot policy rollouts. Tier-1 integration is the six-line loop:
import waddle
waddle.init(
project="towels",
robot=waddle.Robot(
name="arm",
action_space=waddle.JointSpace(joints=[f"j{i}" for i in range(7)], rate_hz=50),
),
control=waddle.Control(send=robot.command, hold=robot.hold, resume=robot.resume),
recording_dir="./recordings",
)
with waddle.rollout(task="fold the towel") as ep:
while not ep.done:
obs = get_obs()
action = policy(obs)
action = ep.gate(action, obs) # the only touch point
if action is not None:
send(action)
ep.gate() always answers "what you should send, or None if you must
not send": Pass returns your exact object, Substitute/Blend a fresh
float64 ndarray, Noop and Hold return None. Exiting the with block
before a terminal outcome terminates the episode abort — never success.
A robot that declares named parts (waddle.Composite — a bimanual cell,
say) can be intervened on ONE part at a time, so on such a declaration
Substitute/Blend comes back keyed by part instead: {"right": ndarray}
for a command addressing the right arm — the parts not in the dict are
commanded nothing, "move this part, hold the rest" — and every declared
part, sliced by the declared layout, for a whole-robot one.
ep.last_gate.part names the addressed part (None = the whole robot),
and a dispatched chunk's step values follow the same rule. Report state
back the same way: session.report_proprio(part="right", joint_pos=[...]). Declarations without parts are untouched.
Works fully offline: with recording_dir set, every episode lands as a
sidecar JSON + MCAP (/waddle/actions, /waddle/observations) plus a
manifest.jsonl, no control plane required.
Connect a supervision plane with waddle.init(transport=waddle.Grpc(url, token)) and the same loop is supervised: a teleoperator can intervene, a
reset window can be handed out — and you can hand over a whole episode:
result = waddle.agent("clear the table and stack the cups")
print(result.outcome, result.episode_id, result.detail)
waddle.agent() blocks until the episode reaches an outcome. The invited
agent claims it through the very same intervention machinery a
teleoperator uses, so its actions arrive at the send verb you already
registered; your own gate() ticks would not dispatch in such an episode
anyway (FSM.md E24), which is why this call takes the thread instead of
handing back an episode handle. An ask nobody answers comes back
outcome == "abort" at the deadline — a result, not an exception.
All of the above in one runnable file — a simulated 6-dof arm with a
camera, the loop, and waddle.agent(), offline by default — is
examples/toy_robot.py: uv run python examples/toy_robot.py.
Robot modules (waddle.robots)
Everything above is what you write for a robot Waddle has never heard of.
For one it has, waddle.robots.<vendor> carries that machine's facts and
its driver, and waddle.robots.base carries
everything about driving a robot that is not a vendor fact: the kinematic
twin, the envelope seam, the e-stop latch and the console gesture that
clears it, the reporting loop, and a session's two ends. A vendor module is
then facts + driver + factory and nothing else. The subpackage is opt-in —
import waddle imports none of it.
import waddle
from waddle.robots import yam
rig = yam.bimanual(workspace=WORKSPACE_M, gripper_limits=(0.1, 1.7), sim=True)
with rig.session("towels", transport=waddle.Grpc(url, token)) as session:
result = waddle.agent("stack the cups")
sim is EXPLICIT either way, never inferred: no code path try-imports a
vendor package to decide what you meant. Driving real YAM hardware needs
I2RT's own package, which is not a dependency of this SDK and cannot be an
extra of it — PyPI rejects direct references, and the tree behind it is not
something an install that only supervises a policy should resolve. It is a
documented command instead: yam.I2RT_INSTALL, BUILT from yam.I2RT_PIN so
it cannot drift from the commit those facts are stated against, printed by
the driver when the import fails, and quoted in the root
README. Importing waddle.robots.yam needs none of it.
rig.session(...) exists for the two ends every hand-written version gets
wrong at least once. __enter__ opens the drivers inside the with —
so a bus that will not open unwinds structurally, and a rig that opens half
its arms closes them rather than leaving them energized under a vendor's own
re-send — registers the verbs, calls waddle.init, and starts the reporting
pump. __exit__ runs whatever the body did: on live hardware it holds (still
reporting) until a human says the machine is parked — closing stops the
vendor's command re-send, and the motors' own watchdog then drops all torque
from wherever the mission left the arms — then stops the pump, shuts the
session down and closes the drivers. (A Ctrl-C skips that hold: whoever
typed it is already at the machine. A twin returns at once.)
Finalizing the recording is
no longer a finally: you remembered to write. The pump is always on, not
only for an agent run, so your own loop only gates and applies — there is no
interleaved robot tick to forget, and a session whose thread is blocked
inside waddle.agent() keeps reporting.
Every piece is usable alone
The rig is composition sugar over pieces that each stand on their own — which is the design, not an accident:
| piece | what it is | alone |
|---|---|---|
yam.declaration(...) / rig.robot() |
the waddle.Robot this rig registers |
hand it to waddle.init yourself; nothing else here is involved |
rig.arms() |
one base.Arm per declared part, each an owner's envelope over a driver |
the hardware opens here, never at the factory call |
rig.control(arms) |
the posture as waddle.Control verbs |
send= replaces the envelope wholesale (below) |
rig.pre_reset(arms) |
the default scene reset — refuses a latched scene, homes a twin, vouches for metal without moving it | pass your own callable to waddle.init instead |
rig.pump(session, arms) |
base.RobotPump reporting every part at the declared rate |
RobotPump(tick, rate_hz) runs any tick callable you write |
rig.session(project, ...) |
all of the above, with the two ends | — |
Sugar that cannot be reproduced by hand is a wall, so that claim is a test
rather than a promise: tests/test_yam_session.py wires yam.declaration(),
drivers, base.Arm, waddle.Control, a plain waddle.init, the console
recovery and a RobotPump by hand and asserts the session that opens is
byte-identical to rig.session()'s.
The envelope is yours
Waddle never provides the envelope — the owner's hard safety is the owner's
(see GLOSSARY.md). What ships here is
a parameterized default built from your own numbers, on the one object
every path to the hardware crosses: base.Arm checks width, finiteness, your
declared joint limits, per-step travel against where the unit actually is,
and — only when the rig was given forward kinematics — the FK'd TCP inside
your declared workspace box. It rejects, never clamps: a failing target
is refused WHOLE, the unit holds, and one bounded line names the check. A
clamped command is a command nobody wrote, executed faithfully.
The factory provides the check; you own the envelope by choosing and
parameterising it — or by replacing it. Pass send= to rig.session(...)
(or rig.control(arms, send=...)) and your callable is the whole envelope,
while you keep the twin, the latch, the loop and the console recovery.
Forward kinematics is opt-in and its absence is named rather than filled in:
an arm built without fk reports joint positions only (ee_pose() answers
None instead of inventing a frame), and a workspace box declared without
one is refused at construction rather than silently checking nothing.
Postures
posture= is the one construction-time choice, and it maps to which control
verbs the session registers — nothing else:
posture |
verbs registered | what that buys |
|---|---|---|
"monitor" |
the owner's estop alone |
Nothing may command this robot: the session says so on the wire instead of accepting motion it intends to drop. Where a vendor has a compliant mode the driver is constructed that way too (a monitor YAM opens in zero gravity and then refuses to write), so it is a property of the object rather than of a flag somebody remembered to check. No hold — waddle-core reads a registered hold as a live engage path and refuses any session offering one with no send — and no media plane, which carries the teleoperator's stream as well as the video and so IS an intervention path, refused by the same rule. Watching is undiminished: transport= uplinks proprioception and each camera's declared low-rate stills, recording_dir= keeps the full-rate archive. |
"supervised" |
send, hold, estop |
The ordinary posture: a teleoperator, a reset agent or a Waddle-hosted agent may drive this robot — through the owner's envelope. |
A posture is not an authority decision and adds none: who may command a
robot, when, and under what claim is waddle-core's, identical under both.
Whether a rollout is agent-driven or windowed stays a call-site choice
(waddle.agent() vs waddle.rollout()), never a construction one. For that
authority story in full (which phase hands the lease to whom, what gate()
returns while they hold it, and what a monitor session therefore cannot do),
see docs/lease-lifecycle.md.
The same rule that governs the rest of this package governs robots/: it is
owner-side code that ships in the frontend, it enforces the OWNER's envelope
(limits arithmetic on the owner's own numbers), and it asks nothing about who
may command what. The part an action addresses is the core's answer —
indexed, never validated. See the hollow-frontend checklist below.
Write your own vendor module
A driver is any object with the ten members of base.Driver (kind,
estopped, read, write, hold, estop, re_enable, step, home,
close) — a typing.Protocol, so yours is admitted on its members and never
on its ancestry. kind is your driver's own word for itself, and this layer
reads it in ONE direction: "sim" alone selects the harmless branch of the
two questions it asks (does closing this drop all torque, is homing it a
motion nobody is watching), and every other word is treated as metal.
The rest is a facts table, a driver and a factory. These are the exact lines
tests/test_robots_base.py builds a whole toy vendor module out of and drives
end to end through a real session — declaration, envelope, gate, pump, MCAP
read-back — with nothing vendor-specific in base to help it:
import waddle
from waddle.robots import base
TOY_FACTS = {
# The vendor's own numbers, with their provenance in the comment beside
# them in a real module. A toy crane: two arm joints and a hand.
"joints": ("boom", "stick", "grip"),
"limits": ((-1.0, 1.0), (-1.5, 1.5), (0.0, 1.0)),
"step_caps": (0.10, 0.10, 0.25),
"max_effort_nm": 4.0,
"rate_hz": 20.0,
"home": (0.0, 0.0, 1.0),
}
def toy_driver() -> base.SimDriver:
return base.SimDriver(
TOY_FACTS["home"],
lower=[lo for lo, _ in TOY_FACTS["limits"]],
upper=[hi for _, hi in TOY_FACTS["limits"]],
step_caps=TOY_FACTS["step_caps"],
rate_hz=TOY_FACTS["rate_hz"],
)
def toy_crane(*, posture: str = "supervised") -> base.Rig:
"""The whole of a second vendor module: declare the robot, say how to open
it, hand back a rig."""
space = waddle.JointSpace(
joints=[
waddle.Joint(name=name, min_position=lo, max_position=hi,
max_effort=TOY_FACTS["max_effort_nm"])
for name, (lo, hi) in zip(TOY_FACTS["joints"], TOY_FACTS["limits"])
],
rate_hz=TOY_FACTS["rate_hz"],
chunking=waddle.Chunking(horizon=1, replan="immediate", interp="hold"),
)
def build_arms() -> dict[str, base.Arm]: # the bus opens HERE
return {
"": base.Arm(
part="",
driver=toy_driver(),
joint_names=TOY_FACTS["joints"],
joint_limits=TOY_FACTS["limits"],
step_caps=TOY_FACTS["step_caps"],
rate_hz=TOY_FACTS["rate_hz"],
home_values=TOY_FACTS["home"],
)
}
return base.Rig(
declaration=waddle.Robot(
name="toy-crane", robot_id="toy-crane-01", action_space=space
),
build_arms=build_arms,
rate_hz=TOY_FACTS["rate_hz"],
posture=posture,
)
That is the whole of a second vendor module, and it is a test rather than
a docs snippet in the only sense that survives a year: the claim it makes —
"the base layer carries all of the behaviour" — is true exactly while that
test passes, and the block above is not a retelling of it but the same text,
held to the test's own source by
test_the_published_template_is_these_same_lines. (The two imports are yours;
every line below them is that file's.)
toy_driver() returns the shipped twin because a test has no bus to open.
Yours returns your own driver there — any object with the ten members above —
and a module that ships both takes sim: bool and branches, as
waddle.robots.yam does. Either way it is constructed inside build_arms and
never at import, so the factory call opens no bus and starts no thread: a
program may build a rig and then decide not to run it.
For more than one part, declare a waddle.Composite and return one Arm per
part name (declaration order IS the concatenated action layout). Add fk= to
each Arm if you have forward kinematics, and only then a workspace= box.
Ship the source that can gate a fact next to the facts — waddle.robots.yam
vendors the model its numbers come from (MIT data inside this Apache-2.0
wheel: Third-party content in the wheel)
and tests/test_yam_facts.py compares every one of them against it,
directionally (a declared limit may only be TIGHTER than the model's) — and
where nothing can gate a number, say in the comment which pinned artifact it
came from. An unsourced number is one nothing checks.
Installing
pip install waddle-sdk # control plane included
pip install 'waddle-sdk[teleop]' # + the LiveKit media plane
Two distributions from one source tree (the psycopg / psycopg-binary
shape): waddle-sdk bundles the core built with the grpc control
transport, and the teleop extra adds the exact-pinned waddle-sdk-teleop
wheel, which is the SAME shim built with livekit too. LiveKit's libwebrtc
dependency chain is ~690 MB of build, and an install whose job is to
supervise a policy should not pay for a teleop media plane it will never
open. Either way you import waddle: waddle._native picks the richer
core when it is installed, warns and falls back to the bundled one if the
two versions disagree (a half-upgraded environment), and honours
WADDLE_NO_TELEOP=1.
Third-party content in the wheel
This repo is Apache-2.0 and the wheel carries one deliberate exception:
waddle/robots/yam_data/ is a vendored snapshot of I2RT's YAM robot
description, shipped under its own MIT licence (yam_data/LICENSE, verbatim
from the source repo) and pinned to the upstream commit its README names. It
is data rather than code, text only — the STL meshes are not shipped — and it
earns its 16 KB twice: waddle.robots.yam hands it to a single-arm
declaration as kinematics_urdf, and tests/test_yam_facts.py compares every
constant in that module against the vendor's own numbers in it.
Development
cd sdk
uv sync --dev && uv run pytest # full build + test
uv run maturin develop --uv && uv run --no-sync pytest # iterate on Rust
cargo clippy --manifest-path rust/Cargo.toml --all-targets -- -D warnings
cargo fmt --manifest-path rust/Cargo.toml --check
The shim is its own cargo workspace (rust/) with path-deps into
../waddle-core/crates/*; pyo3's extension-module feature lives only in
[tool.maturin].features so plain cargo check/clippy keep working.
Connected builds
The transports are cargo features on the shim. grpc (the control plane:
create_session(transport_url=, transport_token=)) is in the DEFAULT
build, so uv sync --dev/maturin develop already carry it; livekit
(the media plane: media_url=, media_token= — the plane mints both
tokens, this SDK never does) is not, since it belongs to the
waddle-sdk-teleop companion:
uv run maturin develop --uv --features grpc,livekit # the companion's flavour
cargo clippy --manifest-path rust/Cargo.toml --features grpc,livekit --all-targets -- -D warnings
Clippy must be clean featureless, --features grpc, and
--features grpc,livekit. A build that lacks a feature refuses the
matching kwarg rather than running offline in silence.
waddle._native.FEATURES is the probe, not waddle._core.FEATURES:
_native selects which core this process runs on and re-exports that
core's features, so on a [teleop] install waddle._core.FEATURES still
reports the bundled core's grpc-only set while the process is running the
teleop core. It is the only feature detection the Python layer does, and
two places read it — _native itself, to pick a core, and init(), to
refuse a transport=/media= this build cannot honour.
The companion wheel is sdk/teleop/pyproject.toml: same
manifest-path = "../rust/Cargo.toml" (hence the same version by
construction), module-name = "waddle_teleop._core", features
grpc,livekit. sdk/pyproject.toml's [tool.uv.sources] points the
teleop extra at it so uv can resolve the lock; nothing builds it
unless the extra is actually installed. The extra's exact pin
(waddle-sdk-teleop==X) is the ONE version here that maturin cannot
derive from the manifest, so a version bump must edit it too —
tests/test_features.py holds it to waddle.__version__ (and the two
projects to one manifest) rather than to memory.
Hollow-frontend checklist (review gate for every change here)
All claim/lease/handoff/timeline logic lives in waddle-core exactly once. Concretely, in this package:
- No Python variable ever holds gate mode, claim id, lease id, or engage
stage; the Noop/Hold→
Nonemapping marshals a core decision, it is not anifabout claims. - No handoff math (blend, chunk-boundary waits, HOLD_FIRST sequencing,
retake/successor logic) — Python only declares
Handoff. - No FSM/timeline:
ep.done/ep.outcomeare single reads of the core mirror; no Python timers, stall detection, or state mirroring. - No tripwire evaluation, reset verification, grant negotiation/demotion logic; no provenance computation (strings surfaced verbatim); no recording writes (the core reducer owns all recording).
- Reset API (
TeleopReset/AgentReset,init(pre_reset=, post_reset=, reset_verification=),rollout(pre_reset=, post_reset=)): the markers and callables are pure config — which reset kind string names a marker's type, and normalizing a hook's return shape to(bool, Optional[bool]), are type dispatch and input-shape validation, not reset decisions. Every actual behavior (whichResetStrategyruns, howreset_verificationgates the RESETTING→READY transition, the window's claim/lease/gate-mode sequencing,post_reset_failed's permanence, the outcome-pinning at POST_RESET entry) lives in waddle-core; Python never branches on any of it. - Connected build (
waddle.Grpc/waddle.LiveKit, thetransport_url/media_urlkwargs,FEATURES): URLs and tokens are config handed to core constructors; nothing here inspects a connection. Feature detection answers "can this build do it at all", never "what should happen now" — no branch on plane state, negotiated flags, or connectivity.waddle._native's core selection is packaging, decided once at import, and the only stateinitrecords about a session is whether a plane was declared at all (a declaration fact, not plane state). - Feature raises key off
_native.FEATURES, never a try-import. Atry: ... except (ImportError, AttributeError)reads as "can this build do it?" and answers "did this particular call happen to fail?", so a genuine runtime error becomes a not-compiled message and the user chases the wrong thing.FEATURESis a build fact the core states outright. Teleop-only surfaces must name the extra in the error text (pip install 'waddle-sdk[teleop]'): the caller cannot act on "not compiled" alone, and the whole point of the two-wheel split is that this is a one-command fix rather than a rebuild. - Agent runs (
waddle.agent,Session.agent): a prompt goes in, anAgentResultcomes out. The invite, its deadline, who may claim the episode, and what the caller's own ticks do meanwhile are all FSM rows; Python refuses early only when there is nobody to ask. The only other decision made here is when to reattach and run Python's signal handlers. - Part-keyed payloads (
Compositesessions: dict-by-partgate()returns andChunkstep values,report_proprio(part=)): the layout is read off the customer's own declaration — each part's name and width, in declaration order — and applied as arithmetic to a row the core already decided. Which part an action addresses is the core's answer (Step.part/OwnedAction.part, honored only under a negotiatedwaddle.v0.parts); Python never decides it, never validates a part name (the core refuses an undeclared one), and must never grow anifabout which part may command what — that is authority, and v0's lease is whole-robot single-writer. - Review heuristic: descriptors may validate shape ("must declare"), never behavior.
Private test hooks
waddle._testing (engage/release/push_teleop/push_chunk/
reset_window_engage/reset_window_complete/mark_done/frames) requires
waddle.init(_testing=True), which wires an in-process loopback media
plane. Private and unstable — it exists so the intervention, remote-reset-
window and agent-invited paths are testable with no real plane at all. Each
hook stands in for one thing a plane would send: mark_done, for instance,
is an EpisodeDirective{MARK_DONE} — the only way to end a
waddle.agent() run in a test, since its caller is blocked and holds no
episode handle. Because it stands in for a plane, _testing=True counts as
a plane declaration for waddle.agent()'s "nobody to ask" refusal, exactly
as a transport does.
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distributions
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 waddle_sdk-0.0.0-cp310-abi3-win_amd64.whl.
File metadata
- Download URL: waddle_sdk-0.0.0-cp310-abi3-win_amd64.whl
- Upload date:
- Size: 3.1 MB
- Tags: CPython 3.10+, Windows x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
bdfefafa0ef3dfdb7490be9b47caad5805c37eb9df2cad2f72b8d54aaabf1d98
|
|
| MD5 |
b68238c4d677c0f60241bb42212ea7dc
|
|
| BLAKE2b-256 |
d2bbd6b2b97ed153c8c6b2b7d615edcacb9774e5214e70acb0474dd0e061d458
|
Provenance
The following attestation bundles were made for waddle_sdk-0.0.0-cp310-abi3-win_amd64.whl:
Publisher:
release.yml on waddlelabs/waddle-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waddle_sdk-0.0.0-cp310-abi3-win_amd64.whl -
Subject digest:
bdfefafa0ef3dfdb7490be9b47caad5805c37eb9df2cad2f72b8d54aaabf1d98 - Sigstore transparency entry: 2342934120
- Sigstore integration time:
-
Permalink:
waddlelabs/waddle-sdk@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Branch / Tag:
refs/tags/v0.0.0 - Owner: https://github.com/waddlelabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Trigger Event:
push
-
Statement type:
File details
Details for the file waddle_sdk-0.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.
File metadata
- Download URL: waddle_sdk-0.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
- Upload date:
- Size: 3.8 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
e68ad421a25ffc62affa8aed02b0e0d1a15d897edb38b48d7a68de0294043592
|
|
| MD5 |
3853b54f1ddae5e07f8a5ff8a4964851
|
|
| BLAKE2b-256 |
e40511a01baf309c8a64841abf8a4ab5da82c3f1746b50a31c1d1b4f4d69bf97
|
Provenance
The following attestation bundles were made for waddle_sdk-0.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:
Publisher:
release.yml on waddlelabs/waddle-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waddle_sdk-0.0.0-cp310-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl -
Subject digest:
e68ad421a25ffc62affa8aed02b0e0d1a15d897edb38b48d7a68de0294043592 - Sigstore transparency entry: 2342934108
- Sigstore integration time:
-
Permalink:
waddlelabs/waddle-sdk@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Branch / Tag:
refs/tags/v0.0.0 - Owner: https://github.com/waddlelabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Trigger Event:
push
-
Statement type:
File details
Details for the file waddle_sdk-0.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.
File metadata
- Download URL: waddle_sdk-0.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
- Upload date:
- Size: 3.8 MB
- Tags: CPython 3.10+, manylinux: glibc 2.17+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7e4e52cfe23bbf597240a0088d9ab525b4786a3c395b1cd8a71b60049691599c
|
|
| MD5 |
3c652e502a07989691fe7804a27fbf45
|
|
| BLAKE2b-256 |
769039e4c49e28f2b9f7f9f5f853d385572aa1ab3a37664d3e328b8e90be9b2a
|
Provenance
The following attestation bundles were made for waddle_sdk-0.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:
Publisher:
release.yml on waddlelabs/waddle-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waddle_sdk-0.0.0-cp310-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl -
Subject digest:
7e4e52cfe23bbf597240a0088d9ab525b4786a3c395b1cd8a71b60049691599c - Sigstore transparency entry: 2342934054
- Sigstore integration time:
-
Permalink:
waddlelabs/waddle-sdk@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Branch / Tag:
refs/tags/v0.0.0 - Owner: https://github.com/waddlelabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Trigger Event:
push
-
Statement type:
File details
Details for the file waddle_sdk-0.0.0-cp310-abi3-macosx_11_0_arm64.whl.
File metadata
- Download URL: waddle_sdk-0.0.0-cp310-abi3-macosx_11_0_arm64.whl
- Upload date:
- Size: 3.4 MB
- Tags: CPython 3.10+, macOS 11.0+ ARM64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
9be8093e33406629669cebae1b48a2375e305577b2195ad112334459d0c036d0
|
|
| MD5 |
a465b953887463cfe2b90307b747ced9
|
|
| BLAKE2b-256 |
03281f9d6ff05a319d216f7319ca0f9a028167c84195e5b5180395539c17afcf
|
Provenance
The following attestation bundles were made for waddle_sdk-0.0.0-cp310-abi3-macosx_11_0_arm64.whl:
Publisher:
release.yml on waddlelabs/waddle-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waddle_sdk-0.0.0-cp310-abi3-macosx_11_0_arm64.whl -
Subject digest:
9be8093e33406629669cebae1b48a2375e305577b2195ad112334459d0c036d0 - Sigstore transparency entry: 2342934090
- Sigstore integration time:
-
Permalink:
waddlelabs/waddle-sdk@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Branch / Tag:
refs/tags/v0.0.0 - Owner: https://github.com/waddlelabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Trigger Event:
push
-
Statement type:
File details
Details for the file waddle_sdk-0.0.0-cp310-abi3-macosx_10_12_x86_64.whl.
File metadata
- Download URL: waddle_sdk-0.0.0-cp310-abi3-macosx_10_12_x86_64.whl
- Upload date:
- Size: 3.5 MB
- Tags: CPython 3.10+, macOS 10.12+ x86-64
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
52d1853a08b536535346ea6b7be5ea0a4e0086af3df30610ea263f7b585f6028
|
|
| MD5 |
7fb1d248840f3d2675961f354afaafcf
|
|
| BLAKE2b-256 |
8dcd5fbb5acd8c328db8a336b78760f18c1b706b23d2ff3eb9acb0708721bfd6
|
Provenance
The following attestation bundles were made for waddle_sdk-0.0.0-cp310-abi3-macosx_10_12_x86_64.whl:
Publisher:
release.yml on waddlelabs/waddle-sdk
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
waddle_sdk-0.0.0-cp310-abi3-macosx_10_12_x86_64.whl -
Subject digest:
52d1853a08b536535346ea6b7be5ea0a4e0086af3df30610ea263f7b585f6028 - Sigstore transparency entry: 2342934071
- Sigstore integration time:
-
Permalink:
waddlelabs/waddle-sdk@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Branch / Tag:
refs/tags/v0.0.0 - Owner: https://github.com/waddlelabs
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@249ced4b5a31ce5ceb283fe78510923e8af54375 -
Trigger Event:
push
-
Statement type: