python-iterutils 0.0.5__tar.gz → 0.0.7__tar.gz
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.
- {python_iterutils-0.0.5 → python_iterutils-0.0.7}/PKG-INFO +1 -1
- {python_iterutils-0.0.5 → python_iterutils-0.0.7}/iterutils/__init__.py +100 -77
- {python_iterutils-0.0.5 → python_iterutils-0.0.7}/pyproject.toml +1 -1
- {python_iterutils-0.0.5 → python_iterutils-0.0.7}/LICENSE +0 -0
- {python_iterutils-0.0.5 → python_iterutils-0.0.7}/iterutils/py.typed +0 -0
- {python_iterutils-0.0.5 → python_iterutils-0.0.7}/readme.md +0 -0
|
@@ -2,19 +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, 7)
|
|
6
6
|
__all__ = [
|
|
7
7
|
"iterable", "async_iterable", "foreach", "async_foreach", "through", "async_through",
|
|
8
8
|
"wrap_iter", "wrap_aiter", "acc_step", "cut_iter", "run_gen_step", "run_gen_step_iter",
|
|
9
9
|
"Yield", "YieldFrom",
|
|
10
10
|
]
|
|
11
11
|
|
|
12
|
+
from abc import ABC, abstractmethod
|
|
12
13
|
from asyncio import to_thread
|
|
13
14
|
from collections.abc import (
|
|
14
15
|
AsyncIterable, AsyncIterator, Awaitable, Callable, Generator, Iterable, Iterator,
|
|
15
16
|
)
|
|
16
17
|
from inspect import isawaitable
|
|
17
|
-
from typing import overload, Any, Literal, TypeVar
|
|
18
|
+
from typing import overload, Any, Literal, NamedTuple, TypeVar
|
|
18
19
|
|
|
19
20
|
from asynctools import async_zip, ensure_async, ensure_aiter
|
|
20
21
|
|
|
@@ -22,16 +23,24 @@ from asynctools import async_zip, ensure_async, ensure_aiter
|
|
|
22
23
|
T = TypeVar("T")
|
|
23
24
|
|
|
24
25
|
|
|
25
|
-
class
|
|
26
|
+
class YieldBase(ABC, Iterable):
|
|
27
|
+
__slots__ = "value", "identity", "try_call_me"
|
|
28
|
+
@property
|
|
29
|
+
@abstractmethod
|
|
30
|
+
def yield_type(self, /) -> int:
|
|
31
|
+
...
|
|
26
32
|
|
|
27
|
-
def __init__(self, value, /):
|
|
28
|
-
self.value = value
|
|
29
33
|
|
|
34
|
+
@YieldBase.register
|
|
35
|
+
class Yield(NamedTuple):
|
|
36
|
+
value: Any
|
|
37
|
+
identity: bool = False
|
|
38
|
+
try_call_me: bool = True
|
|
39
|
+
yield_type = 1 # type: ignore
|
|
30
40
|
|
|
31
|
-
class YieldFrom:
|
|
32
41
|
|
|
33
|
-
|
|
34
|
-
|
|
42
|
+
class YieldFrom(Yield):
|
|
43
|
+
yield_type = 2
|
|
35
44
|
|
|
36
45
|
|
|
37
46
|
def iterable(it, /) -> bool:
|
|
@@ -48,23 +57,23 @@ def async_iterable(it, /) -> bool:
|
|
|
48
57
|
return False
|
|
49
58
|
|
|
50
59
|
|
|
51
|
-
def foreach(
|
|
60
|
+
def foreach(ret: Callable, iterable, /, *iterables):
|
|
52
61
|
if iterables:
|
|
53
62
|
for args in zip(iterable, *iterables):
|
|
54
|
-
|
|
63
|
+
ret(*args)
|
|
55
64
|
else:
|
|
56
65
|
for arg in iterable:
|
|
57
|
-
|
|
66
|
+
ret(arg)
|
|
58
67
|
|
|
59
68
|
|
|
60
|
-
async def async_foreach(
|
|
61
|
-
|
|
69
|
+
async def async_foreach(ret: Callable, iterable, /, *iterables, threaded: bool = True):
|
|
70
|
+
ret = ensure_async(ret, threaded=threaded)
|
|
62
71
|
if iterables:
|
|
63
72
|
async for args in async_zip(iterable, *iterables, threaded=threaded):
|
|
64
|
-
await
|
|
73
|
+
await ret(*args)
|
|
65
74
|
else:
|
|
66
75
|
async for arg in ensure_aiter(iterable, threaded=threaded):
|
|
67
|
-
await
|
|
76
|
+
await ret(arg)
|
|
68
77
|
|
|
69
78
|
|
|
70
79
|
def through(it: Iterable, /):
|
|
@@ -199,29 +208,25 @@ def run_gen_step(
|
|
|
199
208
|
async def process():
|
|
200
209
|
try:
|
|
201
210
|
if threaded:
|
|
202
|
-
|
|
211
|
+
ret = await to_thread(send, None)
|
|
203
212
|
else:
|
|
204
|
-
|
|
213
|
+
ret = send(None)
|
|
205
214
|
while True:
|
|
206
215
|
try:
|
|
207
|
-
if
|
|
208
|
-
ret =
|
|
209
|
-
|
|
210
|
-
ret =
|
|
211
|
-
if isawaitable(ret):
|
|
212
|
-
ret = await ret
|
|
213
|
-
else:
|
|
214
|
-
ret = func
|
|
216
|
+
if callable(ret):
|
|
217
|
+
ret = ret()
|
|
218
|
+
if isawaitable(ret):
|
|
219
|
+
ret = await ret
|
|
215
220
|
except BaseException as e:
|
|
216
221
|
if threaded:
|
|
217
|
-
|
|
222
|
+
ret = await to_thread(throw, e)
|
|
218
223
|
else:
|
|
219
|
-
|
|
224
|
+
ret = throw(e)
|
|
220
225
|
else:
|
|
221
226
|
if threaded:
|
|
222
|
-
|
|
227
|
+
ret = await to_thread(send, ret)
|
|
223
228
|
else:
|
|
224
|
-
|
|
229
|
+
ret = send(ret)
|
|
225
230
|
except StopIteration as e:
|
|
226
231
|
return e.value
|
|
227
232
|
finally:
|
|
@@ -248,14 +253,15 @@ def run_gen_step(
|
|
|
248
253
|
return result
|
|
249
254
|
else:
|
|
250
255
|
try:
|
|
251
|
-
|
|
256
|
+
ret = send(None)
|
|
252
257
|
while True:
|
|
253
258
|
try:
|
|
254
|
-
|
|
259
|
+
if callable(ret):
|
|
260
|
+
ret = ret()
|
|
255
261
|
except BaseException as e:
|
|
256
|
-
|
|
262
|
+
ret = throw(e)
|
|
257
263
|
else:
|
|
258
|
-
|
|
264
|
+
ret = send(ret)
|
|
259
265
|
except StopIteration as e:
|
|
260
266
|
result = e.value
|
|
261
267
|
if as_iter:
|
|
@@ -298,45 +304,53 @@ def run_gen_step_iter(
|
|
|
298
304
|
throw = gen.throw
|
|
299
305
|
if async_:
|
|
300
306
|
async def process():
|
|
307
|
+
async def extract(ret):
|
|
308
|
+
yield_type = 0
|
|
309
|
+
identity = False
|
|
310
|
+
try_call_me = True
|
|
311
|
+
if isinstance(ret, YieldBase):
|
|
312
|
+
yield_type = ret.yield_type
|
|
313
|
+
ret, identity, try_call_me = ret
|
|
314
|
+
if not identity:
|
|
315
|
+
if try_call_me and callable(ret):
|
|
316
|
+
ret = ret()
|
|
317
|
+
if isawaitable(ret):
|
|
318
|
+
ret = await ret
|
|
319
|
+
return yield_type, ret
|
|
301
320
|
try:
|
|
302
321
|
if threaded:
|
|
303
|
-
|
|
322
|
+
ret = await to_thread(send, None)
|
|
304
323
|
else:
|
|
305
|
-
|
|
324
|
+
ret = send(None)
|
|
306
325
|
while True:
|
|
307
|
-
yield_type = 0
|
|
308
|
-
if isinstance(func, Yield):
|
|
309
|
-
yield_type = 1
|
|
310
|
-
elif isinstance(func, YieldFrom):
|
|
311
|
-
yield_type = 2
|
|
312
|
-
if yield_type:
|
|
313
|
-
func = func.value
|
|
314
326
|
try:
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
ret = func
|
|
327
|
+
yield_type, ret = await extract(ret)
|
|
328
|
+
match yield_type:
|
|
329
|
+
case 1:
|
|
330
|
+
yield ret
|
|
331
|
+
case 2:
|
|
332
|
+
async for val in ensure_aiter(ret, threaded=threaded):
|
|
333
|
+
yield val
|
|
323
334
|
except BaseException as e:
|
|
324
335
|
if threaded:
|
|
325
|
-
|
|
336
|
+
ret = await to_thread(throw, e)
|
|
326
337
|
else:
|
|
327
|
-
|
|
338
|
+
ret = throw(e)
|
|
328
339
|
else:
|
|
329
|
-
if
|
|
340
|
+
if threaded:
|
|
341
|
+
ret = await to_thread(send, ret)
|
|
342
|
+
else:
|
|
343
|
+
ret = send(ret)
|
|
344
|
+
except StopIteration as e:
|
|
345
|
+
ret = e.value
|
|
346
|
+
if isinstance(ret, YieldBase):
|
|
347
|
+
yield_type, ret = await extract(ret)
|
|
348
|
+
match yield_type:
|
|
349
|
+
case 1:
|
|
330
350
|
yield ret
|
|
331
|
-
|
|
351
|
+
case 2:
|
|
332
352
|
async for val in ensure_aiter(ret, threaded=threaded):
|
|
333
353
|
yield val
|
|
334
|
-
if threaded:
|
|
335
|
-
func = await to_thread(send, ret)
|
|
336
|
-
else:
|
|
337
|
-
func = send(ret)
|
|
338
|
-
except (StopIteration, GeneratorExit):
|
|
339
|
-
pass
|
|
340
354
|
finally:
|
|
341
355
|
if close is not None:
|
|
342
356
|
if threaded:
|
|
@@ -345,30 +359,39 @@ def run_gen_step_iter(
|
|
|
345
359
|
close()
|
|
346
360
|
else:
|
|
347
361
|
def process():
|
|
362
|
+
def extract(ret):
|
|
363
|
+
yield_type = 0
|
|
364
|
+
identity = False
|
|
365
|
+
try_call_me = True
|
|
366
|
+
if isinstance(ret, YieldBase):
|
|
367
|
+
yield_type = ret.yield_type
|
|
368
|
+
ret, identity, try_call_me = ret
|
|
369
|
+
if not identity and try_call_me and callable(ret):
|
|
370
|
+
ret = ret()
|
|
371
|
+
return yield_type, ret
|
|
348
372
|
try:
|
|
349
|
-
|
|
373
|
+
ret = send(None)
|
|
350
374
|
while True:
|
|
351
|
-
yield_type = 0
|
|
352
|
-
if isinstance(func, Yield):
|
|
353
|
-
yield_type = 1
|
|
354
|
-
elif isinstance(func, YieldFrom):
|
|
355
|
-
yield_type = 2
|
|
356
|
-
if yield_type:
|
|
357
|
-
func = func.value
|
|
358
375
|
try:
|
|
359
|
-
ret =
|
|
376
|
+
yield_type, ret = extract(ret)
|
|
377
|
+
match yield_type:
|
|
378
|
+
case 1:
|
|
379
|
+
yield ret
|
|
380
|
+
case 2:
|
|
381
|
+
yield from ret
|
|
360
382
|
except BaseException as e:
|
|
361
|
-
|
|
383
|
+
ret = throw(e)
|
|
362
384
|
else:
|
|
363
|
-
|
|
385
|
+
ret = send(ret)
|
|
386
|
+
except StopIteration as e:
|
|
387
|
+
ret = e.value
|
|
388
|
+
if isinstance(ret, YieldBase):
|
|
389
|
+
yield_type, ret = extract(ret)
|
|
390
|
+
match yield_type:
|
|
391
|
+
case 1:
|
|
364
392
|
yield ret
|
|
365
|
-
|
|
393
|
+
case 2:
|
|
366
394
|
yield from ret
|
|
367
|
-
func = send(ret)
|
|
368
|
-
except StopIteration as e:
|
|
369
|
-
return e.value
|
|
370
|
-
except GeneratorExit:
|
|
371
|
-
pass
|
|
372
395
|
finally:
|
|
373
396
|
if close is not None:
|
|
374
397
|
close()
|
|
File without changes
|
|
File without changes
|
|
File without changes
|