Skip to content

Commit 76c26bd

Browse files
(api-break) Queueのみを提供するパッケージにし、名前も"asyncgui-ext-synctools"から"asyncgui-ext-queue"に変更
1 parent 393f147 commit 76c26bd

File tree

11 files changed

+234
-129
lines changed

11 files changed

+234
-129
lines changed

.github/workflows/python-package.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ jobs:
1414
runs-on: ubuntu-latest
1515
strategy:
1616
matrix:
17-
python-version: ['3.10', '3.11', '3.12']
17+
python-version: ['3.10', '3.11', '3.12', '3.13']
1818
steps:
1919
- uses: actions/checkout@v3
2020
- name: Set up Python ${{ matrix.python-version }}
@@ -24,7 +24,7 @@ jobs:
2424
- name: Install dependencies
2525
run: |
2626
python -m pip install --upgrade pip
27-
python -m pip install pytest "asyncgui>=0.6,<0.7"
27+
python -m pip install pytest "asyncgui>=0.8,<0.9"
2828
python -m pip install .
2929
- name: Test with pytest
3030
run: make test

README.md

+32-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,46 @@
1-
# SyncTools
1+
# Queue
22

3-
Inter-task sychronization and communication.
3+
An `asyncio.Queue` equivalence for asyncgui.
4+
5+
```python
6+
import asyncgui as ag
7+
from asyncgui_ext.queue import Queue
8+
9+
async def producer(q):
10+
for c in "ABC":
11+
await q.put(c)
12+
print('produced', c)
13+
14+
async def consumer(q):
15+
async for c in q:
16+
print('consumed', c)
17+
18+
q = Queue(capacity=1)
19+
ag.start(producer(q))
20+
ag.start(consumer(q))
21+
```
22+
23+
```
24+
produced A
25+
produced B
26+
consumed A
27+
produced C
28+
consumed B
29+
consumed C
30+
```
431

532
## Installation
633

734
Pin the minor version.
835

936
```
10-
poetry add asyncgui-ext-synctools@~0.2
11-
pip install "asyncgui-ext-synctools>=0.2,<0.3"
37+
poetry add asyncgui-ext-queue@~0.3
38+
pip install "asyncgui-ext-queue>=0.3,<0.4"
1239
```
1340

1441
## Tested on
1542

1643
- CPython 3.10
1744
- CPython 3.11
1845
- CPython 3.12
46+
- CPython 3.13

poetry.lock

