python-iterutils 0.0.4.5__py3-none-any.whl → 0.0.6__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 +155 -26
- {python_iterutils-0.0.4.5.dist-info → python_iterutils-0.0.6.dist-info}/METADATA +1 -1
- python_iterutils-0.0.6.dist-info/RECORD +7 -0
- python_iterutils-0.0.4.5.dist-info/RECORD +0 -7
- {python_iterutils-0.0.4.5.dist-info → python_iterutils-0.0.6.dist-info}/LICENSE +0 -0
- {python_iterutils-0.0.4.5.dist-info → python_iterutils-0.0.6.dist-info}/WHEEL +0 -0
iterutils/__init__.py
CHANGED
|
@@ -2,18 +2,20 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
|
|
4
4
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
5
|
-
__version__ = (0, 0,
|
|
5
|
+
__version__ = (0, 0, 6)
|
|
6
6
|
__all__ = [
|
|
7
7
|
"iterable", "async_iterable", "foreach", "async_foreach", "through", "async_through",
|
|
8
|
-
"wrap_iter", "wrap_aiter", "acc_step", "cut_iter", "run_gen_step",
|
|
8
|
+
"wrap_iter", "wrap_aiter", "acc_step", "cut_iter", "run_gen_step", "run_gen_step_iter",
|
|
9
|
+
"Yield", "YieldFrom",
|
|
9
10
|
]
|
|
10
11
|
|
|
12
|
+
from abc import ABC, abstractmethod
|
|
11
13
|
from asyncio import to_thread
|
|
12
14
|
from collections.abc import (
|
|
13
15
|
AsyncIterable, AsyncIterator, Awaitable, Callable, Generator, Iterable, Iterator,
|
|
14
16
|
)
|
|
15
17
|
from inspect import isawaitable
|
|
16
|
-
from typing import Any, TypeVar
|
|
18
|
+
from typing import overload, Any, Literal, NamedTuple, TypeVar
|
|
17
19
|
|
|
18
20
|
from asynctools import async_zip, ensure_async, ensure_aiter
|
|
19
21
|
|
|
@@ -21,6 +23,25 @@ from asynctools import async_zip, ensure_async, ensure_aiter
|
|
|
21
23
|
T = TypeVar("T")
|
|
22
24
|
|
|
23
25
|
|
|
26
|
+
class YieldBase(ABC, Iterable):
|
|
27
|
+
__slots__ = "value", "identity"
|
|
28
|
+
@property
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def yield_type(self, /) -> int:
|
|
31
|
+
...
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
@YieldBase.register
|
|
35
|
+
class Yield(NamedTuple):
|
|
36
|
+
value: Any
|
|
37
|
+
identity: bool = False
|
|
38
|
+
yield_type = 1 # type: ignore
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
class YieldFrom(Yield):
|
|
42
|
+
yield_type = 2
|
|
43
|
+
|
|
44
|
+
|
|
24
45
|
def iterable(it, /) -> bool:
|
|
25
46
|
try:
|
|
26
47
|
return isinstance(iter(it), Iterable)
|
|
@@ -35,23 +56,23 @@ def async_iterable(it, /) -> bool:
|
|
|
35
56
|
return False
|
|
36
57
|
|
|
37
58
|
|
|
38
|
-
def foreach(
|
|
59
|
+
def foreach(ret: Callable, iterable, /, *iterables):
|
|
39
60
|
if iterables:
|
|
40
61
|
for args in zip(iterable, *iterables):
|
|
41
|
-
|
|
62
|
+
ret(*args)
|
|
42
63
|
else:
|
|
43
64
|
for arg in iterable:
|
|
44
|
-
|
|
65
|
+
ret(arg)
|
|
45
66
|
|
|
46
67
|
|
|
47
|
-
async def async_foreach(
|
|
48
|
-
|
|
68
|
+
async def async_foreach(ret: Callable, iterable, /, *iterables, threaded: bool = True):
|
|
69
|
+
ret = ensure_async(ret, threaded=threaded)
|
|
49
70
|
if iterables:
|
|
50
71
|
async for args in async_zip(iterable, *iterables, threaded=threaded):
|
|
51
|
-
await
|
|
72
|
+
await ret(*args)
|
|
52
73
|
else:
|
|
53
74
|
async for arg in ensure_aiter(iterable, threaded=threaded):
|
|
54
|
-
await
|
|
75
|
+
await ret(arg)
|
|
55
76
|
|
|
56
77
|
|
|
57
78
|
def through(it: Iterable, /):
|
|
@@ -186,29 +207,27 @@ def run_gen_step(
|
|
|
186
207
|
async def process():
|
|
187
208
|
try:
|
|
188
209
|
if threaded:
|
|
189
|
-
|
|
210
|
+
ret = await to_thread(send, None)
|
|
190
211
|
else:
|
|
191
|
-
|
|
212
|
+
ret = send(None)
|
|
192
213
|
while True:
|
|
193
214
|
try:
|
|
194
|
-
if isawaitable(
|
|
195
|
-
ret = await
|
|
196
|
-
elif callable(
|
|
197
|
-
ret =
|
|
215
|
+
if isawaitable(ret):
|
|
216
|
+
ret = await ret
|
|
217
|
+
elif callable(ret):
|
|
218
|
+
ret = ret()
|
|
198
219
|
if isawaitable(ret):
|
|
199
220
|
ret = await ret
|
|
200
|
-
else:
|
|
201
|
-
ret = func
|
|
202
221
|
except BaseException as e:
|
|
203
222
|
if threaded:
|
|
204
|
-
|
|
223
|
+
ret = await to_thread(throw, e)
|
|
205
224
|
else:
|
|
206
|
-
|
|
225
|
+
ret = throw(e)
|
|
207
226
|
else:
|
|
208
227
|
if threaded:
|
|
209
|
-
|
|
228
|
+
ret = await to_thread(send, ret)
|
|
210
229
|
else:
|
|
211
|
-
|
|
230
|
+
ret = send(ret)
|
|
212
231
|
except StopIteration as e:
|
|
213
232
|
return e.value
|
|
214
233
|
finally:
|
|
@@ -235,14 +254,15 @@ def run_gen_step(
|
|
|
235
254
|
return result
|
|
236
255
|
else:
|
|
237
256
|
try:
|
|
238
|
-
|
|
257
|
+
ret = send(None)
|
|
239
258
|
while True:
|
|
240
259
|
try:
|
|
241
|
-
|
|
260
|
+
if callable(ret):
|
|
261
|
+
ret = ret()
|
|
242
262
|
except BaseException as e:
|
|
243
|
-
|
|
263
|
+
ret = throw(e)
|
|
244
264
|
else:
|
|
245
|
-
|
|
265
|
+
ret = send(ret)
|
|
246
266
|
except StopIteration as e:
|
|
247
267
|
result = e.value
|
|
248
268
|
if as_iter:
|
|
@@ -252,3 +272,112 @@ def run_gen_step(
|
|
|
252
272
|
if close is not None:
|
|
253
273
|
close()
|
|
254
274
|
|
|
275
|
+
|
|
276
|
+
@overload
|
|
277
|
+
def run_gen_step_iter(
|
|
278
|
+
gen_step: Generator | Callable[[], Generator],
|
|
279
|
+
threaded: bool = False,
|
|
280
|
+
*,
|
|
281
|
+
async_: Literal[False] = False,
|
|
282
|
+
) -> Iterator:
|
|
283
|
+
...
|
|
284
|
+
@overload
|
|
285
|
+
def run_gen_step_iter(
|
|
286
|
+
gen_step: Generator | Callable[[], Generator],
|
|
287
|
+
threaded: bool = False,
|
|
288
|
+
*,
|
|
289
|
+
async_: Literal[True],
|
|
290
|
+
) -> AsyncIterator:
|
|
291
|
+
...
|
|
292
|
+
def run_gen_step_iter(
|
|
293
|
+
gen_step: Generator | Callable[[], Generator],
|
|
294
|
+
threaded: bool = False,
|
|
295
|
+
*,
|
|
296
|
+
async_: bool = False,
|
|
297
|
+
) -> Iterator | AsyncIterator:
|
|
298
|
+
if callable(gen_step):
|
|
299
|
+
gen = gen_step()
|
|
300
|
+
close = gen.close
|
|
301
|
+
else:
|
|
302
|
+
gen = gen_step
|
|
303
|
+
close = None
|
|
304
|
+
send = gen.send
|
|
305
|
+
throw = gen.throw
|
|
306
|
+
if async_:
|
|
307
|
+
async def process():
|
|
308
|
+
try:
|
|
309
|
+
if threaded:
|
|
310
|
+
ret = await to_thread(send, None)
|
|
311
|
+
else:
|
|
312
|
+
ret = send(None)
|
|
313
|
+
while True:
|
|
314
|
+
yield_type = 0
|
|
315
|
+
identity = False
|
|
316
|
+
if isinstance(ret, YieldBase):
|
|
317
|
+
yield_type = ret.yield_type
|
|
318
|
+
ret, identity = ret
|
|
319
|
+
try:
|
|
320
|
+
if not identity:
|
|
321
|
+
if isawaitable(ret):
|
|
322
|
+
ret = await ret
|
|
323
|
+
elif callable(ret):
|
|
324
|
+
ret = ret()
|
|
325
|
+
if isawaitable(ret):
|
|
326
|
+
ret = await ret
|
|
327
|
+
else:
|
|
328
|
+
ret = ret
|
|
329
|
+
except BaseException as e:
|
|
330
|
+
if threaded:
|
|
331
|
+
ret = await to_thread(throw, e)
|
|
332
|
+
else:
|
|
333
|
+
ret = throw(e)
|
|
334
|
+
else:
|
|
335
|
+
match yield_type:
|
|
336
|
+
case 1:
|
|
337
|
+
yield ret
|
|
338
|
+
case 2:
|
|
339
|
+
async for val in ensure_aiter(ret, threaded=threaded):
|
|
340
|
+
yield val
|
|
341
|
+
if threaded:
|
|
342
|
+
ret = await to_thread(send, ret)
|
|
343
|
+
else:
|
|
344
|
+
ret = send(ret)
|
|
345
|
+
except (StopIteration, GeneratorExit):
|
|
346
|
+
pass
|
|
347
|
+
finally:
|
|
348
|
+
if close is not None:
|
|
349
|
+
if threaded:
|
|
350
|
+
await to_thread(close)
|
|
351
|
+
else:
|
|
352
|
+
close()
|
|
353
|
+
else:
|
|
354
|
+
def process():
|
|
355
|
+
try:
|
|
356
|
+
ret = send(None)
|
|
357
|
+
while True:
|
|
358
|
+
yield_type = 0
|
|
359
|
+
identity = False
|
|
360
|
+
if isinstance(ret, YieldBase):
|
|
361
|
+
yield_type = ret.yield_type
|
|
362
|
+
ret, identity = ret
|
|
363
|
+
try:
|
|
364
|
+
if not identity:
|
|
365
|
+
ret = ret() if callable(ret) else ret
|
|
366
|
+
except BaseException as e:
|
|
367
|
+
ret = throw(e)
|
|
368
|
+
else:
|
|
369
|
+
match yield_type:
|
|
370
|
+
case 1:
|
|
371
|
+
yield ret
|
|
372
|
+
case 2:
|
|
373
|
+
yield from ret
|
|
374
|
+
ret = send(ret)
|
|
375
|
+
except StopIteration as e:
|
|
376
|
+
return e.value
|
|
377
|
+
except GeneratorExit:
|
|
378
|
+
pass
|
|
379
|
+
finally:
|
|
380
|
+
if close is not None:
|
|
381
|
+
close()
|
|
382
|
+
return process()
|
|
383
|
+
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
2
|
+
iterutils/__init__.py,sha256=aYUSOaw43HFhnmfoT8pawi-KKY4WDOH_iXngkjqQd6o,11355
|
|
3
|
+
iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
python_iterutils-0.0.6.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
5
|
+
python_iterutils-0.0.6.dist-info/METADATA,sha256=-WzkUWH49JTub_IGyT4aT65QEjso9tjiGWGLzdyc5AQ,1382
|
|
6
|
+
python_iterutils-0.0.6.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
7
|
+
python_iterutils-0.0.6.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
2
|
-
iterutils/__init__.py,sha256=aUoT5_AkcRUYDM5M9WHckr_URTA01jKhbPDcufH90Ko,7381
|
|
3
|
-
iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
python_iterutils-0.0.4.5.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
5
|
-
python_iterutils-0.0.4.5.dist-info/METADATA,sha256=feKv9AWPu1xSoVXmPjJN86CY3xUzMLjaUEPbPpW79LY,1384
|
|
6
|
-
python_iterutils-0.0.4.5.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
7
|
-
python_iterutils-0.0.4.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|