diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | python-asyncgui.spec | 480 | ||||
-rw-r--r-- | sources | 1 |
3 files changed, 482 insertions, 0 deletions
@@ -0,0 +1 @@ +/asyncgui-0.5.5.tar.gz diff --git a/python-asyncgui.spec b/python-asyncgui.spec new file mode 100644 index 0000000..7a8f9f8 --- /dev/null +++ b/python-asyncgui.spec @@ -0,0 +1,480 @@ +%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 <Python_Bot@openeuler.org> - 0.5.5-1 +- Package Spec generated @@ -0,0 +1 @@ +106b3c5e12e8903a929a41f21c09a832 asyncgui-0.5.5.tar.gz |