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.1.tar.gz (61.6 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.1-cp315-cp315t-musllinux_1_1_x86_64.whl (604.8 kB view details)

Uploaded CPython 3.15tmusllinux: musl 1.1+ x86-64

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

Uploaded CPython 3.15tmusllinux: musl 1.1+ ARMv7l

tonio-0.7.1-cp315-cp315t-musllinux_1_1_aarch64.whl (554.8 kB view details)

Uploaded CPython 3.15tmusllinux: musl 1.1+ ARM64

tonio-0.7.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (389.8 kB view details)

Uploaded CPython 3.15tmanylinux: glibc 2.17+ x86-64

tonio-0.7.1-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.1-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl (377.4 kB view details)

Uploaded CPython 3.15tmanylinux: glibc 2.17+ ARM64

tonio-0.7.1-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.1-cp315-cp315t-macosx_11_0_arm64.whl (340.4 kB view details)

Uploaded CPython 3.15tmacOS 11.0+ ARM64

tonio-0.7.1-cp315-cp315t-macosx_10_12_x86_64.whl (358.3 kB view details)

Uploaded CPython 3.15tmacOS 10.12+ x86-64

tonio-0.7.1-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.1-cp314-cp314t-musllinux_1_1_armv7l.whl (668.0 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARMv7l

tonio-0.7.1-cp314-cp314t-musllinux_1_1_aarch64.whl (554.6 kB view details)

Uploaded CPython 3.14tmusllinux: musl 1.1+ ARM64

tonio-0.7.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (389.8 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.17+ x86-64

tonio-0.7.1-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.1-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.1-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl (419.7 kB view details)

Uploaded CPython 3.14tmanylinux: glibc 2.12+ i686

tonio-0.7.1-cp314-cp314t-macosx_11_0_arm64.whl (340.3 kB view details)

Uploaded CPython 3.14tmacOS 11.0+ ARM64

tonio-0.7.1-cp314-cp314t-macosx_10_12_x86_64.whl (358.2 kB view details)

Uploaded CPython 3.14tmacOS 10.12+ x86-64

File details

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

File metadata

  • Download URL: tonio-0.7.1.tar.gz
  • Upload date:
  • Size: 61.6 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.1.tar.gz
Algorithm Hash digest
SHA256 07094ac4bdc7f03fbd6ed6b77b9a14067c5c166650c578bb21121ea95cac3fb4
MD5 f2e07c9916bbd7f195eb6aca0c78ee1f
BLAKE2b-256 1b8738af3734d2c2eb322f3e936e4ce47d3e40fe883761526f63ad918f8ad713

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 598e28ed67c60d27398fac597fd010e6234519bdf6807ae536f9bf9975fce153
MD5 8173cbcdd4bbd4f2f0e3b269cc2181f6
BLAKE2b-256 cb2eea91335acbb6a3332b05eab5e3c9138cb7727850b41dd8b6889e728c6fa2

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 3a3c16caecbb36dc8ad63921e95137930405ed04ee1d0753ee58377713c7434f
MD5 599e58c943d10d1772b752dbf3cf2525
BLAKE2b-256 7396efc6699a30abab9f9eeb098964acb744db53a2577c2340f695f186046fe5

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 2626a0a0250852ad2ee079d9542d37e536f17d5ec4ecd8841cbd470fb5d3a76f
MD5 c0d4cab6f7bfe1b70f18745cff610370
BLAKE2b-256 6d7d5c0557e9c7d62cad10773788021a15dd68e993bef1a4252350dbf9c63b1e

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 1399a8dba65eb268f673bcf5a8d3def9e296d49c9f31d7968957a2582a153b6c
MD5 16114af20a003039cf484e18772f4040
BLAKE2b-256 5f700dac580b795b7cadd0e09b524a30dcd5c193aad73b74c50a989b1d06bf18

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 a31c61b475ae4655bff51c1c3885d3e35696d912a8b4b2aba2f14e3d8377b9e9
MD5 5c4a596c1c62499d335ed0320f0d3594
BLAKE2b-256 bd723ab997df3b7534ef05c9957eca9faf1d6a19f2c443df49eee8257ed3153b

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 fac2c51778a8ab1ceb4f28250b8aa33be49ba4ce99e29d376d782c94ec263773
MD5 ed8eba20cb1f08077ecd59add0e06c12
BLAKE2b-256 71af78145aea0874b2c7eb7e3e4f9ee4c707e13d5cb628d1a5edcb260d186aa3

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 96cb4f7384bec6cc5d342bdd82dabcf4671f67dea083fe2b1b06e3915e6c441f
MD5 541f537dcd154e39ea77f48179b161a0
BLAKE2b-256 e023ecafca3b9b0afadfe40a0303248a9f9bb52f1fcb5a168e77c983a66c6319

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 a9287fa212682c14e7facb4bb698bf9bf2a442b4b6c7c31a1cfddfa26ee4dc77
MD5 f05f1793784d834041cac1fcfa5148e1
BLAKE2b-256 e44ea60e3f7c1fa2be6ec52e28ad9e9a37807c9052b05ac0af15f0a90354fe67

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp315-cp315t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 d6c38b736862c48f728e86302a539af6a9b43d64caeaf1b92ea5305504b81161
MD5 cb71bd36e059c0cc997fe62b501b33ff
BLAKE2b-256 95cb7d39d7f66ea98cafe50b6ba6fc80fc8ac399fc26687464fed03622f7d7c9

See more details on using hashes here.

Provenance

The following attestation bundles were made for tonio-0.7.1-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.1-cp314-cp314t-musllinux_1_1_x86_64.whl.

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-musllinux_1_1_x86_64.whl
Algorithm Hash digest
SHA256 700eb53a543bbb1ef7f1c60597da5ddbe91066a8f86ddd8ee976071f8b235ae1
MD5 a0e8feb8c52241453e1a87d7f4206d89
BLAKE2b-256 3ebadc2c0230be6d1090532b4ee8b7e2b1b84d04bd8154a3f0b9812b9d66a59c

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-musllinux_1_1_armv7l.whl
Algorithm Hash digest
SHA256 bd43762688ee5f2ea0133f6415171505df51a5f668d2c0e21d2a349b84eb03a4
MD5 3fa575f7f3f24819a25f7c3a7c6916be
BLAKE2b-256 83f1dc36dae4764f465f5c8d8d80f7d7cbef20179e0f331efd91581b15b7a7b2

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-musllinux_1_1_aarch64.whl
Algorithm Hash digest
SHA256 ae6353a938ff954cb5ca72bba946cd4b985115816741bea20b04ac539f3ff06b
MD5 9d405d1315b5edb4413b74fd5d86c9af
BLAKE2b-256 4d07037120b064c78216a3f9b9f00b218db2629a8fa9849229b3b90734aa1028

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 a77c4b6b0ef1d8f90938c29d32ba212eb861bf67ee3f34c6b68f7aaff9c81d12
MD5 c0956ac78a56e515e9ec3d8a1d7dfb3c
BLAKE2b-256 bfe85bd27da6b24b4049ea623c6a7a412972676743e4abd8af02cd9856134b3d

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl
Algorithm Hash digest
SHA256 df09aa5dcbb850cc6d10cb9c0c5cf9e29e5ec8c213cd0d173f7ea19243a361f7
MD5 35e5c486bddec78926a852780de6de6a
BLAKE2b-256 459fe9266c573068e1f3d34f1597dbe3652ac188a10a9cc517ac7f29d60b1753

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl
Algorithm Hash digest
SHA256 0000c32938a27a761ee067c00197573b9ad0ab5c45f594b3abe2e8142f68c849
MD5 6b3927f15d980aa670e13aa5ebdb3e0c
BLAKE2b-256 12fe47f0acaa7775bec6660bfb507532adefe767e81ff9d7c2c61f27f7111379

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-manylinux_2_12_i686.manylinux2010_i686.whl
Algorithm Hash digest
SHA256 67112aba7562e62d0ef4640da99500b29fb99b2ee254f6644c30b8c2a1f3a86f
MD5 d5a0e129e2da7f631350e76c21827b3a
BLAKE2b-256 684779b0015ce77f0e7a34aa18fdfcbfa97744d133e745341f18833963287d7c

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 fa8f6fb10b3fc3625c26f146cff488d28131ecc73dab29b6dbf6649eebcf269a
MD5 202b2d22f2dec0b7e9f1a17deb1f66a4
BLAKE2b-256 cb219d59794fe9b52c6b869475bf5ebf292d90af6da2451103f4d60531db3ee7

See more details on using hashes here.

Provenance

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

File metadata

File hashes

Hashes for tonio-0.7.1-cp314-cp314t-macosx_10_12_x86_64.whl
Algorithm Hash digest
SHA256 3f938b82a58d4051fe1a77cf5bf91d7551b92df3fd8e295376b9947cafb31031
MD5 d7955b00707be4bce971672b4de3af71
BLAKE2b-256 076e7fd2ddf5da84d6f5f183c15fb7bcfa13302c8d0202d96d5ab86b13d93394

See more details on using hashes here.

Provenance

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