Skip to main content

A multi-threaded async runtime

Project description

TonIO

TonIO is a multi-threaded async runtime for free-threaded Python, built in Rust on top of the mio crate, and inspired by tinyio, trio and tokio.

Warning: TonIO is currently a work in progress and in alpha state. The APIs are subtle to breaking changes.

Note: TonIO is available on free-threaded Python and Unix systems only.

TonIO supports both using yield and the more canonical async/await notations, with the latter being available as part of the tonio.colored module. Following code snippets show both the usages.

Warning: despite the fact TonIO supports async and await notations, it's not compatible with any asyncio object like futures and tasks.

In a nutshell

yield syntax

import tonio

def wait_and_add(x: int) -> int:
    yield tonio.sleep(1)
    return x + 1

def foo():
    four, five = yield tonio.spawn(
        wait_and_add(3), 
        wait_and_add(4)
    )
    return four, five

out = tonio.run(foo())
assert out == (4, 5)

await syntax

import tonio.colored as tonio

async def wait_and_add(x: int) -> int:
    await tonio.sleep(1)
    return x + 1

async def foo():
    four, five = await tonio.spawn(
        wait_and_add(3), 
        wait_and_add(4)
    )
    return four, five

out = tonio.run(foo())
assert out == (4, 5)

Usage

Entrypoint

Every TonIO program consist of an entrypoint, which should be passed to the run method:

yield syntax

import tonio

def main():
    yield
    print("Hello world")

tonio.run(main())

await syntax

import tonio.colored as tonio

async def main():
    await tonio.yield_now()
    print("Hellow world")

tonio.run(main())

TonIO also provides a main decorator, thus we can rewrite the previous example as:

yield syntax

import tonio

@tonio.main
def main():
    yield
    print("Hello world")

main()

await syntax

import tonio.colored as tonio

@tonio.main
async def main():
    await tonio.yield_now()
    print("Hello world")

main()

Note: as you can see the colored module provides the additional yield_now coroutine, a quick way to define a suspension point, given you cannot just yield as in the non-colored notation.

Note: both run and main can only be called once per program. To run the runtime multiple times in the same program, follow the section below.

Manually managing the runtime

TonIO also provides the runtime function, to manually manage the runtime lifecycle:

import tonio

def _run1():
    ...

async def _run2():
    ...

def main():
    runtime = tonio.runtime()
    runtime.run_until_complete(_run1())
    runtime.run_until_complete(_run2())

Runtime options

The run, main and runtime methods accept options, specifically:

option name description default
context enable contextvars usage in coroutines False
signals list of signals to listen to
threads Number of runtime threads # of CPU cores
blocking_threadpool_size Maximum number of blocking threads 128
blocking_threadpool_idle_ttl Idle timeout for blocking threads (in seconds) 30

Events

The core object in TonIO is Event. It's basically a wrapper around an atomic boolean flag, initialised with False. Event provides the following methods:

  • is_set(): return the value of the flag
  • set(): set the flag to True
  • clear(): set the flag to False
  • wait(timeout=None): returns a coroutine you can yield on that unblocks when the flag is set to True or the timeout expires. Timeout is in seconds.

yield syntax

import tonio

@tonio.main
def main():
    event = tonio.Event()

    def setter():
        yield tonio.sleep(1)
        event.set()

    tonio.spawn(setter())
    yield event.wait()

await syntax

import tonio.colored as tonio

@tonio.main
async def main():
    event = tonio.Event()

    async def setter():
        await tonio.sleep(1)
        event.set()

    tonio.spawn(setter())
    await event.wait()

Spawning tasks

TonIO provides the spawn method to schedule new coroutines onto the runtime:

yield syntax

import tonio

def doubv(v):
    yield
    return v * 2

@tonio.main
def main():
    parallel = tonio.spawn(doubv(2), doubv(3))
    v3 = yield doubv(4)
    v1, v2 = yield parallel
    print([v1, v2, v3])

await syntax

import tonio.colored as tonio

async def doubv(v):
    await tonio.yield_now()
    return v * 2

@tonio.main
async def main():
    parallel = tonio.spawn(doubv(2), doubv(3))
    v3 = await doubv(4)
    v1, v2 = await parallel
    print([v1, v2, v3])

