queutils 0.8.5__py3-none-any.whl → 0.9.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- queutils/__init__.py +5 -0
- queutils/eventcounterqueue.py +116 -0
- {queutils-0.8.5.dist-info → queutils-0.9.3.dist-info}/METADATA +22 -8
- queutils-0.9.3.dist-info/RECORD +11 -0
- {queutils-0.8.5.dist-info → queutils-0.9.3.dist-info}/WHEEL +1 -1
- queutils-0.8.5.dist-info/RECORD +0 -10
- {queutils-0.8.5.dist-info → queutils-0.9.3.dist-info}/licenses/LICENSE +0 -0
queutils/__init__.py
CHANGED
@@ -2,10 +2,15 @@ from .countable import Countable as Countable
|
|
2
2
|
from .asyncqueue import AsyncQueue as AsyncQueue
|
3
3
|
from .iterablequeue import IterableQueue as IterableQueue, QueueDone as QueueDone
|
4
4
|
from .filequeue import FileQueue as FileQueue
|
5
|
+
from .eventcounterqueue import (
|
6
|
+
QCounter as QCounter,
|
7
|
+
EventCounterQueue as EventCounterQueue,
|
8
|
+
)
|
5
9
|
|
6
10
|
__all__ = [
|
7
11
|
"asyncqueue",
|
8
12
|
"countable",
|
13
|
+
"eventcounterqueue",
|
9
14
|
"filequeue",
|
10
15
|
"iterablequeue",
|
11
16
|
]
|
@@ -0,0 +1,116 @@
|
|
1
|
+
from asyncio import Queue
|
2
|
+
from typing import TypeVar
|
3
|
+
from deprecated import deprecated
|
4
|
+
from .countable import Countable
|
5
|
+
from .iterablequeue import IterableQueue, QueueDone
|
6
|
+
from collections import defaultdict
|
7
|
+
import logging
|
8
|
+
|
9
|
+
logger = logging.getLogger()
|
10
|
+
error = logger.error
|
11
|
+
message = logger.warning
|
12
|
+
verbose = logger.info
|
13
|
+
debug = logger.debug
|
14
|
+
|
15
|
+
###########################################
|
16
|
+
#
|
17
|
+
# class CounterQueue
|
18
|
+
#
|
19
|
+
###########################################
|
20
|
+
T = TypeVar("T")
|
21
|
+
|
22
|
+
|
23
|
+
@deprecated(version="0.9.1", reason="Use EventCounterQueue instead")
|
24
|
+
class CounterQueue(Queue[T], Countable):
|
25
|
+
"""
|
26
|
+
CounterQueue is a asyncio.Queue for counting items
|
27
|
+
"""
|
28
|
+
|
29
|
+
_counter: int
|
30
|
+
_count_items: bool
|
31
|
+
_batch: int
|
32
|
+
|
33
|
+
def __init__(
|
34
|
+
self, *args, count_items: bool = True, batch: int = 1, **kwargs
|
35
|
+
) -> None:
|
36
|
+
super().__init__(*args, **kwargs)
|
37
|
+
self._counter = 0
|
38
|
+
self._count_items = count_items
|
39
|
+
self._batch = batch
|
40
|
+
|
41
|
+
def task_done(self) -> None:
|
42
|
+
super().task_done()
|
43
|
+
if self._count_items:
|
44
|
+
self._counter += 1
|
45
|
+
return None
|
46
|
+
|
47
|
+
@property
|
48
|
+
def count(self) -> int:
|
49
|
+
"""Return number of completed tasks"""
|
50
|
+
return self._counter * self._batch
|
51
|
+
|
52
|
+
@property
|
53
|
+
def count_items(self) -> bool:
|
54
|
+
"""Whether or not count items"""
|
55
|
+
return self._count_items
|
56
|
+
|
57
|
+
|
58
|
+
class EventCounterQueue(IterableQueue[tuple[str, int]]):
|
59
|
+
"""
|
60
|
+
EventCounterQueue is a asyncio.Queue for counting events by name
|
61
|
+
"""
|
62
|
+
|
63
|
+
_counter: defaultdict[str, int]
|
64
|
+
_batch: int
|
65
|
+
|
66
|
+
def __init__(self, *args, batch: int = 1, **kwargs) -> None:
|
67
|
+
super().__init__(*args, **kwargs)
|
68
|
+
self._batch = batch
|
69
|
+
self._counter = defaultdict(int)
|
70
|
+
|
71
|
+
async def receive(self) -> tuple[str, int]:
|
72
|
+
"""Receive an event value from the queue and sum it"""
|
73
|
+
event: str
|
74
|
+
value: int
|
75
|
+
event, value = await super().get()
|
76
|
+
self._counter[event] += value
|
77
|
+
super().task_done()
|
78
|
+
return (event, value)
|
79
|
+
|
80
|
+
async def send(self, event: str = "count", value: int = 1) -> None:
|
81
|
+
"""Send count of an event"""
|
82
|
+
await super().put((event, value))
|
83
|
+
return None
|
84
|
+
|
85
|
+
def get_count(self, event: str = "count") -> int:
|
86
|
+
"""Return count for an event"""
|
87
|
+
return self._counter[event]
|
88
|
+
|
89
|
+
def get_counts(self) -> defaultdict[str, int]:
|
90
|
+
"""Return counts of all events"""
|
91
|
+
return self._counter
|
92
|
+
|
93
|
+
async def listen(self) -> defaultdict[str, int]:
|
94
|
+
"""Listen for event values"""
|
95
|
+
try:
|
96
|
+
while True:
|
97
|
+
await self.receive()
|
98
|
+
except QueueDone:
|
99
|
+
pass
|
100
|
+
return self.get_counts()
|
101
|
+
|
102
|
+
|
103
|
+
class QCounter:
|
104
|
+
def __init__(self, Q: Queue[int]):
|
105
|
+
self._count = 0
|
106
|
+
self._Q: Queue[int] = Q
|
107
|
+
|
108
|
+
@property
|
109
|
+
def count(self) -> int:
|
110
|
+
return self._count
|
111
|
+
|
112
|
+
async def start(self) -> None:
|
113
|
+
"""Read and count items from Q"""
|
114
|
+
while True:
|
115
|
+
self._count += await self._Q.get()
|
116
|
+
self._Q.task_done()
|
@@ -1,10 +1,11 @@
|
|
1
|
-
Metadata-Version: 2.
|
1
|
+
Metadata-Version: 2.4
|
2
2
|
Name: queutils
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.9.3
|
4
4
|
Summary: Handy Python Queue utilies
|
5
5
|
Project-URL: Homepage, https://github.com/Jylpah/queutils
|
6
6
|
Project-URL: Bug Tracker, https://github.com/Jylpah/queutils/issues
|
7
7
|
Author-email: Jylpah <jylpah@gmail.com>
|
8
|
+
License-File: LICENSE
|
8
9
|
Classifier: Development Status :: 4 - Beta
|
9
10
|
Classifier: Framework :: AsyncIO
|
10
11
|
Classifier: License :: OSI Approved :: MIT License
|
@@ -13,6 +14,7 @@ Classifier: Programming Language :: Python :: 3
|
|
13
14
|
Classifier: Topic :: Software Development :: Libraries
|
14
15
|
Requires-Python: >=3.11
|
15
16
|
Requires-Dist: aioconsole>=0.6
|
17
|
+
Requires-Dist: deprecated>=1.2.18
|
16
18
|
Provides-Extra: dev
|
17
19
|
Requires-Dist: build>=0.10; extra == 'dev'
|
18
20
|
Requires-Dist: hatchling>=1.22.4; extra == 'dev'
|
@@ -24,6 +26,7 @@ Requires-Dist: pytest-datafiles>=3.0; extra == 'dev'
|
|
24
26
|
Requires-Dist: pytest-timeout>=2.2; extra == 'dev'
|
25
27
|
Requires-Dist: pytest>=8.0; extra == 'dev'
|
26
28
|
Requires-Dist: ruff>=0.1.9; extra == 'dev'
|
29
|
+
Requires-Dist: types-deprecated>=1.2.15; extra == 'dev'
|
27
30
|
Description-Content-Type: text/markdown
|
28
31
|
|
29
32
|
[](https://github.com/Jylpah/queutils/actions/workflows/python-package.yml) [](https://codecov.io/gh/Jylpah/queutils)
|
@@ -32,14 +35,15 @@ Description-Content-Type: text/markdown
|
|
32
35
|
|
33
36
|
Queutils *[Queue Utils]* is a package of handy Python queue classes:
|
34
37
|
|
35
|
-
- **
|
36
|
-
- **
|
37
|
-
- **
|
38
|
+
- **AsyncQueue** - An `async` wrapper for non-async `queue.Queue`
|
39
|
+
- **IterableQueue** - An `AsyncIterable` queue that terminates when finished
|
40
|
+
- **EventCounterQueue** - An `IterableQueue` for counting events in `async` threads
|
41
|
+
- **FileQueue** - Builds an iterable queue of filenames from files/dirs given as input
|
38
42
|
|
39
43
|
|
40
44
|
# AsyncQueue
|
41
45
|
|
42
|
-
|
46
|
+
`AsyncQueue` is a async wrapper for non-async `queue.Queue`. It can be used to create
|
43
47
|
an `asyncio.Queue` compatible interface to a (non-async) managed `multiprocessing.Queue` and thus enable `async` code in parent/child processes to communicate over `multiprocessing.Queue` as it were an `asyncio.Queue`.
|
44
48
|
|
45
49
|
## Features
|
@@ -51,7 +55,7 @@ an `asyncio.Queue` compatible interface to a (non-async) managed `multiprocessin
|
|
51
55
|
|
52
56
|
# IterableQueue
|
53
57
|
|
54
|
-
|
58
|
+
`IterableQueue` is an `asyncio.Queue` subclass that is `AsyncIterable[T]` i.e. it can be
|
55
59
|
iterated in `async for` loop. `IterableQueue` terminates automatically when the queue has been filled and emptied.
|
56
60
|
|
57
61
|
The `IterableQueue` requires "producers" (functions adding items to the queue) to register themselves and it
|
@@ -71,9 +75,19 @@ producers are "finished", the queue enters into "filled" state and no new items
|
|
71
75
|
- Countable property can be disabled with count_items=False. This is useful when you
|
72
76
|
want to sum the count of multiple IterableQueues
|
73
77
|
|
78
|
+
# EventCounterQueue
|
79
|
+
|
80
|
+
`EventCounterQueue` can be used to count named events (default event is `count`) between `async` threads. `async` worker threads call `queue.send(event="event_name", N=amount)`. The receving end can either `receive()` a single event or `listen()` all events and return `collections.defaultdict[str, int]` as a result.
|
81
|
+
|
82
|
+
## Features
|
83
|
+
|
84
|
+
- Supports multiple producers and a single listener
|
85
|
+
- Default event is `count`
|
86
|
+
|
87
|
+
|
74
88
|
# FileQueue
|
75
89
|
|
76
|
-
|
90
|
+
`FileQueue` builds a queue (`IterableQueue[pathlib.Path]`) of the matching
|
77
91
|
files found based on search parameters given. It can search both list of files or directories or
|
78
92
|
mixed. Async method `FileQueue.mk_queue()` searches subdirectories of given directories.
|
79
93
|
|
@@ -0,0 +1,11 @@
|
|
1
|
+
queutils/__init__.py,sha256=rbDSh9513Dday-MfWzPOUfN7Aj2x4IqrvCmKbBj7has,441
|
2
|
+
queutils/asyncqueue.py,sha256=GZRmlWTBQoKzTf7xr4MI-qhNqvIiaNWswAxFokP91Lg,2789
|
3
|
+
queutils/countable.py,sha256=YSi7ILf9CuB5Tm3T4UUMEFlveqzqcmomfqJAlLGHEz8,172
|
4
|
+
queutils/eventcounterqueue.py,sha256=NjT8FqEskZhjmus7L333DZU9kXoZCNsn7ydCI5HSe1U,3047
|
5
|
+
queutils/filequeue.py,sha256=q2ly9H-lSCq6xuOqT1IlWgyCVyLoZiKbc0NuzmkF4aw,5360
|
6
|
+
queutils/iterablequeue.py,sha256=ZXwa9040yTawL1DMMNBXgQKiYr32nmzuSbgi-raAtZc,8664
|
7
|
+
queutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
8
|
+
queutils-0.9.3.dist-info/METADATA,sha256=VGe0K6t0aepLD6DlXlwjFiifK8IUZfcmQlOUXVCKFbA,4664
|
9
|
+
queutils-0.9.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
10
|
+
queutils-0.9.3.dist-info/licenses/LICENSE,sha256=J1zeIKU2JVQmhwO2hHQDK8WR6zjVZ-wX8r7ZlL45AbI,1063
|
11
|
+
queutils-0.9.3.dist-info/RECORD,,
|
queutils-0.8.5.dist-info/RECORD
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
queutils/__init__.py,sha256=MboAom80iQTQURz0liGv_f2ae2Np8YA5ORX1LwsNa50,311
|
2
|
-
queutils/asyncqueue.py,sha256=GZRmlWTBQoKzTf7xr4MI-qhNqvIiaNWswAxFokP91Lg,2789
|
3
|
-
queutils/countable.py,sha256=YSi7ILf9CuB5Tm3T4UUMEFlveqzqcmomfqJAlLGHEz8,172
|
4
|
-
queutils/filequeue.py,sha256=q2ly9H-lSCq6xuOqT1IlWgyCVyLoZiKbc0NuzmkF4aw,5360
|
5
|
-
queutils/iterablequeue.py,sha256=ZXwa9040yTawL1DMMNBXgQKiYr32nmzuSbgi-raAtZc,8664
|
6
|
-
queutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
7
|
-
queutils-0.8.5.dist-info/METADATA,sha256=6sJ7O4naraaat7-8ZFeTD9c_r1RFM9uDtkotLuX6aq0,4169
|
8
|
-
queutils-0.8.5.dist-info/WHEEL,sha256=C2FUgwZgiLbznR-k0b_5k3Ai_1aASOXDss3lzCUsUug,87
|
9
|
-
queutils-0.8.5.dist-info/licenses/LICENSE,sha256=J1zeIKU2JVQmhwO2hHQDK8WR6zjVZ-wX8r7ZlL45AbI,1063
|
10
|
-
queutils-0.8.5.dist-info/RECORD,,
|
File without changes
|