+49-11
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+7-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
[tool.poetry]
2-
name = "asyncgui-ext-synctools"
3-
version = "0.2.1.dev0"
4-
description = "Inter-task sychronization and communication."
2+
name = "asyncgui-ext-queue"
3+
version = "0.3.0"
4+
description = "An asyncio.Queue equivalence for asyncgui"
55
authors = ["Nattōsai Mitō <[email protected]>"]
66
license = "MIT"
77
readme = 'README.md'
8-
repository = 'https://github.com/asyncgui/asyncgui-ext-synctools'
9-
homepage = 'https://github.com/asyncgui/asyncgui-ext-synctools'
8+
repository = 'https://github.com/asyncgui/asyncgui-ext-queue'
9+
homepage = 'https://github.com/asyncgui/asyncgui-ext-queue'
1010
keywords = ['async', ]
1111
classifiers=[
1212
'Development Status :: 5 - Production/Stable',
@@ -16,6 +16,7 @@ classifiers=[
1616
'Programming Language :: Python :: 3.10',
1717
'Programming Language :: Python :: 3.11',
1818
'Programming Language :: Python :: 3.12',
19+
'Programming Language :: Python :: 3.13',
1920
'Topic :: Software Development :: Libraries',
2021
'Operating System :: OS Independent',
2122
]
@@ -25,7 +26,7 @@ packages = [
2526

2627
[tool.poetry.dependencies]
2728
python = "^3.10"
28-
asyncgui = "~0.7"
29+
asyncgui = ">=0.7,<0.9"
2930

3031
[tool.poetry.group.dev.dependencies]
3132
pytest = "^8.0"

sphinx/conf.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77

88
# -- Project information -----------------------------------------------------
99
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
10-
project = 'asyncgui-ext-synctools'
10+
project = 'asyncgui-ext-queue'
1111
copyright = '2024, Mitō Nattōsai'
1212
author = 'Mitō Nattōsai'
1313
release = importlib.metadata.version(project)

sphinx/index.rst

+115-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,118 @@
1-
=========
2-
SyncTools
3-
=========
1+
Queue
2+
=====
43

5-
Inter-task sychronization and communication.
4+
An :class:`asyncio.Queue` equivalence for asyncgui.
65

7-
.. toctree::
8-
:hidden:
6+
Usage
7+
-----
98

10-
queue
9+
.. code::
10+
11+
import asyncgui as ag
12+
from asyncgui_ext.queue import Queue
13+
14+
async def producer(q):
15+
for c in "ABC":
16+
await q.put(c)
17+
print('produced', c)
18+
19+
async def consumer(q):
20+
async for c in q:
21+
print('consumed', c)
22+
23+
q = Queue(capacity=1)
24+
ag.start(producer(q))
25+
ag.start(consumer(q))
26+
27+
.. code:: text
28+
29+
produced A
30+
produced B
31+
consumed A
32+
produced C
33+
consumed B
34+
consumed C
35+
36+
37+
API Reference
38+
-------------
39+
40+
.. automodule:: asyncgui_ext.queue
41+
:members:
42+
:undoc-members:
43+
:exclude-members:
44+
:special-members: __aiter__
45+
46+
47+
Quirk
48+
-----
49+
50+
The output of the following code may surprise you.
51+
52+
.. code::
53+
54+
async def fn1(q, received):
55+
await q.put('A')
56+
await q.put('B')
57+
item = await q.get()
58+
received.append(item)
59+
await q.put('C')
60+
item = await q.get()
61+
received.append(item)
62+
63+
async def fn2(q, received):
64+
item = await q.get()
65+
received.append(item)
66+
67+
received = []
68+
q = Queue(capacity=1)
69+
ag.start(fn1(q, received))
70+
ag.start(fn2(q, received))
71+
print(received)
72+
73+
.. code:: text
74+
75+
['B', 'C', 'A']
76+
77+
.. Why it doesn't print ``['A', 'B', 'C']`` when it clearly puts ``A``, ``B``, and ``C`` in that order?
78+
.. This is because :meth:`asyncgui_ext.queue.Queue.get` not only retrieves an item from the queue,
79+
.. but also fills the resulting vacancy with an item if there is a Task waiting to put one into the queue.
80+
.. Then if there is a Task waiting to get an item from the queue, it will be woken up and an item will be passed to it.
81+
.. And this goes forever until either of the following conditions are met:
82+
83+
.. 1. The queue is empty and there is no Task waiting to put an item into the queue.
84+
.. 2. The queue is full and there is no Task waiting to get an item from the queue.
85+
86+
.. 何故 ``A``, ``B``, ``C`` の順でキューに入れているのにその順で出力されないのか?
87+
.. それは :meth:`asyncgui_ext.queue.Queue.get` が只キューから取り出すだけでなく取り出してできた空きを埋めもするからです。
88+
.. そしてそれを終えた時にもしキューから受け取る為に停まっているタスクが居ればそれを再開させもします。
89+
.. そういった転送処理をその必要が無くなるまでやり続け、それが終わってようやく ``await queue.get()`` が完了します。
90+
.. なので上のコードの進行を追うと
91+
92+
..
93+
.. async def fn1(q, received):
94+
.. await q.put('A') # B
95+
.. await q.put('B') # C
96+
.. item = await q.get()
97+
.. received.append(item)
98+
.. await q.put('C')
99+
.. item = await q.get()
100+
.. received.append(item)
101+
102+
.. async def fn2(q, received):
103+
.. item = await q.get() # E
104+
.. received.append(item)
105+
106+
.. received = []
107+
.. q = Queue(capacity=1)
108+
.. ag.start(fn1(q, received)) # A
109+
.. ag.start(fn2(q, received)) # D
110+
.. print(received)
111+
112+
.. 1. ``fn1`` が始まる。 (A行)
113+
.. 2. ``fn1`` がキューに ``A`` を入れる事でキューが満たされる。 (B行)
114+
.. 3. ``fn1`` がキューに ``B`` を入れようとするが空きがないので空くまで待つ。 (C行)
115+
.. 4. ``fn1`` の進行が停まりA行が完遂される。
116+
.. 5. ``fn2`` が始まる。 (D行)
117+
.. 6. ``fn2`` がキューから ``A`` を取り出すがそれで終わりではない。 (E行)
118+
.. 7. 6によりキューに空きができたため ``fn1`` を再開する。

sphinx/queue.rst

-8
This file was deleted.

0 commit comments

Comments
 (0)