Coroutines passed to spawn get schedule onto the runtime immediately. Using yield or await on the return value of spawn just waits for the coroutines to complete and retreive the results.

Blocking tasks

TonIO provides the spawn_blocking method to schedule blocking operations onto the runtime:

yield syntax

import tonio

def read_file(path):
    with open(file, "r") as f:
        return f.read()

@tonio.main
def main():
    file_data = yield tonio.spawn_blocking(
        read_file, 
        "sometext.txt"
    )

await syntax

import tonio.colored as tonio

def read_file(path):
    with open(file, "r") as f:
        return f.read()

@tonio.main
async def main():
    file_data = await tonio.spawn_blocking(
        read_file, 
        "sometext.txt"
    )

Running tasks from synchronous contexts

TonIO provides the block_on method to spawn coroutines from a synchronous context. It works the same way of spawn, except it accepts a single coroutine and it blocks the current thread until the coroutine is completed.

Warning: using block_on from within a coroutine might produce a runtime deadlock.

Map utilities

TonIO provides the map and map_blocking utilities to spawn the same operation with an iterable of parameters:

yield syntax

import tonio

accum = []

def task(no):
    yield tonio.sleep(0.5)
    accum.append(no * 2)

@tonio.main
def main():
    yield tonio.map(task, range(4))

await syntax

import tonio.colored as tonio

accum = []

async def task(no):
    await tonio.sleep(0.5)
    accum.append(no * 2)

@tonio.main
async def main():
    await tonio.map(task, range(4))

Scopes and cancellations

TonIO provides a scope context, that lets you cancel work spawned within it:

yield syntax

import tonio

def slow_push(target, sleep):
    yield tonio.sleep(sleep)
    target.append(True)

@tonio.main
def main():
    values = []
    with tonio.scope() as scope:
        scope.spawn(_slow_push(values, 0.1))
        scope.spawn(_slow_push(values, 2))
        yield tonio.sleep(0.2)
        scope.cancel()
    yield scope()
    assert len(values) == 1

await syntax

import tonio.colored as tonio

async def slow_push(target, sleep):
    await tonio.sleep(sleep)
    target.append(True)

@tonio.main
async def main():
    values = []
    async with tonio.scope() as scope:
        scope.spawn(_slow_push(values, 0.1))
        scope.spawn(_slow_push(values, 2))
        await tonio.sleep(0.2)
        scope.cancel()
    assert len(values) == 1

When you yield on the scope, it will wait for all the spawned coroutines to end. If the scope was canceled, then all the pending coroutines will be canceled.

Note: as you can see, the colored version of scope doesn't require to be awaited, as it will yield when exiting the context.

Select first completing task

TonIO also provides a select utility to cancel remaining work on the first completing task:

yield syntax

import tonio

def slow_push(target, sleep):
    yield tonio.sleep(sleep)
    target.append(True)

@tonio.main
def main():
    values = []
    yield tonio.select(
        _slow_push(values, 0.1),
        _slow_push(values, 2)
    )
    assert len(values) == 1

await syntax

import tonio.colored as tonio

async def slow_push(target, sleep):
    await tonio.sleep(sleep)
    target.append(True)

@tonio.main
async def main():
    values = []
    await tonio.select(
        _slow_push(values, 0.1),
        _slow_push(values, 2)
    )
    assert len(values) == 1

Time-related functions

  • tonio.time.time(): a function returning the runtime's clock (in seconds, microsecond resolution)
  • tonio.time.sleep(delay): a coroutine you can yield on to sleep (delay is in seconds)
  • tonio.time.timeout(coro, timeout): a coroutine you can yield on returning a tuple (output, success). If the coroutine succeeds in the given time then the pair (output, True) is returned. Otherwise this will return (None, False).

Note: time.sleep is also exported to the main tonio module.

Note: all of the above functions are also present in tonio.colored.time module.

Scheduling work

TonIO provides the time.interval function to create interval objects you can yield on a scheduled basis:

yield syntax

import tonio
from tonio import time

def some_task():
    ...

def scheduler():
    interval = time.interval(1)
    while True:
        yield interval.tick()
        tonio.spawn(some_task())

