Skip to main content

Async library for Kivy

Project description

AsyncKivy

Youtube
日本語doc

asynckivy is an async library that saves you from ugly callback-style code, like most of async libraries do. Let's say you want to do:

  1. print('A')
  2. wait for 1sec
  3. print('B')
  4. wait for a button to be pressed
  5. print('C')

in that order. Your code would look like this:

from kivy.clock import Clock

def what_you_want_to_do(button):
    print('A')

    def one_sec_later(__):
        print('B')
        button.bind(on_press=on_button_press)
    Clock.schedule_once(one_sec_later, 1)

    def on_button_press(button):
        button.unbind(on_press=on_button_press)
        print('C')

what_you_want_to_do(...)

It's not easy to understand. If you use asynckivy, the code above will become:

import asynckivy as ak

async def what_you_want_to_do(button):
    print('A')
    await ak.sleep(1)
    print('B')
    await ak.event(button, 'on_press')
    print('C')

ak.start(what_you_want_to_do(...))

Installation

Pin the minor version.

poetry add asynckivy@~0.7
pip install "asynckivy>=0.7,<0.8"

Usage

import asynckivy as ak

async def some_task(button):
    # waits for 2 seconds to elapse
    dt = await ak.sleep(2)
    print(f'{dt} seconds have elapsed')

    # waits for a button to be pressed
    await ak.event(button, 'on_press')

    # waits for the value of 'button.x' to change
    __, x = await ak.event(button, 'x')
    print(f'button.x is now {x}')

    # waits for the value of 'button.x' to become greater than 100
    if button.x <= 100:
        __, x = await ak.event(button, 'x', filter=lambda __, x: x>100)
        print(f'button.x is now {x}')

    # waits for either 5 seconds to elapse or a button to be pressed.
    # i.e. waits at most 5 seconds for a button to be pressed
    tasks = await ak.wait_any(
        ak.sleep(5),
        ak.event(button, 'on_press'),
    )
    print("Timeout" if tasks[0].finished else "The button was pressed")

    # same as the above
    async with ak.move_on_after(5) as bg_task:
        await ak.event(button, 'on_press')
    print("Timeout" if bg_task.finished else "The button was pressed")

    # waits for both 5 seconds to elapse and a button to be pressed.
    tasks = await ak.wait_all(
        ak.sleep(5),
        ak.event(button, 'on_press'),
    )

    # nest as you want.
    # waits for a button to be pressed, and either 5 seconds to elapse or 'other_async_func' to complete.
    tasks = await ak.wait_all(
        ak.event(button, 'on_press'),
        ak.wait_any(
            ak.sleep(5),
            other_async_func(),
        ),
    )
    child_tasks = tasks[1].result
    print("5 seconds elapsed" if child_tasks[0].finished else "other_async_func has completed")

ak.start(some_task(some_button))

For more details, read the documentation.

Tested on

  • CPython 3.9 + Kivy 2.3.0
  • CPython 3.10 + Kivy 2.3.0
  • CPython 3.11 + Kivy 2.3.0
  • CPython 3.12 + Kivy 2.3.0 (3.12.0 is not supported due to this issue)

Why this even exists

Kivy supports two legitimate async libraries, asyncio and Trio, starting from version 2.0.0, so developing another one seems like reinventing the wheel. Actually, I started this one just to learn how the async/await syntax works, so it initially was "reinventing the wheel".

But after playing with Trio and Kivy for a while, I noticed that Trio is not suitable for the situation where fast reactions are required e.g. touch events. The same is true of asyncio. You can confirm that by running investigation/why_xxx_is_not_suitable_for_handling_touch_events.py, and mashing a mouse button as quickly as possible. You'll see sometimes up is not paired with down. You'll see the coordinates aren't relative to the RelativeLayout even though the target belongs to it.

The cause of those problems is that trio.Event.set() and asyncio.Event.set() don't immediately resume the tasks waiting for the Event to be set. They just schedule the tasks to resume. Same thing can be said to nursery.start_soon() and asyncio.create_task().

Trio and asyncio are async I/O libraries after all. They probably don't have to immediately resumes/starts tasks, which I think necessary for touch handling in Kivy. (If you fail to handle touches promptly, their state might undergo changes, leaving no time to wait for tasks to resume/start). Their core design might not be suitable for GUI in the first place. That's why I'm still developing this asynckivy library to this day.

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

asynckivy-0.7.0.tar.gz (14.8 kB view details)

Uploaded Source

Built Distribution

asynckivy-0.7.0-py3-none-any.whl (17.0 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: asynckivy-0.7.0.tar.gz
  • Upload date:
  • Size: 14.8 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.11.4 Linux/5.4.0-193-generic

File hashes

Hashes for asynckivy-0.7.0.tar.gz
Algorithm Hash digest
SHA256 83396cecceb513393040b40a3cf6d920ed6190e78660aae5edf48c9d3fd1140b
MD5 a958e5cd19400e9a319cecac23fecd29
BLAKE2b-256 5062be185b612bc8470277de71f765b1d92c64a481a087c93d983a380decc563

See more details on using hashes here.

File details

Details for the file asynckivy-0.7.0-py3-none-any.whl.

File metadata

  • Download URL: asynckivy-0.7.0-py3-none-any.whl
  • Upload date:
  • Size: 17.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: poetry/1.8.3 CPython/3.11.4 Linux/5.4.0-193-generic

File hashes

Hashes for asynckivy-0.7.0-py3-none-any.whl
Algorithm Hash digest
SHA256 4855d730ff3283203dcb325bc4018301737a307732f1075b6ef61c2db590bd10
MD5 2da6f85ae3df25947a1ac4f14e158b78
BLAKE2b-256 324001236aaac02a422e97ed8fe3fc20bbf93bd499ddab433a509158e4ba565e

See more details on using hashes here.

Supported by

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