python-iterutils 0.0.9__py3-none-any.whl → 0.1.0__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.
- iterutils/__init__.py +183 -58
- {python_iterutils-0.0.9.dist-info → python_iterutils-0.1.0.dist-info}/METADATA +3 -5
- python_iterutils-0.1.0.dist-info/RECORD +7 -0
- python_iterutils-0.0.9.dist-info/RECORD +0 -7
- {python_iterutils-0.0.9.dist-info → python_iterutils-0.1.0.dist-info}/LICENSE +0 -0
- {python_iterutils-0.0.9.dist-info → python_iterutils-0.1.0.dist-info}/WHEEL +0 -0
iterutils/__init__.py
CHANGED
|
@@ -2,26 +2,26 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
|
|
4
4
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
5
|
-
__version__ = (0,
|
|
5
|
+
__version__ = (0, 1, 0)
|
|
6
6
|
__all__ = [
|
|
7
7
|
"iterable", "async_iterable", "foreach", "async_foreach", "through", "async_through",
|
|
8
|
-
"
|
|
9
|
-
"Return", "Yield", "YieldFrom",
|
|
8
|
+
"flatten", "async_flatten", "chunked", "wrap_iter", "wrap_aiter", "acc_step",
|
|
9
|
+
"cut_iter", "run_gen_step", "run_gen_step_iter", "Return", "Yield", "YieldFrom",
|
|
10
10
|
]
|
|
11
11
|
|
|
12
|
+
|
|
12
13
|
from abc import ABC, abstractmethod
|
|
13
14
|
from asyncio import to_thread
|
|
14
15
|
from collections.abc import (
|
|
15
|
-
AsyncIterable, AsyncIterator, Callable, Generator,
|
|
16
|
+
AsyncIterable, AsyncIterator, Buffer, Callable, Generator,
|
|
17
|
+
Iterable, Iterator, Sequence,
|
|
16
18
|
)
|
|
17
19
|
from dataclasses import dataclass
|
|
20
|
+
from itertools import batched, pairwise
|
|
18
21
|
from inspect import isawaitable
|
|
19
|
-
from typing import overload, Any, Literal
|
|
20
|
-
|
|
21
|
-
from asynctools import async_map, async_zip, ensure_async, ensure_aiter
|
|
22
|
-
|
|
22
|
+
from typing import overload, Any, Literal
|
|
23
23
|
|
|
24
|
-
|
|
24
|
+
from asynctools import async_map, async_zip, async_batched, ensure_async, ensure_aiter
|
|
25
25
|
|
|
26
26
|
|
|
27
27
|
@dataclass(slots=True, frozen=True)
|
|
@@ -48,21 +48,28 @@ class YieldFrom(YieldBase):
|
|
|
48
48
|
yield_type = 2
|
|
49
49
|
|
|
50
50
|
|
|
51
|
-
def iterable(
|
|
51
|
+
def iterable(iterable, /) -> bool:
|
|
52
52
|
try:
|
|
53
|
-
return isinstance(iter(
|
|
53
|
+
return isinstance(iter(iterable), Iterable)
|
|
54
54
|
except TypeError:
|
|
55
55
|
return False
|
|
56
56
|
|
|
57
57
|
|
|
58
|
-
def async_iterable(
|
|
58
|
+
def async_iterable(iterable, /) -> bool:
|
|
59
59
|
try:
|
|
60
|
-
return isinstance(iter(
|
|
60
|
+
return isinstance(iter(iterable), AsyncIterable)
|
|
61
61
|
except TypeError:
|
|
62
62
|
return False
|
|
63
63
|
|
|
64
64
|
|
|
65
|
-
def foreach(
|
|
65
|
+
def foreach(
|
|
66
|
+
value: Callable,
|
|
67
|
+
iterable: Iterable | AsyncIterable,
|
|
68
|
+
/,
|
|
69
|
+
*iterables: Iterable | AsyncIterable,
|
|
70
|
+
):
|
|
71
|
+
if not (isinstance(iterable, Iterable) and all(isinstance(it, Iterable) for it in iterables)):
|
|
72
|
+
return async_foreach(value, iterable, *iterables)
|
|
66
73
|
if iterables:
|
|
67
74
|
for args in zip(iterable, *iterables):
|
|
68
75
|
value(*args)
|
|
@@ -71,7 +78,13 @@ def foreach(value: Callable, iterable, /, *iterables):
|
|
|
71
78
|
value(arg)
|
|
72
79
|
|
|
73
80
|
|
|
74
|
-
async def async_foreach(
|
|
81
|
+
async def async_foreach(
|
|
82
|
+
value: Callable,
|
|
83
|
+
iterable: Iterable | AsyncIterable,
|
|
84
|
+
/,
|
|
85
|
+
*iterables: Iterable | AsyncIterable,
|
|
86
|
+
threaded: bool = True,
|
|
87
|
+
):
|
|
75
88
|
value = ensure_async(value, threaded=threaded)
|
|
76
89
|
if iterables:
|
|
77
90
|
async for args in async_zip(iterable, *iterables, threaded=threaded):
|
|
@@ -81,76 +94,188 @@ async def async_foreach(value: Callable, iterable, /, *iterables, threaded: bool
|
|
|
81
94
|
await value(arg)
|
|
82
95
|
|
|
83
96
|
|
|
84
|
-
def through(
|
|
97
|
+
def through(
|
|
98
|
+
iterable: Iterable | AsyncIterable,
|
|
99
|
+
/,
|
|
100
|
+
take_while: None | Callable = None,
|
|
101
|
+
):
|
|
102
|
+
if not isinstance(iterable, Iterable):
|
|
103
|
+
return async_through(iterable, take_while)
|
|
85
104
|
if take_while is None:
|
|
86
|
-
for _ in
|
|
105
|
+
for _ in iterable:
|
|
87
106
|
pass
|
|
88
107
|
else:
|
|
89
|
-
for v in map(take_while,
|
|
108
|
+
for v in map(take_while, iterable):
|
|
90
109
|
if not v:
|
|
91
110
|
break
|
|
92
111
|
|
|
93
112
|
|
|
94
113
|
async def async_through(
|
|
95
|
-
|
|
114
|
+
iterable: Iterable | AsyncIterable,
|
|
96
115
|
/,
|
|
97
116
|
take_while: None | Callable = None,
|
|
98
117
|
threaded: bool = True,
|
|
99
118
|
):
|
|
100
|
-
|
|
119
|
+
iterable = ensure_aiter(iterable, threaded=threaded)
|
|
101
120
|
if take_while is None:
|
|
102
|
-
async for _ in
|
|
121
|
+
async for _ in iterable:
|
|
103
122
|
pass
|
|
104
123
|
elif take_while is bool:
|
|
105
|
-
async for v in
|
|
124
|
+
async for v in iterable:
|
|
106
125
|
if not v:
|
|
107
126
|
break
|
|
108
127
|
else:
|
|
109
|
-
async for v in async_map(take_while,
|
|
128
|
+
async for v in async_map(take_while, iterable):
|
|
110
129
|
if not v:
|
|
111
130
|
break
|
|
112
131
|
|
|
113
132
|
|
|
114
|
-
|
|
115
|
-
|
|
133
|
+
@overload
|
|
134
|
+
def flatten(
|
|
135
|
+
iterable: Iterable,
|
|
136
|
+
/,
|
|
137
|
+
exclude_types: type | tuple[type, ...] = (Buffer, str),
|
|
138
|
+
) -> Iterable:
|
|
139
|
+
...
|
|
140
|
+
@overload
|
|
141
|
+
def flatten(
|
|
142
|
+
iterable: AsyncIterable,
|
|
143
|
+
/,
|
|
144
|
+
exclude_types: type | tuple[type, ...] = (Buffer, str),
|
|
145
|
+
) -> AsyncIterable:
|
|
146
|
+
...
|
|
147
|
+
def flatten(
|
|
148
|
+
iterable: Iterable | AsyncIterable,
|
|
149
|
+
/,
|
|
150
|
+
exclude_types: type | tuple[type, ...] = (Buffer, str),
|
|
151
|
+
) -> Iterable | AsyncIterable:
|
|
152
|
+
if not isinstance(iterable, Iterable):
|
|
153
|
+
return async_flatten(iterable, exclude_types)
|
|
154
|
+
def gen(iterable):
|
|
155
|
+
for e in iterable:
|
|
156
|
+
if isinstance(e, (Iterable, AsyncIterable)) and not isinstance(e, exclude_types):
|
|
157
|
+
yield from gen(e)
|
|
158
|
+
else:
|
|
159
|
+
yield e
|
|
160
|
+
return gen(iterable)
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
async def async_flatten(
|
|
164
|
+
iterable: Iterable | AsyncIterable,
|
|
165
|
+
/,
|
|
166
|
+
exclude_types: type | tuple[type, ...] = (Buffer, str),
|
|
167
|
+
threaded: bool = True,
|
|
168
|
+
) -> AsyncIterator:
|
|
169
|
+
async for e in ensure_aiter(iterable, threaded=threaded):
|
|
170
|
+
if isinstance(e, (Iterable, AsyncIterable)) and not isinstance(e, exclude_types):
|
|
171
|
+
async for e in async_flatten(e, exclude_types, threaded=threaded):
|
|
172
|
+
yield e
|
|
173
|
+
else:
|
|
174
|
+
yield e
|
|
175
|
+
|
|
176
|
+
|
|
177
|
+
@overload
|
|
178
|
+
def chunked[T](
|
|
179
|
+
iterable: Iterable[T],
|
|
180
|
+
n: int = 1,
|
|
181
|
+
/,
|
|
182
|
+
) -> Iterator[Sequence[T]]:
|
|
183
|
+
...
|
|
184
|
+
@overload
|
|
185
|
+
def chunked[T](
|
|
186
|
+
iterable: AsyncIterable[T],
|
|
187
|
+
n: int = 1,
|
|
188
|
+
/,
|
|
189
|
+
) -> AsyncIterator[Sequence[T]]:
|
|
190
|
+
...
|
|
191
|
+
def chunked[T](
|
|
192
|
+
iterable: Iterable[T] | AsyncIterable[T],
|
|
193
|
+
n: int = 1,
|
|
194
|
+
/,
|
|
195
|
+
) -> Iterator[Sequence[T]] | AsyncIterator[Sequence[T]]:
|
|
196
|
+
if n < 0:
|
|
197
|
+
n = 1
|
|
198
|
+
if isinstance(iterable, Sequence):
|
|
199
|
+
if n == 1:
|
|
200
|
+
return ((e,) for e in iterable)
|
|
201
|
+
return (iterable[i:j] for i, j in pairwise(range(0, len(iterable)+n, n)))
|
|
202
|
+
elif isinstance(iterable, Iterable):
|
|
203
|
+
return batched(iterable, n)
|
|
204
|
+
else:
|
|
205
|
+
return async_batched(iterable, n)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
@overload
|
|
209
|
+
def wrap_iter[T](
|
|
210
|
+
iterable: Iterable[T],
|
|
116
211
|
/,
|
|
117
212
|
callprev: None | Callable[[T], Any] = None,
|
|
118
213
|
callnext: None | Callable[[T], Any] = None,
|
|
119
214
|
callenter: None | Callable[[Iterable[T]], Any] = None,
|
|
120
215
|
callexit: None | Callable[[Iterable[T], None | BaseException], Any] = None,
|
|
121
216
|
) -> Iterator[T]:
|
|
217
|
+
...
|
|
218
|
+
@overload
|
|
219
|
+
def wrap_iter[T](
|
|
220
|
+
iterable: AsyncIterable[T],
|
|
221
|
+
/,
|
|
222
|
+
callprev: None | Callable[[T], Any] = None,
|
|
223
|
+
callnext: None | Callable[[T], Any] = None,
|
|
224
|
+
callenter: None | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
|
|
225
|
+
callexit: None | Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] = None,
|
|
226
|
+
) -> AsyncIterator[T]:
|
|
227
|
+
...
|
|
228
|
+
def wrap_iter[T](
|
|
229
|
+
iterable: Iterable[T] | AsyncIterable[T],
|
|
230
|
+
/,
|
|
231
|
+
callprev: None | Callable[[T], Any] = None,
|
|
232
|
+
callnext: None | Callable[[T], Any] = None,
|
|
233
|
+
callenter: None | Callable[[Iterable[T]], Any] | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
|
|
234
|
+
callexit: ( None | Callable[[Iterable[T], None | BaseException], Any] |
|
|
235
|
+
Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] ) = None,
|
|
236
|
+
) -> Iterator[T] | AsyncIterator[T]:
|
|
237
|
+
if not isinstance(iterable, Iterable):
|
|
238
|
+
return wrap_aiter(
|
|
239
|
+
iterable,
|
|
240
|
+
callprev=callprev,
|
|
241
|
+
callnext=callnext,
|
|
242
|
+
callenter=callenter, # type: ignore
|
|
243
|
+
callexit=callexit, # type: ignore
|
|
244
|
+
)
|
|
122
245
|
if not callable(callprev):
|
|
123
246
|
callprev = None
|
|
124
247
|
if not callable(callnext):
|
|
125
248
|
callnext = None
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
callenter
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
if
|
|
249
|
+
def gen():
|
|
250
|
+
try:
|
|
251
|
+
if callable(callenter):
|
|
252
|
+
callenter(iterable)
|
|
253
|
+
for e in iterable:
|
|
254
|
+
if callprev:
|
|
255
|
+
try:
|
|
256
|
+
callprev(e)
|
|
257
|
+
except (StopIteration, GeneratorExit):
|
|
258
|
+
break
|
|
259
|
+
yield e
|
|
260
|
+
if callnext:
|
|
261
|
+
try:
|
|
262
|
+
callnext(e)
|
|
263
|
+
except (StopIteration, GeneratorExit):
|
|
264
|
+
break
|
|
265
|
+
except BaseException as e:
|
|
266
|
+
if callable(callexit):
|
|
267
|
+
if not callexit(iterable, e):
|
|
268
|
+
raise
|
|
269
|
+
else:
|
|
144
270
|
raise
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
callexit(it, None)
|
|
271
|
+
finally:
|
|
272
|
+
if callable(callexit):
|
|
273
|
+
callexit(iterable, None)
|
|
274
|
+
return gen()
|
|
150
275
|
|
|
151
276
|
|
|
152
|
-
async def wrap_aiter(
|
|
153
|
-
|
|
277
|
+
async def wrap_aiter[T](
|
|
278
|
+
iterable: Iterable[T] | AsyncIterable[T],
|
|
154
279
|
/,
|
|
155
280
|
callprev: None | Callable[[T], Any] = None,
|
|
156
281
|
callnext: None | Callable[[T], Any] = None,
|
|
@@ -161,7 +286,7 @@ async def wrap_aiter(
|
|
|
161
286
|
callprev = ensure_async(callprev, threaded=threaded) if callable(callprev) else None
|
|
162
287
|
callnext = ensure_async(callnext, threaded=threaded) if callable(callnext) else None
|
|
163
288
|
try:
|
|
164
|
-
async for e in ensure_aiter(
|
|
289
|
+
async for e in ensure_aiter(iterable, threaded=threaded):
|
|
165
290
|
if callprev:
|
|
166
291
|
try:
|
|
167
292
|
await callprev(e)
|
|
@@ -175,13 +300,13 @@ async def wrap_aiter(
|
|
|
175
300
|
break
|
|
176
301
|
except BaseException as e:
|
|
177
302
|
if callable(callexit):
|
|
178
|
-
if not await ensure_async(callexit, threaded=threaded)(
|
|
303
|
+
if not await ensure_async(callexit, threaded=threaded)(iterable, e):
|
|
179
304
|
raise
|
|
180
305
|
else:
|
|
181
306
|
raise
|
|
182
307
|
finally:
|
|
183
308
|
if callable(callexit):
|
|
184
|
-
await ensure_async(callexit, threaded=threaded)(
|
|
309
|
+
await ensure_async(callexit, threaded=threaded)(iterable, None)
|
|
185
310
|
|
|
186
311
|
|
|
187
312
|
def acc_step(
|
|
@@ -210,7 +335,7 @@ def cut_iter(
|
|
|
210
335
|
yield stop, stop - start
|
|
211
336
|
|
|
212
337
|
|
|
213
|
-
def run_gen_step(
|
|
338
|
+
def run_gen_step[T](
|
|
214
339
|
gen_step: Generator[Any, Any, T] | Callable[[], Generator[Any, Any, T]],
|
|
215
340
|
*,
|
|
216
341
|
async_: bool = False,
|
|
@@ -272,16 +397,16 @@ def run_gen_step(
|
|
|
272
397
|
result = process()
|
|
273
398
|
if as_iter:
|
|
274
399
|
async def wrap(result):
|
|
275
|
-
|
|
400
|
+
iterable = await result
|
|
276
401
|
try:
|
|
277
|
-
|
|
402
|
+
iterable = aiter(iterable)
|
|
278
403
|
except TypeError:
|
|
279
|
-
for val in iter(
|
|
404
|
+
for val in iter(iterable):
|
|
280
405
|
if isawaitable(val):
|
|
281
406
|
val = await val
|
|
282
407
|
yield val
|
|
283
408
|
else:
|
|
284
|
-
async for val in
|
|
409
|
+
async for val in iterable:
|
|
285
410
|
yield val
|
|
286
411
|
result = wrap(result)
|
|
287
412
|
return result
|
|
@@ -1,28 +1,26 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-iterutils
|
|
3
|
-
Version: 0.0
|
|
3
|
+
Version: 0.1.0
|
|
4
4
|
Summary: Python another itertools.
|
|
5
5
|
Home-page: https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-iterutils
|
|
6
6
|
License: MIT
|
|
7
7
|
Keywords: iterable,iterutils
|
|
8
8
|
Author: ChenyangGao
|
|
9
9
|
Author-email: wosiwujm@gmail.com
|
|
10
|
-
Requires-Python: >=3.
|
|
10
|
+
Requires-Python: >=3.12,<4.0
|
|
11
11
|
Classifier: Development Status :: 5 - Production/Stable
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
|
15
15
|
Classifier: Programming Language :: Python
|
|
16
16
|
Classifier: Programming Language :: Python :: 3
|
|
17
|
-
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
19
17
|
Classifier: Programming Language :: Python :: 3.12
|
|
20
18
|
Classifier: Programming Language :: Python :: 3.13
|
|
21
19
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
22
20
|
Classifier: Topic :: Software Development
|
|
23
21
|
Classifier: Topic :: Software Development :: Libraries
|
|
24
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
-
Requires-Dist: python-asynctools (>=0.0.
|
|
23
|
+
Requires-Dist: python-asynctools (>=0.0.9)
|
|
26
24
|
Project-URL: Repository, https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-iterutils
|
|
27
25
|
Description-Content-Type: text/markdown
|
|
28
26
|
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
2
|
+
iterutils/__init__.py,sha256=m6CldG12romSrteHnbHufKlmbRjzd6LfnsxqrqCETwM,17487
|
|
3
|
+
iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
python_iterutils-0.1.0.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
5
|
+
python_iterutils-0.1.0.dist-info/METADATA,sha256=a1p4ibqdGfFKWEhsNSv80GJwd3PiNr7JNCmVOBEAb2U,1341
|
|
6
|
+
python_iterutils-0.1.0.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
7
|
+
python_iterutils-0.1.0.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
2
|
-
iterutils/__init__.py,sha256=1rn-CbwE-giO8p78etuppB6oUN4-g1vMRcAl3hrsPP8,13520
|
|
3
|
-
iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
python_iterutils-0.0.9.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
5
|
-
python_iterutils-0.0.9.dist-info/METADATA,sha256=N2GQcGvPH0jn7dvUbL08QnHb9ECe4q0KnDk7kIghAO0,1445
|
|
6
|
-
python_iterutils-0.0.9.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
7
|
-
python_iterutils-0.0.9.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|