%global _empty_manifest_terminate_build 0 Name: python-asyncgui Version: 0.5.5 Release: 1 Summary: async/await without event-loop License: MIT URL: https://github.com/gottadiveintopython/asyncgui Source0: https://mirrors.aliyun.com/pypi/web/packages/e8/2a/2049a49aee3a1ef19385e5ca8da7420f07034014a1b1f9912a17ab41d6db/asyncgui-0.5.5.tar.gz BuildArch: noarch %description # AsyncGui A thin layer that helps to build an async/await-based api using a callback-based api. ## How to use Despite its name, `asyncgui` has nothing to do with gui. You can wrap any kind of callback-based api in it. The simplest example of it would be [sched](https://docs.python.org/3/library/sched.html), whose the whole feature is a timer. All you need is just few lines of code: ```python import types import sched import asyncgui s = sched.scheduler() # wrapping 'scheduler.enter()' takes only three lines @types.coroutine def sleep(duration): yield lambda step_coro: s.enter(duration, 10, step_coro) async def main(): print('A') await sleep(1) # Now you can sleep in an async-manner print('B') await sleep(1) print('C') asyncgui.start(main()) s.run() ``` And you already have structured concurrency apis as well: ```python async def print_numbers(): for i in range(10): await sleep(.1) print(i) async def print_letters(): for c in "ABCDE": await sleep(.1) print(c) async def main(): from asyncgui.structured_concurrency import or_ # Let print_letters() and print_numbers() race. # As soon as one of them finishes, the other one gets cancelled. tasks = await or_(print_letters(), print_numbers()) if tasks[0].done: print("print_letters() won") else: print("print_numbers() won") print('main end') ``` ``` A 0 B 1 C 2 D 3 E print_letters() won main end ``` ## Why not asyncio ? The above example may not attract you because you can just replace `sched` with [asyncio](https://docs.python.org/3/library/asyncio.html) or [Trio](https://trio.readthedocs.io/en/stable/), and can use thier sleep function (`asyncio.sleep` and `trio.sleep`). But in a read-world situation, that might not be an option: Kivy required [massive changes](https://github.com/kivy/kivy/pull/6368) in order to adapt to `asyncio` and `Trio`, [asyncio-tkinter](https://github.com/fluentpython/asyncio-tkinter)'s codebase is quite big as well. The reason they needed lots of work is that they had to merge two event-loops into one. One is from the gui libraries. The other one is from async libraries. You cannot just simply run multiple event-loops simultaneously in one thread. On the other hand, `asyncgui` doesn't require a lot of work as shown above **because it doesn't have an event-loop**. `asyncgui` and a library who has an event-loop can live in the same thread seemlessly because of it. ## So, is asyncgui superior to asyncio ? No, it is not. For `asyncgui`, many features that exist in `asyncio` are either impossible or hard to implement because of the lack of event-loop. The implementation of those features needs to be specific to the event-loop you are using. You've already witnessed one, the `sleep`. ## asyncgui is not usefull then. There is at least one situation that `asyncgui` shines. When you are creating a gui app, you probably want the app to quickly react to the gui events, like pressing a button. This is problematic for `asyncio` because it cannot immediately start/resume a task. It can schedule a task to *eventually* start/resume but not *immediate*, which causes to [spill gui events](https://github.com/gottadiveintopython/asynckivy/blob/main/examples/misc/why_asyncio_is_not_suitable_for_handling_touch_events.py). As a result, you need to use callback-based apis for that, and thus you cannot fully receive the benefits of async/await. If you use `asyncgui`, that never happens because: - `asyncgui.start()` immediately starts a task. - `asyncgui.Event.set()` immediately resumes the tasks waiting for it to happen. In summary, if your program needs to react to something immediately, `asyncgui` is for you. Otherwise, it's probably not worth it. ## Installation It's recommended to pin the minor version, because if it changed, it means some *important* breaking changes occurred. ```text poetry add asyncgui@~0.5 pip install "asyncgui>=0.5,<0.6" ``` ## Tested on - CPython 3.7 - CPython 3.8 - CPython 3.9 - CPython 3.10 ## Async-libraries who relies on this - [asynckivy](https://github.com/gottadiveintopython/asynckivy) - [asynctkinter](https://github.com/gottadiveintopython/asynctkinter) %package -n python3-asyncgui Summary: async/await without event-loop Provides: python-asyncgui BuildRequires: python3-devel BuildRequires: python3-setuptools BuildRequires: python3-pip %description -n python3-asyncgui # AsyncGui A thin layer that helps to build an async/await-based api using a callback-based api. ## How to use Despite its name, `asyncgui` has nothing to do with gui. You can wrap any kind of callback-based api in it. The simplest example of it would be [sched](https://docs.python.org/3/library/sched.html), whose the whole feature is a timer. All you need is just few lines of code: ```python import types import sched import asyncgui s = sched.scheduler() # wrapping 'scheduler.enter()' takes only three lines @types.coroutine def sleep(duration): yield lambda step_coro: s.enter(duration, 10, step_coro) async def main(): print('A') await sleep(1) # Now you can sleep in an async-manner print('B') await sleep(1) print('C') asyncgui.start(main()) s.run() ``` And you already have structured concurrency apis as well: ```python async def print_numbers(): for i in range(10): await sleep(.1) print(i) async def print_letters(): for c in "ABCDE": await sleep(.1) print(c) async def main(): from asyncgui.structured_concurrency import or_ # Let print_letters() and print_numbers() race. # As soon as one of them finishes, the other one gets cancelled. tasks = await or_(print_letters(), print_numbers()) if tasks[0].done: print("print_letters() won") else: print("print_numbers() won") print('main end') ``` ``` A 0 B 1 C 2 D 3 E print_letters() won main end ``` ## Why not asyncio ? The above example may not attract you because you can just replace `sched` with [asyncio](https://docs.python.org/3/library/asyncio.html) or [Trio](https://trio.readthedocs.io/en/stable/), and can use thier sleep function (`asyncio.sleep` and `trio.sleep`). But in a read-world situation, that might not be an option: Kivy required [massive changes](https://github.com/kivy/kivy/pull/6368) in order to adapt to `asyncio` and `Trio`, [asyncio-tkinter](https://github.com/fluentpython/asyncio-tkinter)'s codebase is quite big as well. The reason they needed lots of work is that they had to merge two event-loops into one. One is from the gui libraries. The other one is from async libraries. You cannot just simply run multiple event-loops simultaneously in one thread. On the other hand, `asyncgui` doesn't require a lot of work as shown above **because it doesn't have an event-loop**. `asyncgui` and a library who has an event-loop can live in the same thread seemlessly because of it. ## So, is asyncgui superior to asyncio ? No, it is not. For `asyncgui`, many features that exist in `asyncio` are either impossible or hard to implement because of the lack of event-loop. The implementation of those features needs to be specific to the event-loop you are using. You've already witnessed one, the `sleep`. ## asyncgui is not usefull then. There is at least one situation that `asyncgui` shines. When you are creating a gui app, you probably want the app to quickly react to the gui events, like pressing a button. This is problematic for `asyncio` because it cannot immediately start/resume a task. It can schedule a task to *eventually* start/resume but not *immediate*, which causes to [spill gui events](https://github.com/gottadiveintopython/asynckivy/blob/main/examples/misc/why_asyncio_is_not_suitable_for_handling_touch_events.py). As a result, you need to use callback-based apis for that, and thus you cannot fully receive the benefits of async/await. If you use `asyncgui`, that never happens because: - `asyncgui.start()` immediately starts a task. - `asyncgui.Event.set()` immediately resumes the tasks waiting for it to happen. In summary, if your program needs to react to something immediately, `asyncgui` is for you. Otherwise, it's probably not worth it. ## Installation It's recommended to pin the minor version, because if it changed, it means some *important* breaking changes occurred. ```text poetry add asyncgui@~0.5 pip install "asyncgui>=0.5,<0.6" ``` ## Tested on - CPython 3.7 - CPython 3.8 - CPython 3.9 - CPython 3.10 ## Async-libraries who relies on this - [asynckivy](https://github.com/gottadiveintopython/asynckivy) - [asynctkinter](https://github.com/gottadiveintopython/asynctkinter) %package help Summary: Development documents and examples for asyncgui Provides: python3-asyncgui-doc %description help # AsyncGui A thin layer that helps to build an async/await-based api using a callback-based api. ## How to use Despite its name, `asyncgui` has nothing to do with gui. You can wrap any kind of callback-based api in it. The simplest example of it would be [sched](https://docs.python.org/3/library/sched.html), whose the whole feature is a timer. All you need is just few lines of code: ```python import types import sched import asyncgui s = sched.scheduler() # wrapping 'scheduler.enter()' takes only three lines @types.coroutine def sleep(duration): yield lambda step_coro: s.enter(duration, 10, step_coro) async def main(): print('A') await sleep(1) # Now you can sleep in an async-manner print('B') await sleep(1) print('C') asyncgui.start(main()) s.run() ``` And you already have structured concurrency apis as well: ```python async def print_numbers(): for i in range(10): await sleep(.1) print(i) async def print_letters(): for c in "ABCDE": await sleep(.1) print(c) async def main(): from asyncgui.structured_concurrency import or_ # Let print_letters() and print_numbers() race. # As soon as one of them finishes, the other one gets cancelled. tasks = await or_(print_letters(), print_numbers()) if tasks[0].done: print("print_letters() won") else: print("print_numbers() won") print('main end') ``` ``` A 0 B 1 C 2 D 3 E print_letters() won main end ``` ## Why not asyncio ? The above example may not attract you because you can just replace `sched` with [asyncio](https://docs.python.org/3/library/asyncio.html) or [Trio](https://trio.readthedocs.io/en/stable/), and can use thier sleep function (`asyncio.sleep` and `trio.sleep`). But in a read-world situation, that might not be an option: Kivy required [massive changes](https://github.com/kivy/kivy/pull/6368) in order to adapt to `asyncio` and `Trio`, [asyncio-tkinter](https://github.com/fluentpython/asyncio-tkinter)'s codebase is quite big as well. The reason they needed lots of work is that they had to merge two event-loops into one. One is from the gui libraries. The other one is from async libraries. You cannot just simply run multiple event-loops simultaneously in one thread. On the other hand, `asyncgui` doesn't require a lot of work as shown above **because it doesn't have an event-loop**. `asyncgui` and a library who has an event-loop can live in the same thread seemlessly because of it. ## So, is asyncgui superior to asyncio ? No, it is not. For `asyncgui`, many features that exist in `asyncio` are either impossible or hard to implement because of the lack of event-loop. The implementation of those features needs to be specific to the event-loop you are using. You've already witnessed one, the `sleep`. ## asyncgui is not usefull then. There is at least one situation that `asyncgui` shines. When you are creating a gui app, you probably want the app to quickly react to the gui events, like pressing a button. This is problematic for `asyncio` because it cannot immediately start/resume a task. It can schedule a task to *eventually* start/resume but not *immediate*, which causes to [spill gui events](https://github.com/gottadiveintopython/asynckivy/blob/main/examples/misc/why_asyncio_is_not_suitable_for_handling_touch_events.py). As a result, you need to use callback-based apis for that, and thus you cannot fully receive the benefits of async/await. If you use `asyncgui`, that never happens because: - `asyncgui.start()` immediately starts a task. - `asyncgui.Event.set()` immediately resumes the tasks waiting for it to happen. In summary, if your program needs to react to something immediately, `asyncgui` is for you. Otherwise, it's probably not worth it. ## Installation It's recommended to pin the minor version, because if it changed, it means some *important* breaking changes occurred. ```text poetry add asyncgui@~0.5 pip install "asyncgui>=0.5,<0.6" ``` ## Tested on - CPython 3.7 - CPython 3.8 - CPython 3.9 - CPython 3.10 ## Async-libraries who relies on this - [asynckivy](https://github.com/gottadiveintopython/asynckivy) - [asynctkinter](https://github.com/gottadiveintopython/asynctkinter) %prep %autosetup -n asyncgui-0.5.5 %build %py3_build %install %py3_install install -d -m755 %{buildroot}/%{_pkgdocdir} if [ -d doc ]; then cp -arf doc %{buildroot}/%{_pkgdocdir}; fi if [ -d docs ]; then cp -arf docs %{buildroot}/%{_pkgdocdir}; fi if [ -d example ]; then cp -arf example %{buildroot}/%{_pkgdocdir}; fi if [ -d examples ]; then cp -arf examples %{buildroot}/%{_pkgdocdir}; fi pushd %{buildroot} if [ -d usr/lib ]; then find usr/lib -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/lib64 ]; then find usr/lib64 -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/bin ]; then find usr/bin -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi if [ -d usr/sbin ]; then find usr/sbin -type f -printf "\"/%h/%f\"\n" >> filelist.lst fi touch doclist.lst if [ -d usr/share/man ]; then find usr/share/man -type f -printf "\"/%h/%f.gz\"\n" >> doclist.lst fi popd mv %{buildroot}/filelist.lst . mv %{buildroot}/doclist.lst . %files -n python3-asyncgui -f filelist.lst %dir %{python3_sitelib}/* %files help -f doclist.lst %{_docdir}/* %changelog * Tue Jun 20 2023 Python_Bot - 0.5.5-1 - Package Spec generated