@tonio.main
def main():
    tonio.spawn(scheduler())
    # do some other work

await syntax

import tonio.colored as tonio
from tonio.colored import time

async def some_task():
    ...

async def scheduler():
    interval = time.interval(1)
    while True:
        await interval.tick()
        tonio.spawn(some_task())

@tonio.main
async def main():
    tonio.spawn(scheduler())
    # do some other work

The interval method first argument is the interval in seconds resolution, and the method also accepts an optional at argument, to delay the first execution at a specific time (from the runtime's clock perspective):

from tonio import time

# tick every 500ms, with the first tick happening in 5 seconds from now
interval = time.interval(0.5, time.time() + 5)

Synchronization primitives

Synchronization primitives are exposed in the tonio.sync module.

Lock

Implements a classic mutex, or a non-reentrant, single-owner lock for coroutines:

yield syntax

import tonio
from tonio import sync

@tonio.main
def main():
    # counter can't go above 1
    counter = 0

    def _count(lock):
        nonlocal counter
        with (yield lock()):
            counter += 1
            yield
            counter -= 1
    
    lock = sync.Lock()
    yield tonio.spawn(*[
        _count(lock)
        for _ in range(10)
    ])

await syntax

import tonio.colored as tonio
from tonio.colored import sync

@tonio.main
async def main():
    # counter can't go above 1
    counter = 0

    async def _count(lock):
        nonlocal counter
        async with lock:
            counter += 1
            await tonio.yield_now()
            counter -= 1
    
    lock = sync.Lock()
    await tonio.spawn(*[
        _count(lock)
        for _ in range(10)
    ])

The Lock object also implements an or_raise method, that will immediately fail when the lock cannot be acquired:

from tonio.exceptions import WouldBlock

try:
    with lock.or_raise():
        ...
except WouldBlock:
    ...

Semaphore

A semaphore for coroutines:

yield syntax

import tonio
from tonio import sync

@tonio.main
def main():
    # counter can't go above 2
    counter = 0

    def _count(semaphore):
        nonlocal counter
        with (yield semaphore()):
            counter += 1
            yield
            counter -= 1
    
    semaphore = sync.Semaphore(2)
    yield tonio.spawn(*[
        _count(semaphore)
        for _ in range(10)
    ])

await syntax

import tonio.colored as tonio
from tonio.colored import sync

@tonio.main
async def main():
    # counter can't go above 2
    counter = 0

    async def _count(semaphore):
        nonlocal counter
        async with semaphore:
            counter += 1
            await tonio.yield_now()
            counter -= 1
    
    semaphore = sync.Semaphore(2)
    await tonio.spawn(*[
        _count(semaphore)
        for _ in range(10)
    ])

As for locks, the Semaphore object also implements an or_raise method, that will immediately fail when the lock cannot be acquired:

from tonio.exceptions import WouldBlock

try:
    with semaphore.or_raise():
        ...
except WouldBlock:
    ...

The Semaphore object also implements a tokens method, that returns the number of available tokens.

Barrier

A barrier for coroutines:

yield syntax

import tonio
from tonio import sync

@tonio.main
def main():
    barrier = sync.Barrier(3)
    count = 0

    def _start_at_3():
        nonlocal count
        count += 1
        i = yield barrier.wait()
        assert count == 3
        return i

    yield tonio.spawn(*[
        _start_at_3()
        for _ in range(3)
    ])

await syntax

import tonio.colored as tonio
from tonio.colored import sync

@tonio.main
async def main():
    barrier = sync.Barrier(3)
    count = 0

    async def _start_at_3():
        nonlocal count
        count += 1
        i = await barrier.wait()
        assert count == 3
        return i

    await tonio.spawn(*[
        _start_at_3()
        for _ in range(3)
    ])

The Barrier object also implements a value method, which returns the current value of the barrier.

Channels

Multi-producer multi-consumer channels for inter-coroutine communication.

The tonio.sync.channel module provides both a channel and an unbounded constructors.
The main difference between bounded and unbounded channels, as the names suggest, is that while the first will suspend sending messages once the specified length is reached, and it will resume accepting messages once the existing buffer is consumed, the latter will always accept new messages. That's also why, the sender part of a bounded channel is async, while in the unbounded is not.

Bounded channel

yield syntax

import tonio
from tonio import sync
from tonio.sync import channel

def producer(sender, barrier, offset):
    for i in range(20):
        message = offset + 1
        yield sender.send(message)
    yield barrier.wait()

def consumer(receiver):
    while True:
        try:
            message = yield receiver.receive()
            print(message)
        except Exception:
            break

@tonio.main
def main():
    def close(sender, barrier):
        yield barrier.wait()
        sender.close()

    sender, receiver = channel.channel(2)
    barrier = sync.Barrier(3)
    yield tonio.spawn(*[
        producer(sender, barrier, 100),
        producer(sender, barrier, 200),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        close(sender, barrier),
    ])

await syntax

import tonio.colored as tonio
from tonio.colored import sync
from tonio.colored.sync import channel

async def producer(sender, barrier, offset):
    for i in range(20):
        message = offset + 1
        await sender.send(message)
    await barrier.wait()

async def consumer(receiver):
    while True:
        try:
            message = await receiver.receive()
            print(message)
        except Exception:
            break

@tonio.main
async def main():
    async def close(sender, barrier):
        await barrier.wait()
        sender.close()

    sender, receiver = channel.channel(2)
    barrier = sync.Barrier(3)
    await tonio.spawn(*[
        producer(sender, barrier, 100),
        producer(sender, barrier, 200),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        close(sender, barrier),
    ])
Unbounded channel

yield syntax

import tonio
from tonio import sync
from tonio.sync import channel

def producer(sender, barrier, offset):
    for i in range(20):
        message = offset + 1
        sender.send(message)
    yield barrier.wait()

def consumer(receiver):
    while True:
        try:
            message = yield receiver.receive()
            print(message)
        except Exception:
            break

@tonio.main
def main():
    def close(sender, barrier):
        yield barrier.wait()
        sender.close()

    sender, receiver = channel.unbounded()
    barrier = sync.Barrier(3)
    yield tonio.spawn(*[
        producer(sender, barrier, 100),
        producer(sender, barrier, 200),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        close(sender, barrier),
    ])

await syntax

import tonio.colored as tonio
from tonio.colored import sync
from tonio.colored.sync import channel

async def producer(sender, barrier, offset):
    for i in range(20):
        message = offset + 1
        sender.send(message)
    await barrier.wait()

async def consumer(receiver):
    while True:
        try:
            message = await receiver.receive()
            print(message)
        except Exception:
            break

@tonio.main
async def main():
    async def close(sender, barrier):
        await barrier.wait()
        sender.close()

    sender, receiver = channel.unbounded()
    barrier = sync.Barrier(3)
    await tonio.spawn(*[
        producer(sender, barrier, 100),
        producer(sender, barrier, 200),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        consumer(receiver),
        close(sender, barrier),
    ])

Network module

Network primitives are exposed under the tonio.net module.

Streams

The high-level network primitives in TonIO are centered aroud the SocketStream and SocketListener objects.

The SocketListener object implements an accept coroutine which returns a SocketStream object.
The SocketStream object implements the send_all and receive_some coroutines to send and receive data.
Both objects implement a close method to shutdown the underlying socket.

You can create and interact with the above objects using some high-level helpers in the net module, specifically:

  • open_tcp_stream: a coroutine to open a SocketStream connected to a TCP endpoint
  • open_unix_socket: a coroutine to open a SocketStream connected to an Unix socket
  • open_tcp_listeners: a coroutine to initialise SocketListener objects
  • serve_listeners: a coroutine to spawn SocketListener accept loops targeting a handler
  • serve_tcp: a coroutine that join open_tcp_listener and serve_listeners in one call

yield syntax

from tonio.net import open_tcp_stream, serve_tcp

def server():
    yield serve_tcp(
        server_handle, 
        host='127.0.0.1', 
        port=8000
    )

def server_handle(stream):
    # receive some data
    data = yield stream.receive_some()

def client():
    stream = yield open_tcp_stream(
        host='127.0.0.1', 
        port=8000
    )
    # send some data
    yield stream.send_all("message")

await syntax

from tonio.colored.net import open_tcp_stream, serve_tcp

async def server():
    await serve_tcp(
        server_handle, 
        host='127.0.0.1', 
        port=8000
    )

async def server_handle(stream):
    # receive some data
    data = await stream.receive_some()

async def client():
    stream = await open_tcp_stream(
        host='127.0.0.1', 
        port=8000
    )
    # send some data
    await stream.send_all("message")

TLS streams

TonIO implement TLS wrappers around the streaming APIs through primitives in the tonio.net.tls module.

TonIO provides the TLSStream and TLSListener object wrappers and the following high-level helpers:

  • open_tls_over_tcp_stream: a coroutine to open a TLSStream wrapping a TCP SocketStream
  • open_tls_over_tcp_listeners: a coroutine to initialise TLSListener objects
  • serve_tls_over_tcp: a coroutine that join open_tls_over_tcp_listeners and serve_listeners in one call

Low-level sockets

The tonio.net.socket module provides TonIO's basic low-level networking API.
Generally, the API exposed by this module mirrors the standard library socket module.

TonIO socket objects are overall very similar to the standard library socket objects, with the main difference being that blocking methods become coroutines.

yield syntax

import tonio
from tonio.net import socket

def server():
    sock = socket.socket()
    with sock:
        yield sock.bind(('127.0.0.1', 8000))
        sock.listen()

        while True:
            client, _ = yield sock.accept()
            tonio.spawn(server_handle(client))

def server_handle(connection):
    with connection:
        # receive some data
        data = yield connection.recv(4096)

def client():
    sock = socket.socket()
    with sock:
        yield sock.connect(('127.0.0.1', 8000))
        yield sock.send("message")

await syntax

import tonio.colored as tonio
from tonio.colored.net import socket

async def server():
    sock = socket.socket()
    with sock:
        await sock.bind(('127.0.0.1', 8000))
        sock.listen()

        while True:
            client, _ = await sock.accept()
            tonio.spawn(server_handle(client))

async def server_handle(connection):
    with connection:
        # receive some data
        data = await connection.recv(4096)

async def client():
    sock = socket.socket()
    with sock:
        await sock.connect(('127.0.0.1', 8000))
        await sock.send("message")

Signals

TonIO provides a context manager to catch signals.

The usage of such context manager requires to first configure the runtime to listen for such signals:

yield syntax

import signal
import tonio
from tonio.time import interval

def sig_handle():
    with tonio.signal_receiver(
        signal.SIGHUP, 
        signal.SIGUSR1
    ) as sigs:
        for ev in sigs:
            sig = yield ev
            if sig == signal.SIGHUP:
                ...

@tonio.main(
    signals=[signal.SIGHUP, signal.SIGUSR1]
)
def main():
    tonio.spawn(sig_handle())
    ticker = interval(1)
    while True:
        yield ticker.tick()

await syntax

import signal
import tonio.colored as tonio
from tonio.colored.time import interval

async def sig_handle():
    with tonio.signal_receiver(
        signal.SIGHUP, 
        signal.SIGUSR1
    ) as sigs:
        async for sig in sigs:
            if sig == signal.SIGHUP:
                ...

@tonio.main(
    signals=[signal.SIGHUP, signal.SIGUSR1]
)
async def main():
    tonio.spawn(sig_handle())
    ticker = interval(1)
    while True:
        await ticker.tick()

License

TonIO is released under the BSD License.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tonio-0.5.0.tar.gz (59.2 kB view details)

Uploaded Source

Built Distributions

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

tonio-0.5.0-cp314-cp314t-musllinux_1_1_x86_64.whl (615.6 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ x86-64

tonio-0.5.0-cp314-cp314t-musllinux_1_1_armv7l.whl (676.0 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARMv7l

tonio-0.5.0-cp314-cp314t-musllinux_1_1_aarch64.whl (562.4 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARM64

tonio-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (401.4 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64

tonio-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (399.6 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARMv7l

tonio-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (385.0 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARM64

tonio-0.5.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl (431.3 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.12+ i686

tonio-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl (348.4 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

tonio-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl (369.0 kB view details)

Uploaded CPython 3.14tmacOS 10.12+ x86-64

tonio-0.5.0-cp313-cp313t-musllinux_1_1_x86_64.whl (620.2 kB view details)

Uploaded CPython 3.13tmusllinux: musl 1.1+ x86-64

tonio-0.5.0-cp313-cp313t-musllinux_1_1_armv7l.whl (675.7 kB view details)

Uploaded CPython 3.13tmusllinux: musl 1.1+ ARMv7l

tonio-0.5.0-cp313-cp313t-musllinux_1_1_aarch64.whl (566.4 kB view details)

Uploaded CPython 3.13tmusllinux: musl 1.1+ ARM64

tonio-0.5.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (405.7 kB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.17+ x86-64

tonio-0.5.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (399.2 kB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.17+ ARMv7l

tonio-0.5.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (388.8 kB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.17+ ARM64

tonio-0.5.0-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl (430.8 kB view details)

Uploaded CPython 3.13tmanylinux: glibc 2.12+ i686

tonio-0.5.0-cp313-cp313t-macosx_11_0_arm64.whl (348.1 kB view details)

Uploaded CPython 3.13tmacOS 11.0+ ARM64

tonio-0.5.0-cp313-cp313t-macosx_10_12_x86_64.whl (368.6 kB view details)

Uploaded CPython 3.13tmacOS 10.12+ x86-64

File details

Details for the file tonio-0.5.0.tar.gz.

File metadata

  • Download URL: tonio-0.5.0.tar.gz
  • Upload date:
  • Size: 59.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for tonio-0.5.0.tar.gz
Algorithm Hash digest
SHA256 ea52603e7df2208ca4ecbae540c027b4da1c813fc6a2d07e7e5968a35670997a
MD5 9db3cbd2e4343a3d6eed09d10d9e2dc8
BLAKE2b-256 078d7bbc4192a4354d4f455e173e31bb373a4043d1309f32d60471081658d901

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0.tar.gz:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 88d6c5bf3a51f953f2da84c1de5f9bec90df652c2707517d16d5fdf3c7aa3e6a
MD5 ef91d0f5aa9ecf8c8b0f822fe6a821b4
BLAKE2b-256 26b545816bcf9c1db59906549016310ec2aba1ad728a16278396e3ea12576706

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-musllinux_1_1_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 aa2a160ee8e4de4ec4fb82b6f8a641cd9988ddd64b61f9006b00f1f1e939bc41
MD5 8193bd4469daf9d193a8adea397a7d5e
BLAKE2b-256 1435824784aff593aec590599a50bc13c2a27146f494770b311fca1f2c39646e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-musllinux_1_1_armv7l.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 f96468d49f3c057ee783da9715406d50f06804528a3a5e2fbef6023263c5f624
MD5 8289904f6e3f39ffe711d3ff4d305804
BLAKE2b-256 2860c741f774b1e6d518d38120a8223644282f054bbda2ac39b619e0d4b9d95e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-musllinux_1_1_aarch64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 27d633fca33b3150e975bf9bcdd390baae404f07ecf7611839af158a7bc765b3
MD5 0a61224282381109050b597907d198f4
BLAKE2b-256 db7ad77c44da2f1d1b58f6ad4f90bad7a223512c6e59812db32e2c43acfa826f

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 6fae33e0658a5b6633574c905f99ab629c59a1d92c61e47df00f0c30602c5b2a
MD5 f7a708f4b4a31c6d0f6ff1786351c728
BLAKE2b-256 b361acd7211d1f6a040e1fd46444616052ffbee0d8ce5ad785f7a7a439a32c9d

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0ebd4ab0b48dcedc2eb0fac589e433d9b47faeebe3a3a596000a329cb777c6f3
MD5 89df81573cec91608d330896a6f11822
BLAKE2b-256 98b05709a1fc50c947ddde629fc6576cf3e43e88889e52d0aec17be41461e48d

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 23fa8efa27d923b082bb6e31de72af0bc4b3c8f74179ff157e6c24a429c340d8
MD5 cb9f094516008dcdb5b70abaf1365c8d
BLAKE2b-256 a8cedf08bdc569540b209a1c8248582afdfc03c483846e9c1b4e91ce6671f177

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 f383dd10b83ffde455617a53dfe830328e58dcae7270728c297b1a82080e5c66
MD5 5724de80c21857c8fdefebaeb4ca28b7
BLAKE2b-256 eef850f1d31bb216c06976faff80700a2f85566b919e24f9743717f341fd637d

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-macosx_11_0_arm64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 a4acf3eb1fb83d9301b15c720452efb5a8c4dafa44161cd609c5a0deda86ff8f
MD5 a01c4d90631af98242d2550245cfe357
BLAKE2b-256 93ef9fc7edfa24b864ac2c2ee25f91415f897dc6c36a80be7ebcd7a447f471bb

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp314-cp314t-macosx_10_12_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 b6bb66621f7e194a0501936203b68bc6c51a9c6a7550d180a20c8d7db2e6cdef
MD5 7c58d7b5bc2df03013302e354ab35bd2
BLAKE2b-256 d4a277bbf5956f5bd3e499a48dc58ff8c4d0dc2c98d11b38e2bc74eb937ea41b

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-musllinux_1_1_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 5aa08bd8f68a59c17943555acf7a4d10e532d0b97b1927cda2ffe8caf9ccfad3
MD5 155aa0ec23d213eef57d4ab57e0e5a63
BLAKE2b-256 146c6feffc9f05a1b6b930a9d9ed703a0589c074782119f950d66e6ed69534cf

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-musllinux_1_1_armv7l.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 f75beee9bab9ae67371ddbe96eee970d5dec7bd9a9d48cd6c30d090fcd772119
MD5 87610a28ba23d8b0a1d39d7852dd416f
BLAKE2b-256 a7169dd51f514cea16bebbb77f251ce4edff7fffaa8c46994ed93ba4eee5e75b

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-musllinux_1_1_aarch64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 031f11f798b6912cefafe0f1d009f5321f6542a10ad52dc76cc7c6c633ddc2ee
MD5 1e4054b2a249fee130f55e8eaa7acfad
BLAKE2b-256 1e9eb3a76f441988bf9c687ae2c9f0460e4cb70f6f4f6b50a75442af8de9565d

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 996bf0aa25e25ef699e38d5af6f4d1057e8175d351978d257a072e472d866722
MD5 671f68376970b8c4a4f234c4f33e1e32
BLAKE2b-256 f529c2fa3c7510c6159e5d18b7d0e0af27e9fb2163e7316ba5eff0b8c40cd2ee

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 2caf15fc016ee3147bf40788b8e169b5d0c8d50b34b8343b0e57f1c52f5bb4b3
MD5 270ef493783159b36221c30aa5a2024f
BLAKE2b-256 1daa103f38500f216cc535b6c4617f7c3dbc83dbc87b1529ce75e43c02ccfbc4

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 75a3796d2c6b7a688d844fdfca82e5426d4c513b3ab948fc05d3119e1c3d01a0
MD5 5a764a1551c699330f1b2fb855be07a8
BLAKE2b-256 bf1612d4e41c791b86edbc4e165411bed851b6215909d79a68b62f9d37963a51

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-manylinux_2_12_i686.manylinux2010_i686.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 dcf74aa57a74ec495c3f9cb2c675a20ed4ea3343b3dba40e27f593860b7ee066
MD5 9647e451be6230c38ee96429d6d48206
BLAKE2b-256 eaa240dcbd3beca2fd4707edaf23f3d74883dec022f4f6dc5a1e51a1956fabf4

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-macosx_11_0_arm64.whl:

Publisher: release.yml on gi0baro/tonio

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

File details

Details for the file tonio-0.5.0-cp313-cp313t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.5.0-cp313-cp313t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 230e6c1450712b25e6182c609dd806c28249ae6bbeff4f2ad9f051ced2f8ca8d
MD5 5c14beef440352ef9a04339a5ae39b2c
BLAKE2b-256 2be8a61ab31e68c28df6453eb2c4a8bea1a5b2987d704178d754525eae9df8f2

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.5.0-cp313-cp313t-macosx_10_12_x86_64.whl:

Publisher: release.yml on gi0baro/tonio

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

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page