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. The TonIO-Monkey project provides patches for some popular asyncio packages.

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))

Completion-based iterators

TonIO provides the as_completed utility to iterate over task results based on completion order:

yield syntax

import tonio

def _sleep(v):
    yield tonio.sleep(v)
    return v

@tonio.main
def main():
    vals = []
    for task in tonio.as_completed(
        _sleep(0.5),
        _sleep(0.1),
        _sleep(0.3),
    ):
        vals.append(yield task)

await syntax

import tonio.colored as tonio

async def _sleep(v):
    await tonio.sleep(v)
    return v

@tonio.main
async def main():
    vals = []
    async for val in tonio.as_completed(
        _sleep(0.5),
        _sleep(0.1),
        _sleep(0.3),
    ):
        vals.append(val)

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.7.0.tar.gz (61.5 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.7.0-cp315-cp315t-musllinux_1_1_x86_64.whl (604.7 kB view details)

Uploaded CPython 3.15tmusllinux: musl 1.1+ x86-64

tonio-0.7.0-cp315-cp315t-musllinux_1_1_armv7l.whl (668.1 kB view details)

Uploaded CPython 3.15tmusllinux: musl 1.1+ ARMv7l

tonio-0.7.0-cp315-cp315t-musllinux_1_1_aarch64.whl (554.6 kB view details)

Uploaded CPython 3.15tmusllinux: musl 1.1+ ARM64

tonio-0.7.0-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (390.0 kB view details)

Uploaded CPython 3.15tmanylinux: glibc 2.17+ x86-64

tonio-0.7.0-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (391.3 kB view details)

Uploaded CPython 3.15tmanylinux: glibc 2.17+ ARMv7l

tonio-0.7.0-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (377.6 kB view details)

Uploaded CPython 3.15tmanylinux: glibc 2.17+ ARM64

tonio-0.7.0-cp315-cp315t-manylinux_2_12_i686.manylinux2010_i686.whl (419.9 kB view details)

Uploaded CPython 3.15tmanylinux: glibc 2.12+ i686

tonio-0.7.0-cp315-cp315t-macosx_11_0_arm64.whl (340.4 kB view details)

Uploaded CPython 3.15tmacOS 11.0+ ARM64

tonio-0.7.0-cp315-cp315t-macosx_10_12_x86_64.whl (357.9 kB view details)

Uploaded CPython 3.15tmacOS 10.12+ x86-64

tonio-0.7.0-cp314-cp314t-musllinux_1_1_x86_64.whl (604.6 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ x86-64

tonio-0.7.0-cp314-cp314t-musllinux_1_1_armv7l.whl (668.0 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARMv7l

tonio-0.7.0-cp314-cp314t-musllinux_1_1_aarch64.whl (554.4 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARM64

tonio-0.7.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (390.0 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64

tonio-0.7.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl (391.1 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARMv7l

tonio-0.7.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (377.4 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ ARM64

tonio-0.7.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl (419.6 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.12+ i686

tonio-0.7.0-cp314-cp314t-macosx_11_0_arm64.whl (340.1 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

tonio-0.7.0-cp314-cp314t-macosx_10_12_x86_64.whl (357.7 kB view details)

Uploaded CPython 3.14tmacOS 10.12+ x86-64

File details

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

File metadata

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

File hashes

Hashes for tonio-0.7.0.tar.gz
Algorithm Hash digest
SHA256 6d4595bb26a2adf63aff8f764210249e97353a1c1ffb269489acf29330f2c7f5
MD5 fbb98bc443aec00567724e7f49086dde
BLAKE2b-256 5c19ee2913fce6c60630c59f4b6f03193b85ad4eaf793f7da2b0c740760b2d89

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp315-cp315t-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 c03b9b3a8951b2fde64f65e8b03a1b344bf945cd8c2de423e0dc47f87f90bc7e
MD5 336d659896e8f39b402fe14340724275
BLAKE2b-256 72071e501a8d90a437a8ab5c20813914f62f3c7349503a1e42d7fbed630b87a8

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp315-cp315t-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 36313c248bc937f9549b430d20d9cf297638ffe451ae3323e5c60944c0c7d7f3
MD5 b7e13aaeb5b70b41113f2a2e64b64c1f
BLAKE2b-256 1234da527e0fa11c0a2fffdcc2c6640c23b227c79d22166eb44510b794e4aff7

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp315-cp315t-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 309d8e35d7979e483618e0ce4b2c044636a570acd870f613bc09ec9849358427
MD5 1502b322571c7a46ea0037cb2871bf4e
BLAKE2b-256 aad7bcbece6e368b3be861975fa49e482ed05ecf5386c4b4fc6d2466e5d6f58e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 7746010f5ffeb9063c8e10adebda5ca57ef2cecf586bc8a019d0ec51a5aaf247
MD5 470772f67132d389858f8e6ea1138341
BLAKE2b-256 8b5dd5557d1c4c6a5cdb527c3a7562af0692b167e1bf80d4b4410f9070512717

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 31a885f11976ad12a9d3ad7d36b93bf12a26adf4d1f56ada04637db25295a943
MD5 c2689e66a6990761aab74dafb4eb98f3
BLAKE2b-256 24ef085dd9916cf81746050f03d04e3ac1a2001156bb773cb389ff42a947b7a6

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 5db1f34378130105d6f91c7fd9f9ab362ec006f91a7d05a6a4be10354e40081f
MD5 5ba01a94deadb5830fd15882422eb70e
BLAKE2b-256 7f2b9bc3f3f18b9c60b65d10ccc9c84e65c880bc6d91938545a20d2b6da6d0f6

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp315-cp315t-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 8106dc184ece74b922d8f073d3f4e5d08dc70d832c4310d9342dcd357156296a
MD5 87123f244853cf2f920640861e6e720a
BLAKE2b-256 27901524a88700d762ba01a8c533f4156bf227d23ce480ab1794d1d06fcb8848

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp315-cp315t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6dc8cba2ca674cac2d19e07bc4002143c1f8c0f45b2d19bc2ec91a1ed43b68bb
MD5 7048c86e83bee41a2fb1c0572ce2de4c
BLAKE2b-256 771da358774ad357d3e661a089122a3081036686043d76b829d809b2498eb640

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp315-cp315t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp315-cp315t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 179a5d0590c80d237602dea7d7d5b77b1f84a22e0a4b6a49a6a98fc1eee16950
MD5 d0aba1654871b2d6b1c54a26c7bd65f6
BLAKE2b-256 a97fe85bc251cd3ba844c642f8b873f0c20c41dc86fec6bad9809523fd43e388

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.0-cp315-cp315t-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.7.0-cp314-cp314t-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 808b236f849668d9f7f3b9a4accb8266dd4932fc7989cf0cdd4e9665fae3b720
MD5 8b69a4a3e2e5929281a42c32ef0f34af
BLAKE2b-256 c9a18623320a5d8f6c8fdd03a4bc598b70f4681cd700a6020eef5e101827cb57

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp314-cp314t-musllinux_1_1_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 b8d84b3dd4f259a5a9636a10a5779b44e2aadddb7f724b8a54564d5708fed0ac
MD5 ee1ab624f0a835eec0c5eff74be0dc0d
BLAKE2b-256 4c5c88c056c71a5622df2e389885cc974752cc467d306fe8d6c36fa63b5f008f

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp314-cp314t-musllinux_1_1_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 f9c1b0df6e93dad31f41a371d376df3f9ed3e6e407fb3501a35cb2052d64e85d
MD5 0c7f632b0917ecfb889bdad8b71d89e7
BLAKE2b-256 307070e0cd2659650ab049eb162f12137f70a6294f4200aff2fdab8dc4120ab8

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a324087cc880d6926e76ed5a9fc7043cc7afcdd4d941aded4fe288376d2f6658
MD5 05fb250936564c0c3ac48edcfb5f13fa
BLAKE2b-256 2cb6e2fb11b63aae4dbd5a14468ca3abdab6f994ef3be35f655e466d6978d550

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 edf906aff744e9fa4aebe1ec78668ed441a6d1a91ff40b63cfba3485f98e708a
MD5 768fa0fd029d7f0e8a4624bcc520baf7
BLAKE2b-256 86491cf76a3bf742704f679efc1257d5251a2a1a0ba62f8f674ac0d3312cdd13

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 d018814a0aeacba195df830185fa5b3c1e26a6068a7328fe2be17ebfeb8e011f
MD5 ef97103959e628e4e59b014ce0f8c8ba
BLAKE2b-256 ba2c261cba0352e4bde15dc7138be5c1dbedf7cebf070fdbd8510335f04fc0f9

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 fcae69b6192e4e2c12c2093b284ce2959cfd78d9064d28dcd2ecc89cf12e12d1
MD5 88abc866e48dc9296bf1c1ebf1b89799
BLAKE2b-256 5b27096e4af323adce820d02ecc96fa7a9cff499473ef77320d4b6983659082e

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp314-cp314t-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 22f322503634efa0acc5f6749d00387080a918a9fc648b22df71053e03e20a52
MD5 d35ea883554fc62d8233120de66d981c
BLAKE2b-256 0ac0e067fb0b472f14db0ca05b25f673ef957499cae0acc6cbc034bf16725eec

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.7.0-cp314-cp314t-macosx_10_12_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.7.0-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d96a7a98d2ea98882076b88452224a8d3534f18f97965c012989620d55c5b486
MD5 931230202fddd5a9397febbdd626b62b
BLAKE2b-256 30200b701e3a7709e5ca9d912088d22877747bba8204355fc7c7a37b934b29ca

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.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.

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