python-iterutils 0.2__py3-none-any.whl → 0.2.1__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 +237 -204
- {python_iterutils-0.2.dist-info → python_iterutils-0.2.1.dist-info}/METADATA +1 -1
- python_iterutils-0.2.1.dist-info/RECORD +7 -0
- python_iterutils-0.2.dist-info/RECORD +0 -7
- {python_iterutils-0.2.dist-info → python_iterutils-0.2.1.dist-info}/LICENSE +0 -0
- {python_iterutils-0.2.dist-info → python_iterutils-0.2.1.dist-info}/WHEEL +0 -0
iterutils/__init__.py
CHANGED
|
@@ -2,14 +2,16 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
|
|
4
4
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
5
|
-
__version__ = (0, 2)
|
|
5
|
+
__version__ = (0, 2, 1)
|
|
6
6
|
__all__ = [
|
|
7
|
-
"Return", "Yield", "YieldFrom", "iterable", "async_iterable",
|
|
8
|
-
"
|
|
9
|
-
"
|
|
10
|
-
"
|
|
11
|
-
"
|
|
12
|
-
"
|
|
7
|
+
"Return", "Yield", "YieldFrom", "iterable", "async_iterable",
|
|
8
|
+
"foreach", "async_foreach", "through", "async_through", "flatten",
|
|
9
|
+
"async_flatten", "collect", "async_collect", "group_collect",
|
|
10
|
+
"async_group_collect", "map", "filter", "reduce", "zip", "chunked",
|
|
11
|
+
"iter_unique", "async_iter_unique", "wrap_iter", "wrap_aiter",
|
|
12
|
+
"acc_step", "cut_iter", "iter_gen_step", "iter_gen_step_async",
|
|
13
|
+
"run_gen_step", "run_gen_step_iter", "as_gen_step", "bfs_gen",
|
|
14
|
+
"with_iter_next", "backgroud_loop",
|
|
13
15
|
]
|
|
14
16
|
|
|
15
17
|
from abc import ABC, abstractmethod
|
|
@@ -17,11 +19,14 @@ from asyncio import create_task, sleep as async_sleep, to_thread
|
|
|
17
19
|
from builtins import map as _map, filter as _filter, zip as _zip
|
|
18
20
|
from collections import defaultdict, deque
|
|
19
21
|
from collections.abc import (
|
|
20
|
-
AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable,
|
|
21
|
-
Coroutine, Generator, Iterable, Iterator,
|
|
22
|
-
MutableSequence, Sequence,
|
|
22
|
+
AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable,
|
|
23
|
+
Collection, Container, Coroutine, Generator, Iterable, Iterator,
|
|
24
|
+
Mapping, MutableMapping, MutableSet, MutableSequence, Sequence,
|
|
25
|
+
ValuesView,
|
|
26
|
+
)
|
|
27
|
+
from contextlib import (
|
|
28
|
+
asynccontextmanager, contextmanager, ExitStack, AsyncExitStack,
|
|
23
29
|
)
|
|
24
|
-
from contextlib import asynccontextmanager, contextmanager, ExitStack, AsyncExitStack
|
|
25
30
|
from copy import copy
|
|
26
31
|
from dataclasses import dataclass
|
|
27
32
|
from itertools import batched, pairwise
|
|
@@ -30,11 +35,14 @@ from sys import _getframe
|
|
|
30
35
|
from _thread import start_new_thread
|
|
31
36
|
from time import sleep, time
|
|
32
37
|
from types import FrameType
|
|
33
|
-
from typing import
|
|
38
|
+
from typing import (
|
|
39
|
+
cast, overload, Any, AsyncContextManager, ContextManager, Literal,
|
|
40
|
+
Protocol,
|
|
41
|
+
)
|
|
34
42
|
|
|
35
43
|
from asynctools import (
|
|
36
|
-
async_filter, async_map, async_reduce, async_zip, async_batched,
|
|
37
|
-
collect as async_collect,
|
|
44
|
+
async_filter, async_map, async_reduce, async_zip, async_batched,
|
|
45
|
+
ensure_async, ensure_aiter, collect as async_collect,
|
|
38
46
|
)
|
|
39
47
|
from decotools import optional
|
|
40
48
|
from texttools import format_time
|
|
@@ -42,22 +50,27 @@ from undefined import undefined
|
|
|
42
50
|
|
|
43
51
|
|
|
44
52
|
class SupportsBool(Protocol):
|
|
53
|
+
"""
|
|
54
|
+
"""
|
|
45
55
|
def __bool__(self, /) -> bool: ...
|
|
46
56
|
|
|
47
57
|
|
|
48
58
|
class Reraised(BaseException):
|
|
49
|
-
|
|
59
|
+
"""
|
|
60
|
+
"""
|
|
50
61
|
def __init__(self, exc: BaseException, /):
|
|
51
62
|
if isinstance(exc, Reraised):
|
|
52
63
|
exc = exc.exception
|
|
53
64
|
self.exception: BaseException = exc
|
|
54
65
|
|
|
55
66
|
|
|
56
|
-
@dataclass(slots=True, frozen=True)
|
|
67
|
+
@dataclass(slots=True, frozen=True, unsafe_hash=True)
|
|
57
68
|
class YieldBase(ABC):
|
|
69
|
+
"""
|
|
70
|
+
"""
|
|
58
71
|
value: Any
|
|
59
|
-
may_await: None | bool =
|
|
60
|
-
may_call: None | bool =
|
|
72
|
+
may_await: None | bool | Literal[1] = False
|
|
73
|
+
may_call: None | bool | Literal[1] = None
|
|
61
74
|
|
|
62
75
|
@property
|
|
63
76
|
@abstractmethod
|
|
@@ -66,18 +79,29 @@ class YieldBase(ABC):
|
|
|
66
79
|
|
|
67
80
|
|
|
68
81
|
class Return(YieldBase):
|
|
82
|
+
"""
|
|
83
|
+
"""
|
|
84
|
+
__slots__ = ()
|
|
69
85
|
yield_type = 0
|
|
70
86
|
|
|
71
87
|
|
|
72
88
|
class Yield(YieldBase):
|
|
89
|
+
"""
|
|
90
|
+
"""
|
|
91
|
+
__slots__ = ()
|
|
73
92
|
yield_type = 1
|
|
74
93
|
|
|
75
94
|
|
|
76
95
|
class YieldFrom(YieldBase):
|
|
96
|
+
"""
|
|
97
|
+
"""
|
|
98
|
+
__slots__ = ()
|
|
77
99
|
yield_type = 2
|
|
78
100
|
|
|
79
101
|
|
|
80
102
|
def iterable(iterable, /) -> bool:
|
|
103
|
+
"""
|
|
104
|
+
"""
|
|
81
105
|
try:
|
|
82
106
|
return isinstance(iter(iterable), Iterable)
|
|
83
107
|
except TypeError:
|
|
@@ -85,6 +109,8 @@ def iterable(iterable, /) -> bool:
|
|
|
85
109
|
|
|
86
110
|
|
|
87
111
|
def async_iterable(iterable, /) -> bool:
|
|
112
|
+
"""
|
|
113
|
+
"""
|
|
88
114
|
try:
|
|
89
115
|
return isinstance(iter(iterable), AsyncIterable)
|
|
90
116
|
except TypeError:
|
|
@@ -97,6 +123,8 @@ def foreach(
|
|
|
97
123
|
/,
|
|
98
124
|
*iterables: Iterable | AsyncIterable,
|
|
99
125
|
):
|
|
126
|
+
"""
|
|
127
|
+
"""
|
|
100
128
|
if not (isinstance(iterable, Iterable) and all(isinstance(it, Iterable) for it in iterables)):
|
|
101
129
|
return async_foreach(value, iterable, *iterables)
|
|
102
130
|
if iterables:
|
|
@@ -114,6 +142,8 @@ async def async_foreach(
|
|
|
114
142
|
*iterables: Iterable | AsyncIterable,
|
|
115
143
|
threaded: bool = False,
|
|
116
144
|
):
|
|
145
|
+
"""
|
|
146
|
+
"""
|
|
117
147
|
value = ensure_async(value, threaded=threaded)
|
|
118
148
|
if iterables:
|
|
119
149
|
async for args in async_zip(iterable, *iterables, threaded=threaded):
|
|
@@ -128,6 +158,8 @@ def through(
|
|
|
128
158
|
/,
|
|
129
159
|
take_while: None | Callable = None,
|
|
130
160
|
):
|
|
161
|
+
"""
|
|
162
|
+
"""
|
|
131
163
|
if not isinstance(iterable, Iterable):
|
|
132
164
|
return async_through(iterable, take_while)
|
|
133
165
|
if take_while is None:
|
|
@@ -145,6 +177,8 @@ async def async_through(
|
|
|
145
177
|
take_while: None | Callable = None,
|
|
146
178
|
threaded: bool = False,
|
|
147
179
|
):
|
|
180
|
+
"""
|
|
181
|
+
"""
|
|
148
182
|
iterable = ensure_aiter(iterable, threaded=threaded)
|
|
149
183
|
if take_while is None:
|
|
150
184
|
async for _ in iterable:
|
|
@@ -178,6 +212,8 @@ def flatten(
|
|
|
178
212
|
/,
|
|
179
213
|
exclude_types: type | tuple[type, ...] = (Buffer, str),
|
|
180
214
|
) -> Iterator | AsyncIterator:
|
|
215
|
+
"""
|
|
216
|
+
"""
|
|
181
217
|
if not isinstance(iterable, Iterable):
|
|
182
218
|
return async_flatten(iterable, exclude_types)
|
|
183
219
|
def gen(iterable):
|
|
@@ -195,6 +231,8 @@ async def async_flatten(
|
|
|
195
231
|
exclude_types: type | tuple[type, ...] = (Buffer, str),
|
|
196
232
|
threaded: bool = False,
|
|
197
233
|
) -> AsyncIterator:
|
|
234
|
+
"""
|
|
235
|
+
"""
|
|
198
236
|
async for e in ensure_aiter(iterable, threaded=threaded):
|
|
199
237
|
if isinstance(e, (Iterable, AsyncIterable)) and not isinstance(e, exclude_types):
|
|
200
238
|
async for e in async_flatten(e, exclude_types, threaded=threaded):
|
|
@@ -236,6 +274,8 @@ def collect(
|
|
|
236
274
|
/,
|
|
237
275
|
rettype: Callable[[Iterable], Collection] = list,
|
|
238
276
|
) -> Collection | Coroutine[Any, Any, Collection]:
|
|
277
|
+
"""
|
|
278
|
+
"""
|
|
239
279
|
if not isinstance(iterable, Iterable):
|
|
240
280
|
return async_collect(iterable, rettype)
|
|
241
281
|
return rettype(iterable)
|
|
@@ -274,6 +314,8 @@ def group_collect[K, V, C: Container, M: MutableMapping](
|
|
|
274
314
|
mapping: None | M = None,
|
|
275
315
|
factory: None | C | Callable[[], C] = None,
|
|
276
316
|
) -> dict[K, C] | M | Coroutine[Any, Any, dict[K, C]] | Coroutine[Any, Any, M]:
|
|
317
|
+
"""
|
|
318
|
+
"""
|
|
277
319
|
if not isinstance(iterable, Iterable):
|
|
278
320
|
return async_group_collect(iterable, mapping, factory)
|
|
279
321
|
if factory is None:
|
|
@@ -331,6 +373,8 @@ async def async_group_collect[K, V, C: Container, M: MutableMapping](
|
|
|
331
373
|
factory: None | C | Callable[[], C] = None,
|
|
332
374
|
threaded: bool = False,
|
|
333
375
|
) -> dict[K, C] | M:
|
|
376
|
+
"""
|
|
377
|
+
"""
|
|
334
378
|
iterable = ensure_aiter(iterable, threaded=threaded)
|
|
335
379
|
if factory is None:
|
|
336
380
|
if isinstance(mapping, defaultdict):
|
|
@@ -370,7 +414,9 @@ def map(
|
|
|
370
414
|
iterable: Iterable | AsyncIterable,
|
|
371
415
|
/,
|
|
372
416
|
*iterables: Iterable | AsyncIterable,
|
|
373
|
-
):
|
|
417
|
+
):
|
|
418
|
+
"""
|
|
419
|
+
"""
|
|
374
420
|
if (
|
|
375
421
|
iscoroutinefunction(function) or
|
|
376
422
|
isinstance(iterable, AsyncIterable) or
|
|
@@ -395,6 +441,8 @@ def filter(
|
|
|
395
441
|
iterable: Iterable | AsyncIterable,
|
|
396
442
|
/,
|
|
397
443
|
):
|
|
444
|
+
"""
|
|
445
|
+
"""
|
|
398
446
|
if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
|
|
399
447
|
return async_filter(function, iterable)
|
|
400
448
|
return _filter(function, iterable)
|
|
@@ -406,6 +454,8 @@ def reduce(
|
|
|
406
454
|
initial: Any = undefined,
|
|
407
455
|
/,
|
|
408
456
|
):
|
|
457
|
+
"""
|
|
458
|
+
"""
|
|
409
459
|
if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
|
|
410
460
|
return async_reduce(function, iterable, initial)
|
|
411
461
|
from functools import reduce
|
|
@@ -419,6 +469,8 @@ def zip(
|
|
|
419
469
|
/,
|
|
420
470
|
*iterables: Iterable | AsyncIterable,
|
|
421
471
|
):
|
|
472
|
+
"""
|
|
473
|
+
"""
|
|
422
474
|
if isinstance(iterable, AsyncIterable) or any(isinstance(i, AsyncIterable) for i in iterables):
|
|
423
475
|
return async_zip(iterable, *iterables)
|
|
424
476
|
return _zip(iterable, *iterables)
|
|
@@ -443,6 +495,8 @@ def chunked[T](
|
|
|
443
495
|
n: int = 1,
|
|
444
496
|
/,
|
|
445
497
|
) -> Iterator[Sequence[T]] | AsyncIterator[Sequence[T]]:
|
|
498
|
+
"""
|
|
499
|
+
"""
|
|
446
500
|
if n < 0:
|
|
447
501
|
n = 1
|
|
448
502
|
if isinstance(iterable, Sequence):
|
|
@@ -474,6 +528,8 @@ def iter_unique[T](
|
|
|
474
528
|
/,
|
|
475
529
|
seen: None | MutableSet = None,
|
|
476
530
|
) -> Iterator[T] | AsyncIterator[T]:
|
|
531
|
+
"""
|
|
532
|
+
"""
|
|
477
533
|
if not isinstance(iterable, Iterable):
|
|
478
534
|
return async_iter_unique(iterable, seen)
|
|
479
535
|
if seen is None:
|
|
@@ -493,6 +549,8 @@ async def async_iter_unique[T](
|
|
|
493
549
|
seen: None | MutableSet = None,
|
|
494
550
|
threaded: bool = False,
|
|
495
551
|
) -> AsyncIterator[T]:
|
|
552
|
+
"""
|
|
553
|
+
"""
|
|
496
554
|
if seen is None:
|
|
497
555
|
seen = set()
|
|
498
556
|
add = seen.add
|
|
@@ -508,8 +566,6 @@ def wrap_iter[T](
|
|
|
508
566
|
/,
|
|
509
567
|
callprev: None | Callable[[T], Any] = None,
|
|
510
568
|
callnext: None | Callable[[T], Any] = None,
|
|
511
|
-
callenter: None | Callable[[Iterable[T]], Any] = None,
|
|
512
|
-
callexit: None | Callable[[Iterable[T], None | BaseException], Any] = None,
|
|
513
569
|
) -> Iterator[T]:
|
|
514
570
|
...
|
|
515
571
|
@overload
|
|
@@ -518,8 +574,6 @@ def wrap_iter[T](
|
|
|
518
574
|
/,
|
|
519
575
|
callprev: None | Callable[[T], Any] = None,
|
|
520
576
|
callnext: None | Callable[[T], Any] = None,
|
|
521
|
-
callenter: None | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
|
|
522
|
-
callexit: None | Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] = None,
|
|
523
577
|
) -> AsyncIterator[T]:
|
|
524
578
|
...
|
|
525
579
|
def wrap_iter[T](
|
|
@@ -527,47 +581,24 @@ def wrap_iter[T](
|
|
|
527
581
|
/,
|
|
528
582
|
callprev: None | Callable[[T], Any] = None,
|
|
529
583
|
callnext: None | Callable[[T], Any] = None,
|
|
530
|
-
callenter: None | Callable[[Iterable[T]], Any] | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
|
|
531
|
-
callexit: ( None | Callable[[Iterable[T], None | BaseException], Any] |
|
|
532
|
-
Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] ) = None,
|
|
533
584
|
) -> Iterator[T] | AsyncIterator[T]:
|
|
585
|
+
"""
|
|
586
|
+
"""
|
|
534
587
|
if not isinstance(iterable, Iterable):
|
|
535
588
|
return wrap_aiter(
|
|
536
589
|
iterable,
|
|
537
590
|
callprev=callprev,
|
|
538
591
|
callnext=callnext,
|
|
539
|
-
callenter=callenter, # type: ignore
|
|
540
|
-
callexit=callexit, # type: ignore
|
|
541
592
|
)
|
|
542
593
|
if not callable(callprev):
|
|
543
594
|
callprev = None
|
|
544
595
|
if not callable(callnext):
|
|
545
596
|
callnext = None
|
|
546
597
|
def gen():
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
if callprev:
|
|
552
|
-
try:
|
|
553
|
-
callprev(e)
|
|
554
|
-
except (StopIteration, GeneratorExit):
|
|
555
|
-
break
|
|
556
|
-
yield e
|
|
557
|
-
if callnext:
|
|
558
|
-
try:
|
|
559
|
-
callnext(e)
|
|
560
|
-
except (StopIteration, GeneratorExit):
|
|
561
|
-
break
|
|
562
|
-
except BaseException as e:
|
|
563
|
-
if callable(callexit):
|
|
564
|
-
if not callexit(iterable, e):
|
|
565
|
-
raise
|
|
566
|
-
else:
|
|
567
|
-
raise
|
|
568
|
-
finally:
|
|
569
|
-
if callable(callexit):
|
|
570
|
-
callexit(iterable, None)
|
|
598
|
+
for e in iterable:
|
|
599
|
+
callprev and callprev(e)
|
|
600
|
+
yield e
|
|
601
|
+
callnext and callnext(e)
|
|
571
602
|
return gen()
|
|
572
603
|
|
|
573
604
|
|
|
@@ -576,34 +607,16 @@ async def wrap_aiter[T](
|
|
|
576
607
|
/,
|
|
577
608
|
callprev: None | Callable[[T], Any] = None,
|
|
578
609
|
callnext: None | Callable[[T], Any] = None,
|
|
579
|
-
callenter: None | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
|
|
580
|
-
callexit: None | Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] = None,
|
|
581
610
|
threaded: bool = False,
|
|
582
611
|
) -> AsyncIterator[T]:
|
|
612
|
+
"""
|
|
613
|
+
"""
|
|
583
614
|
callprev = ensure_async(callprev, threaded=threaded) if callable(callprev) else None
|
|
584
615
|
callnext = ensure_async(callnext, threaded=threaded) if callable(callnext) else None
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
await callprev(e)
|
|
590
|
-
except (StopAsyncIteration, GeneratorExit):
|
|
591
|
-
break
|
|
592
|
-
yield e
|
|
593
|
-
if callnext:
|
|
594
|
-
try:
|
|
595
|
-
await callnext(e)
|
|
596
|
-
except (StopAsyncIteration, GeneratorExit):
|
|
597
|
-
break
|
|
598
|
-
except BaseException as e:
|
|
599
|
-
if callable(callexit):
|
|
600
|
-
if not await ensure_async(callexit, threaded=threaded)(iterable, e):
|
|
601
|
-
raise
|
|
602
|
-
else:
|
|
603
|
-
raise
|
|
604
|
-
finally:
|
|
605
|
-
if callable(callexit):
|
|
606
|
-
await ensure_async(callexit, threaded=threaded)(iterable, None)
|
|
616
|
+
async for e in ensure_aiter(iterable, threaded=threaded):
|
|
617
|
+
callprev and await callprev(e)
|
|
618
|
+
yield e
|
|
619
|
+
callnext and await callnext(e)
|
|
607
620
|
|
|
608
621
|
|
|
609
622
|
def acc_step(
|
|
@@ -611,6 +624,8 @@ def acc_step(
|
|
|
611
624
|
stop: None | int = None,
|
|
612
625
|
step: int = 1,
|
|
613
626
|
) -> Iterator[tuple[int, int, int]]:
|
|
627
|
+
"""
|
|
628
|
+
"""
|
|
614
629
|
if stop is None:
|
|
615
630
|
start, stop = 0, start
|
|
616
631
|
for i in range(start + step, stop, step):
|
|
@@ -624,6 +639,8 @@ def cut_iter(
|
|
|
624
639
|
stop: None | int = None,
|
|
625
640
|
step: int = 1,
|
|
626
641
|
) -> Iterator[tuple[int, int]]:
|
|
642
|
+
"""
|
|
643
|
+
"""
|
|
627
644
|
if stop is None:
|
|
628
645
|
start, stop = 0, start
|
|
629
646
|
for start in range(start + step, stop, step):
|
|
@@ -652,23 +669,25 @@ def _get_async(back: int = 2) -> bool:
|
|
|
652
669
|
@overload
|
|
653
670
|
def call_as_async[**Args, T: Coroutine](
|
|
654
671
|
func: Callable[Args, T], /,
|
|
655
|
-
may_await:
|
|
672
|
+
may_await: bool | Literal[1] = False,
|
|
656
673
|
threaded: bool = False,
|
|
657
674
|
) -> Callable[Args, T]:
|
|
658
675
|
...
|
|
659
676
|
@overload
|
|
660
677
|
def call_as_async[**Args, T](
|
|
661
678
|
func: Callable[Args, T], /,
|
|
662
|
-
may_await:
|
|
679
|
+
may_await: bool | Literal[1] = False,
|
|
663
680
|
threaded: bool = False,
|
|
664
681
|
) -> Callable[Args, Coroutine[Any, Any, T]]:
|
|
665
682
|
...
|
|
666
683
|
def call_as_async[**Args, T](
|
|
667
684
|
func: Callable[Args, T],
|
|
668
685
|
/,
|
|
669
|
-
may_await:
|
|
686
|
+
may_await: bool | Literal[1] = False,
|
|
670
687
|
threaded: bool = False,
|
|
671
688
|
) -> Callable[Args, T] | Callable[Args, Coroutine[Any, Any, T]]:
|
|
689
|
+
"""
|
|
690
|
+
"""
|
|
672
691
|
if iscoroutinefunction(func):
|
|
673
692
|
return func
|
|
674
693
|
def wraps(*args, **kwds):
|
|
@@ -681,7 +700,7 @@ def call_as_async[**Args, T](
|
|
|
681
700
|
value = await to_thread(wraps, *args, **kwds)
|
|
682
701
|
else:
|
|
683
702
|
value = wraps(*args, **kwds)
|
|
684
|
-
if may_await is
|
|
703
|
+
if may_await is 1 or may_await and isawaitable(value):
|
|
685
704
|
value = await value
|
|
686
705
|
return value
|
|
687
706
|
return wrapper
|
|
@@ -689,140 +708,131 @@ def call_as_async[**Args, T](
|
|
|
689
708
|
|
|
690
709
|
def iter_gen_step(
|
|
691
710
|
gen_step: Generator | Callable[[], Generator],
|
|
692
|
-
|
|
711
|
+
may_call: bool | Literal[1] = True,
|
|
693
712
|
):
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
713
|
+
"""
|
|
714
|
+
"""
|
|
715
|
+
if callable(gen_step):
|
|
716
|
+
gen_step = gen_step()
|
|
717
|
+
send = gen_step.send
|
|
718
|
+
throw = gen_step.throw
|
|
719
|
+
close = gen_step.close
|
|
698
720
|
value: Any = None
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
while True:
|
|
702
|
-
yield (value := send(value))
|
|
703
|
-
except StopIteration as e:
|
|
704
|
-
yield e.value
|
|
705
|
-
finally:
|
|
706
|
-
close()
|
|
707
|
-
else:
|
|
708
|
-
try:
|
|
709
|
-
while True:
|
|
710
|
-
if isinstance(value, YieldBase):
|
|
711
|
-
raise StopIteration(value)
|
|
712
|
-
try:
|
|
713
|
-
if callable(value):
|
|
714
|
-
value = value()
|
|
715
|
-
except BaseException as e:
|
|
716
|
-
value = throw(e)
|
|
717
|
-
else:
|
|
718
|
-
value = send(value)
|
|
719
|
-
yield value
|
|
720
|
-
except StopIteration as e:
|
|
721
|
-
may_call: None | bool = True
|
|
722
|
-
value = e.value
|
|
721
|
+
try:
|
|
722
|
+
while True:
|
|
723
723
|
if isinstance(value, YieldBase):
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
try:
|
|
724
|
+
raise StopIteration(value)
|
|
725
|
+
try:
|
|
726
|
+
if may_call is 1 or may_call and callable(value):
|
|
728
727
|
value = value()
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
raise Reraised(e) from e
|
|
728
|
+
except BaseException as e:
|
|
729
|
+
value = throw(e)
|
|
730
|
+
else:
|
|
731
|
+
value = send(value)
|
|
734
732
|
yield value
|
|
735
|
-
|
|
736
|
-
|
|
733
|
+
except StopIteration as e:
|
|
734
|
+
value = e.value
|
|
735
|
+
if isinstance(value, YieldBase):
|
|
736
|
+
maybe_callable = value.may_call
|
|
737
|
+
if maybe_callable is not None:
|
|
738
|
+
may_call = maybe_callable
|
|
739
|
+
value = value.value
|
|
740
|
+
if may_call is 1 or may_call and callable(value):
|
|
741
|
+
try:
|
|
742
|
+
value = value()
|
|
743
|
+
except BaseException as e:
|
|
744
|
+
try:
|
|
745
|
+
value = throw(e)
|
|
746
|
+
except BaseException as e:
|
|
747
|
+
raise Reraised(e) from e
|
|
748
|
+
yield value
|
|
749
|
+
finally:
|
|
750
|
+
close()
|
|
737
751
|
|
|
738
752
|
|
|
739
753
|
async def iter_gen_step_async(
|
|
740
754
|
gen_step: Generator | Callable[[], Generator],
|
|
755
|
+
may_await: bool | Literal[1] = True,
|
|
756
|
+
may_call: bool | Literal[1] = True,
|
|
741
757
|
threaded: bool = False,
|
|
742
|
-
simple: bool = False,
|
|
743
758
|
):
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
759
|
+
"""
|
|
760
|
+
"""
|
|
761
|
+
if callable(gen_step):
|
|
762
|
+
gen_step = gen_step()
|
|
763
|
+
send: Callable = call_as_async(gen_step.send, threaded=threaded)
|
|
764
|
+
throw: Callable = call_as_async(gen_step.throw, threaded=threaded)
|
|
765
|
+
close: Callable = call_as_async(gen_step.close, threaded=threaded)
|
|
748
766
|
value: Any = None
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
767
|
+
try:
|
|
768
|
+
while True:
|
|
769
|
+
if isinstance(value, YieldBase):
|
|
770
|
+
raise StopIteration(value)
|
|
771
|
+
try:
|
|
772
|
+
if may_call is 1 or may_call and callable(value):
|
|
773
|
+
value = await call_as_async(
|
|
774
|
+
value, may_await=may_await, threaded=threaded)()
|
|
775
|
+
elif may_await is 1 or may_await and isawaitable(value):
|
|
776
|
+
value = await value
|
|
777
|
+
except BaseException as e:
|
|
778
|
+
if isinstance(e, Reraised):
|
|
779
|
+
e = e.exception
|
|
780
|
+
value = await throw(e)
|
|
760
781
|
else:
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
782
|
+
value = await send(value)
|
|
783
|
+
yield value
|
|
784
|
+
except BaseException as e:
|
|
785
|
+
if isinstance(e, Reraised):
|
|
786
|
+
e = e.exception
|
|
787
|
+
if isinstance(e, StopIteration):
|
|
788
|
+
value = e.value
|
|
789
|
+
if isinstance(value, YieldBase):
|
|
790
|
+
maybe_awaitable = value.may_await
|
|
791
|
+
if maybe_awaitable is not None:
|
|
792
|
+
may_await = maybe_awaitable
|
|
793
|
+
maybe_callable = value.may_call
|
|
794
|
+
if maybe_callable is not None:
|
|
795
|
+
may_call = maybe_callable
|
|
796
|
+
value = value.value
|
|
797
|
+
try:
|
|
798
|
+
if may_call is 1 or may_call and callable(value):
|
|
799
|
+
value = await call_as_async(
|
|
800
|
+
value, may_await=may_await, threaded=threaded)()
|
|
801
|
+
elif may_await is 1 or may_await and isawaitable(value):
|
|
802
|
+
value = await value
|
|
803
|
+
except BaseException as e:
|
|
771
804
|
try:
|
|
772
|
-
if callable(value):
|
|
773
|
-
value = await call_as_async(
|
|
774
|
-
value, may_await=True, threaded=threaded)()
|
|
775
|
-
elif isawaitable(value):
|
|
776
|
-
value = await value
|
|
777
|
-
except BaseException as e:
|
|
778
|
-
if isinstance(e, Reraised):
|
|
779
|
-
e = e.exception
|
|
780
805
|
value = await throw(e)
|
|
781
|
-
else:
|
|
782
|
-
value = await send(value)
|
|
783
|
-
yield value
|
|
784
|
-
except BaseException as e:
|
|
785
|
-
if isinstance(e, Reraised):
|
|
786
|
-
e = e.exception
|
|
787
|
-
if isinstance(e, StopIteration):
|
|
788
|
-
may_await: None | bool = True
|
|
789
|
-
may_call: None | bool = True
|
|
790
|
-
value = e.value
|
|
791
|
-
if isinstance(value, YieldBase):
|
|
792
|
-
may_await = value.may_await
|
|
793
|
-
may_call = value.may_call
|
|
794
|
-
value = value.value
|
|
795
|
-
try:
|
|
796
|
-
if may_call is None or may_call and callable(value):
|
|
797
|
-
value = await call_as_async(
|
|
798
|
-
value, may_await=may_await, threaded=threaded)()
|
|
799
|
-
elif may_await is None or may_await and isawaitable(value):
|
|
800
|
-
value = await value
|
|
801
806
|
except BaseException as e:
|
|
802
|
-
|
|
803
|
-
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
raise
|
|
809
|
-
finally:
|
|
810
|
-
await close()
|
|
807
|
+
raise Reraised(e) from e
|
|
808
|
+
yield value
|
|
809
|
+
else:
|
|
810
|
+
raise
|
|
811
|
+
finally:
|
|
812
|
+
await close()
|
|
811
813
|
|
|
812
814
|
|
|
813
815
|
def run_gen_step(
|
|
814
816
|
gen_step: Generator | Callable[[], Generator],
|
|
815
|
-
|
|
817
|
+
may_await: bool | Literal[1] = True,
|
|
818
|
+
may_call: bool | Literal[1] = True,
|
|
816
819
|
threaded: bool = False,
|
|
817
820
|
running_flag: None | SupportsBool | Callable[[], SupportsBool] | Callable[[], Awaitable[SupportsBool]] = None,
|
|
818
821
|
*,
|
|
819
822
|
async_: None | bool = None,
|
|
820
823
|
):
|
|
824
|
+
"""
|
|
825
|
+
"""
|
|
821
826
|
if async_ is None:
|
|
822
827
|
async_ = _get_async()
|
|
823
828
|
if async_:
|
|
824
829
|
async def process():
|
|
825
|
-
gen = iter_gen_step_async(
|
|
830
|
+
gen = iter_gen_step_async(
|
|
831
|
+
gen_step,
|
|
832
|
+
may_await=may_await,
|
|
833
|
+
may_call=may_call,
|
|
834
|
+
threaded=threaded,
|
|
835
|
+
)
|
|
826
836
|
try:
|
|
827
837
|
if running_flag is None:
|
|
828
838
|
async for value in gen:
|
|
@@ -849,7 +859,7 @@ def run_gen_step(
|
|
|
849
859
|
raise
|
|
850
860
|
return process()
|
|
851
861
|
else:
|
|
852
|
-
gen = iter_gen_step(gen_step,
|
|
862
|
+
gen = iter_gen_step(gen_step, may_call=may_call)
|
|
853
863
|
try:
|
|
854
864
|
if running_flag is None:
|
|
855
865
|
for value in gen:
|
|
@@ -874,7 +884,8 @@ def run_gen_step(
|
|
|
874
884
|
@overload
|
|
875
885
|
def run_gen_step_iter(
|
|
876
886
|
gen_step: Generator | Callable[[], Generator],
|
|
877
|
-
|
|
887
|
+
may_await: bool | Literal[1] = True,
|
|
888
|
+
may_call: bool | Literal[1] = True,
|
|
878
889
|
threaded: bool = False,
|
|
879
890
|
*,
|
|
880
891
|
async_: None = None,
|
|
@@ -883,7 +894,8 @@ def run_gen_step_iter(
|
|
|
883
894
|
@overload
|
|
884
895
|
def run_gen_step_iter(
|
|
885
896
|
gen_step: Generator | Callable[[], Generator],
|
|
886
|
-
|
|
897
|
+
may_await: bool | Literal[1] = True,
|
|
898
|
+
may_call: bool | Literal[1] = True,
|
|
887
899
|
threaded: bool = False,
|
|
888
900
|
*,
|
|
889
901
|
async_: Literal[False],
|
|
@@ -892,7 +904,8 @@ def run_gen_step_iter(
|
|
|
892
904
|
@overload
|
|
893
905
|
def run_gen_step_iter(
|
|
894
906
|
gen_step: Generator | Callable[[], Generator],
|
|
895
|
-
|
|
907
|
+
may_await: bool | Literal[1] = True,
|
|
908
|
+
may_call: bool | Literal[1] = True,
|
|
896
909
|
threaded: bool = False,
|
|
897
910
|
*,
|
|
898
911
|
async_: Literal[True],
|
|
@@ -900,34 +913,43 @@ def run_gen_step_iter(
|
|
|
900
913
|
...
|
|
901
914
|
def run_gen_step_iter(
|
|
902
915
|
gen_step: Generator | Callable[[], Generator],
|
|
903
|
-
|
|
916
|
+
may_await: bool | Literal[1] = True,
|
|
917
|
+
may_call: bool | Literal[1] = True,
|
|
904
918
|
threaded: bool = False,
|
|
905
919
|
*,
|
|
906
920
|
async_: None | bool = None,
|
|
907
921
|
) -> Iterator | AsyncIterator:
|
|
922
|
+
"""
|
|
923
|
+
"""
|
|
908
924
|
if async_ is None:
|
|
909
925
|
async_ = _get_async()
|
|
910
926
|
gen = gen_step() if callable(gen_step) else gen_step
|
|
911
927
|
send: Callable = gen.send
|
|
912
928
|
throw: Callable = gen.throw
|
|
913
929
|
close: Callable = gen.close
|
|
930
|
+
default_may_await = may_await
|
|
931
|
+
default_may_call = may_call
|
|
914
932
|
if async_:
|
|
915
933
|
send = call_as_async(send, threaded=threaded)
|
|
916
934
|
throw = call_as_async(throw, threaded=threaded)
|
|
917
935
|
close = call_as_async(close, threaded=threaded)
|
|
918
936
|
async def aextract(value, /):
|
|
919
|
-
may_await: None | bool = None if simple else False
|
|
920
|
-
may_call: None | bool = not simple
|
|
921
937
|
yield_type = -1
|
|
938
|
+
may_await = default_may_await
|
|
939
|
+
may_call = default_may_call
|
|
922
940
|
if isinstance(value, YieldBase):
|
|
923
|
-
yield_type
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
941
|
+
yield_type = value.yield_type
|
|
942
|
+
maybe_awaitable = value.may_await
|
|
943
|
+
if maybe_awaitable is not None:
|
|
944
|
+
may_await = maybe_awaitable
|
|
945
|
+
maybe_callable = value.may_call
|
|
946
|
+
if maybe_callable is not None:
|
|
947
|
+
may_call = maybe_callable
|
|
948
|
+
value = value.value
|
|
949
|
+
if may_call is 1 or may_call and callable(value):
|
|
928
950
|
value = await call_as_async(
|
|
929
951
|
value, may_await=may_await, threaded=threaded)()
|
|
930
|
-
elif may_await is
|
|
952
|
+
elif may_await is 1 or may_await and isawaitable(value):
|
|
931
953
|
value = await value
|
|
932
954
|
return yield_type, value
|
|
933
955
|
async def aprocess():
|
|
@@ -973,13 +995,15 @@ def run_gen_step_iter(
|
|
|
973
995
|
return aprocess()
|
|
974
996
|
else:
|
|
975
997
|
def extract(value, /):
|
|
976
|
-
may_call: None | bool = not simple
|
|
977
998
|
yield_type = -1
|
|
999
|
+
may_call = default_may_call
|
|
978
1000
|
if isinstance(value, YieldBase):
|
|
979
1001
|
yield_type = value.yield_type
|
|
980
|
-
|
|
1002
|
+
maybe_callable = value.may_call
|
|
1003
|
+
if maybe_callable is not None:
|
|
1004
|
+
may_call = maybe_callable
|
|
981
1005
|
value = value.value
|
|
982
|
-
if may_call is
|
|
1006
|
+
if may_call is 1 or may_call and callable(value):
|
|
983
1007
|
value = value()
|
|
984
1008
|
return yield_type, value
|
|
985
1009
|
def process():
|
|
@@ -1021,7 +1045,8 @@ def as_gen_step(
|
|
|
1021
1045
|
func: Callable,
|
|
1022
1046
|
/,
|
|
1023
1047
|
iter: bool = False,
|
|
1024
|
-
|
|
1048
|
+
may_await: bool | Literal[1] = True,
|
|
1049
|
+
may_call: bool | Literal[1] = True,
|
|
1025
1050
|
threaded: bool = False,
|
|
1026
1051
|
running_flag: None | SupportsBool | Callable[[], SupportsBool] | Callable[[], Awaitable[SupportsBool]] = None,
|
|
1027
1052
|
*,
|
|
@@ -1033,14 +1058,16 @@ def as_gen_step(
|
|
|
1033
1058
|
if iter:
|
|
1034
1059
|
return run_gen_step_iter(
|
|
1035
1060
|
func(*args, **kwds),
|
|
1036
|
-
|
|
1061
|
+
may_await=may_await,
|
|
1062
|
+
may_call=may_call,
|
|
1037
1063
|
threaded=threaded,
|
|
1038
1064
|
async_=async_, # type: ignore
|
|
1039
1065
|
)
|
|
1040
1066
|
else:
|
|
1041
1067
|
return run_gen_step(
|
|
1042
1068
|
func(*args, **kwds),
|
|
1043
|
-
|
|
1069
|
+
may_await=may_await,
|
|
1070
|
+
may_call=may_call,
|
|
1044
1071
|
threaded=threaded,
|
|
1045
1072
|
running_flag=running_flag,
|
|
1046
1073
|
async_=async_,
|
|
@@ -1117,6 +1144,8 @@ def with_iter_next[T](
|
|
|
1117
1144
|
/,
|
|
1118
1145
|
async_: Literal[False, True] = False,
|
|
1119
1146
|
):
|
|
1147
|
+
"""
|
|
1148
|
+
"""
|
|
1120
1149
|
if async_:
|
|
1121
1150
|
get_next: Callable[[], T] | Callable[[], Awaitable[T]] = ensure_aiter(iterable).__anext__
|
|
1122
1151
|
elif isinstance(iterable, Iterable):
|
|
@@ -1155,6 +1184,8 @@ def context[T](
|
|
|
1155
1184
|
*ctxs: ContextManager | AsyncContextManager,
|
|
1156
1185
|
async_: Literal[False, True] = False,
|
|
1157
1186
|
) -> T | Coroutine[Any, Any, T]:
|
|
1187
|
+
"""
|
|
1188
|
+
"""
|
|
1158
1189
|
if async_:
|
|
1159
1190
|
async def call():
|
|
1160
1191
|
args: list = []
|
|
@@ -1203,6 +1234,8 @@ def backgroud_loop(
|
|
|
1203
1234
|
*,
|
|
1204
1235
|
async_: Literal[False, True] = False,
|
|
1205
1236
|
) -> ContextManager | AsyncContextManager:
|
|
1237
|
+
"""
|
|
1238
|
+
"""
|
|
1206
1239
|
use_default_call = not callable(call)
|
|
1207
1240
|
if use_default_call:
|
|
1208
1241
|
start = time()
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
2
|
+
iterutils/__init__.py,sha256=_veJbrFYJld_cVSYbBnR37dSbGi2aSDAkNmLUEvuiXE,37134
|
|
3
|
+
iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
python_iterutils-0.2.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
5
|
+
python_iterutils-0.2.1.dist-info/METADATA,sha256=C55LpIsT807qqeehnsAZ7ZS-za5Gb03eltgrdYiN5vM,1467
|
|
6
|
+
python_iterutils-0.2.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
7
|
+
python_iterutils-0.2.1.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
1
|
-
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
2
|
-
iterutils/__init__.py,sha256=LEkMyVkA2qLrVtJDuTXgUz0cUSexnjyEcJ0skHehf4M,38403
|
|
3
|
-
iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
python_iterutils-0.2.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
5
|
-
python_iterutils-0.2.dist-info/METADATA,sha256=EYmtSSWyFbN7QMzuv79s2UKsPoJ3fNvr_SmLsL8SnlE,1465
|
|
6
|
-
python_iterutils-0.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
7
|
-
python_iterutils-0.2.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|