{"id":15015453,"url":"https://github.com/asyncgui/asynckivy","last_synced_at":"2025-04-04T17:05:34.635Z","repository":{"id":40762072,"uuid":"202916928","full_name":"asyncgui/asynckivy","owner":"asyncgui","description":"Async library for Kivy","archived":false,"fork":false,"pushed_at":"2025-03-19T02:17:42.000Z","size":1046,"stargazers_count":86,"open_issues_count":0,"forks_count":2,"subscribers_count":6,"default_branch":"main","last_synced_at":"2025-03-28T16:04:46.163Z","etag":null,"topics":["kivy"],"latest_commit_sha":null,"homepage":"https://asyncgui.github.io/asynckivy/","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asyncgui.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-08-17T18:14:44.000Z","updated_at":"2025-03-19T02:12:25.000Z","dependencies_parsed_at":"2023-11-08T05:53:43.260Z","dependency_job_id":"2c9444e6-36ad-4c66-8b34-77ce84011c44","html_url":"https://github.com/asyncgui/asynckivy","commit_stats":{"total_commits":339,"total_committers":1,"mean_commits":339.0,"dds":0.0,"last_synced_commit":"dde13930de5e03eb1f508fb8638d940230860187"},"previous_names":["asyncgui/asynckivy","gottadiveintopython/asynckivy"],"tags_count":21,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asyncgui%2Fasynckivy","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asyncgui%2Fasynckivy/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asyncgui%2Fasynckivy/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asyncgui%2Fasynckivy/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asyncgui","download_url":"https://codeload.github.com/asyncgui/asynckivy/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247217174,"owners_count":20903008,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["kivy"],"created_at":"2024-09-24T19:47:29.466Z","updated_at":"2025-04-04T17:05:34.628Z","avatar_url":"https://github.com/asyncgui.png","language":"Python","readme":"# AsyncKivy\n\n[Youtube](https://www.youtube.com/playlist?list=PLNdhqAjzeEGjTpmvNck4Uykps8s9LmRTJ)  \n[日本語doc](README_jp.md)  \n\n`asynckivy` is an async library that saves you from ugly callback-style code,\nlike most of async libraries do.\nLet's say you want to do:\n\n1. `print('A')`\n1. wait for 1sec\n1. `print('B')`\n1. wait for a button to be pressed\n1. `print('C')`\n\nin that order.\nYour code would look like this:\n\n```python\nfrom kivy.clock import Clock\n\ndef what_you_want_to_do(button):\n    print('A')\n\n    def one_sec_later(__):\n        print('B')\n        button.bind(on_press=on_button_press)\n    Clock.schedule_once(one_sec_later, 1)\n\n    def on_button_press(button):\n        button.unbind(on_press=on_button_press)\n        print('C')\n\nwhat_you_want_to_do(...)\n```\n\nIt's not easy to understand.\nIf you use `asynckivy`, the code above will become:\n\n```python\nimport asynckivy as ak\n\nasync def what_you_want_to_do(button):\n    print('A')\n    await ak.sleep(1)\n    print('B')\n    await ak.event(button, 'on_press')\n    print('C')\n\nak.managed_start(what_you_want_to_do(...))\n```\n\n## Installation\n\nPin the minor version.\n\n```text\npoetry add asynckivy@~0.8\npip install \"asynckivy\u003e=0.8,\u003c0.9\"\n```\n\n## Usage\n\n```python\nimport asynckivy as ak\n\nasync def some_task(button):\n    # waits for 2 seconds to elapse\n    dt = await ak.sleep(2)\n    print(f'{dt} seconds have elapsed')\n\n    # waits for a button to be pressed\n    await ak.event(button, 'on_press')\n\n    # waits for the value of 'button.x' to change\n    __, x = await ak.event(button, 'x')\n    print(f'button.x is now {x}')\n\n    # waits for the value of 'button.x' to become greater than 100\n    if button.x \u003c= 100:\n        __, x = await ak.event(button, 'x', filter=lambda __, x: x\u003e100)\n        print(f'button.x is now {x}')\n\n    # waits for either 5 seconds to elapse or a button to be pressed.\n    # i.e. waits at most 5 seconds for a button to be pressed\n    tasks = await ak.wait_any(\n        ak.sleep(5),\n        ak.event(button, 'on_press'),\n    )\n    print(\"Timeout\" if tasks[0].finished else \"The button was pressed\")\n\n    # same as the above\n    async with ak.move_on_after(5) as bg_task:\n        await ak.event(button, 'on_press')\n    print(\"Timeout\" if bg_task.finished else \"The button was pressed\")\n\n    # waits for both 5 seconds to elapse and a button to be pressed.\n    tasks = await ak.wait_all(\n        ak.sleep(5),\n        ak.event(button, 'on_press'),\n    )\n\n    # nest as you want.\n    # waits for a button to be pressed, and either 5 seconds to elapse or 'other_async_func' to complete.\n    tasks = await ak.wait_all(\n        ak.event(button, 'on_press'),\n        ak.wait_any(\n            ak.sleep(5),\n            other_async_func(),\n        ),\n    )\n    child_tasks = tasks[1].result\n    print(\"5 seconds elapsed\" if child_tasks[0].finished else \"other_async_func has completed\")\n\nak.managed_start(some_task(some_button))\n```\n\nFor more details, read the [documentation](https://asyncgui.github.io/asynckivy/).\n\n## Tested on\n\n- CPython 3.9 + Kivy 2.3\n- CPython 3.10 + Kivy 2.3\n- CPython 3.11 + Kivy 2.3\n- CPython 3.12 + Kivy 2.3\n- CPython 3.13 + Kivy 2.3\n\n## Why this even exists\n\nStarting from version 2.0.0, Kivy supports two legitimate async libraries: [asyncio][asyncio] and [Trio][trio].\nAt first glance, developing another one might seem like [reinventing the wheel][reinventing].\nActually, I originally started this project just to learn how the async/await syntax works--\nso at first, it really was 'reinventing the wheel'.\n\nBut after experimenting with Trio in combination with Kivy for a while,\nI noticed that Trio isn't suitable for situations requiring fast reactions, such as handling touch events.\nThe same applies to asyncio.\nYou can confirm this by running `investigation/why_xxx_is_not_suitable_for_handling_touch_events.py` and rapidly clicking a mouse button.\nYou'll notice that sometimes `'up'` isn't paired with a corresponding `'down'` in the console output.\nYou'll also see that the touch coordinates aren't relative to a `RelativeLayout`,\neven though the widget receiving the touches belongs to it.\n\nThe cause of these problems is that `trio.Event.set()` and `asyncio.Event.set()` don't *immediately* resume the tasks waiting for the `Event` to be set--\nthey merely schedule them to resume.\nThe same is true for `nursery.start_soon()` and `asyncio.create_task()`.\n\nTrio and asyncio are async **I/O** libraries after all.\nThey probably don't need to resume or start tasks immediately, but I believe this is essential for touch handling in Kivy.\nIf touch events aren't processed promptly, their state might change before tasks even have a chance to handle them.\nTheir core design might not be ideal for GUI applications in the first place.\nThat's why I continue to develop the asynckivy library to this day.\n\n[asyncio]:https://docs.python.org/3/library/asyncio.html\n[trio]:https://trio.readthedocs.io/en/stable/\n[reinventing]:https://en.wikipedia.org/wiki/Reinventing_the_wheel\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasyncgui%2Fasynckivy","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasyncgui%2Fasynckivy","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasyncgui%2Fasynckivy/lists"}