python-iterutils 0.0.8__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 +288 -137
- {python_iterutils-0.0.8.dist-info → python_iterutils-0.1.0.dist-info}/METADATA +4 -5
- python_iterutils-0.1.0.dist-info/RECORD +7 -0
- {python_iterutils-0.0.8.dist-info → python_iterutils-0.1.0.dist-info}/WHEEL +1 -1
- python_iterutils-0.0.8.dist-info/RECORD +0 -7
- {python_iterutils-0.0.8.dist-info → python_iterutils-0.1.0.dist-info}/LICENSE +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
|
-
"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)
|
|
@@ -36,6 +36,10 @@ class YieldBase(ABC):
|
|
|
36
36
|
...
|
|
37
37
|
|
|
38
38
|
|
|
39
|
+
class Return(YieldBase):
|
|
40
|
+
yield_type = 0
|
|
41
|
+
|
|
42
|
+
|
|
39
43
|
class Yield(YieldBase):
|
|
40
44
|
yield_type = 1
|
|
41
45
|
|
|
@@ -44,105 +48,234 @@ class YieldFrom(YieldBase):
|
|
|
44
48
|
yield_type = 2
|
|
45
49
|
|
|
46
50
|
|
|
47
|
-
def iterable(
|
|
51
|
+
def iterable(iterable, /) -> bool:
|
|
48
52
|
try:
|
|
49
|
-
return isinstance(iter(
|
|
53
|
+
return isinstance(iter(iterable), Iterable)
|
|
50
54
|
except TypeError:
|
|
51
55
|
return False
|
|
52
56
|
|
|
53
57
|
|
|
54
|
-
def async_iterable(
|
|
58
|
+
def async_iterable(iterable, /) -> bool:
|
|
55
59
|
try:
|
|
56
|
-
return isinstance(iter(
|
|
60
|
+
return isinstance(iter(iterable), AsyncIterable)
|
|
57
61
|
except TypeError:
|
|
58
62
|
return False
|
|
59
63
|
|
|
60
64
|
|
|
61
|
-
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)
|
|
62
73
|
if iterables:
|
|
63
74
|
for args in zip(iterable, *iterables):
|
|
64
|
-
|
|
75
|
+
value(*args)
|
|
65
76
|
else:
|
|
66
77
|
for arg in iterable:
|
|
67
|
-
|
|
78
|
+
value(arg)
|
|
68
79
|
|
|
69
80
|
|
|
70
|
-
async def async_foreach(
|
|
71
|
-
|
|
81
|
+
async def async_foreach(
|
|
82
|
+
value: Callable,
|
|
83
|
+
iterable: Iterable | AsyncIterable,
|
|
84
|
+
/,
|
|
85
|
+
*iterables: Iterable | AsyncIterable,
|
|
86
|
+
threaded: bool = True,
|
|
87
|
+
):
|
|
88
|
+
value = ensure_async(value, threaded=threaded)
|
|
72
89
|
if iterables:
|
|
73
90
|
async for args in async_zip(iterable, *iterables, threaded=threaded):
|
|
74
|
-
await
|
|
91
|
+
await value(*args)
|
|
75
92
|
else:
|
|
76
93
|
async for arg in ensure_aiter(iterable, threaded=threaded):
|
|
77
|
-
await
|
|
94
|
+
await value(arg)
|
|
78
95
|
|
|
79
96
|
|
|
80
|
-
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)
|
|
81
104
|
if take_while is None:
|
|
82
|
-
for _ in
|
|
105
|
+
for _ in iterable:
|
|
83
106
|
pass
|
|
84
107
|
else:
|
|
85
|
-
for v in map(take_while,
|
|
108
|
+
for v in map(take_while, iterable):
|
|
86
109
|
if not v:
|
|
87
110
|
break
|
|
88
111
|
|
|
89
112
|
|
|
90
113
|
async def async_through(
|
|
91
|
-
|
|
114
|
+
iterable: Iterable | AsyncIterable,
|
|
92
115
|
/,
|
|
93
116
|
take_while: None | Callable = None,
|
|
94
117
|
threaded: bool = True,
|
|
95
118
|
):
|
|
96
|
-
|
|
119
|
+
iterable = ensure_aiter(iterable, threaded=threaded)
|
|
97
120
|
if take_while is None:
|
|
98
|
-
async for _ in
|
|
121
|
+
async for _ in iterable:
|
|
99
122
|
pass
|
|
123
|
+
elif take_while is bool:
|
|
124
|
+
async for v in iterable:
|
|
125
|
+
if not v:
|
|
126
|
+
break
|
|
100
127
|
else:
|
|
101
|
-
async for v in async_map(take_while,
|
|
128
|
+
async for v in async_map(take_while, iterable):
|
|
102
129
|
if not v:
|
|
103
130
|
break
|
|
104
131
|
|
|
105
132
|
|
|
106
|
-
|
|
107
|
-
|
|
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],
|
|
108
211
|
/,
|
|
109
212
|
callprev: None | Callable[[T], Any] = None,
|
|
110
213
|
callnext: None | Callable[[T], Any] = None,
|
|
111
214
|
callenter: None | Callable[[Iterable[T]], Any] = None,
|
|
112
215
|
callexit: None | Callable[[Iterable[T], None | BaseException], Any] = None,
|
|
113
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
|
+
)
|
|
114
245
|
if not callable(callprev):
|
|
115
246
|
callprev = None
|
|
116
247
|
if not callable(callnext):
|
|
117
248
|
callnext = None
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
callenter
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
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:
|
|
136
270
|
raise
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
callexit(it, None)
|
|
271
|
+
finally:
|
|
272
|
+
if callable(callexit):
|
|
273
|
+
callexit(iterable, None)
|
|
274
|
+
return gen()
|
|
142
275
|
|
|
143
276
|
|
|
144
|
-
async def wrap_aiter(
|
|
145
|
-
|
|
277
|
+
async def wrap_aiter[T](
|
|
278
|
+
iterable: Iterable[T] | AsyncIterable[T],
|
|
146
279
|
/,
|
|
147
280
|
callprev: None | Callable[[T], Any] = None,
|
|
148
281
|
callnext: None | Callable[[T], Any] = None,
|
|
@@ -153,7 +286,7 @@ async def wrap_aiter(
|
|
|
153
286
|
callprev = ensure_async(callprev, threaded=threaded) if callable(callprev) else None
|
|
154
287
|
callnext = ensure_async(callnext, threaded=threaded) if callable(callnext) else None
|
|
155
288
|
try:
|
|
156
|
-
async for e in ensure_aiter(
|
|
289
|
+
async for e in ensure_aiter(iterable, threaded=threaded):
|
|
157
290
|
if callprev:
|
|
158
291
|
try:
|
|
159
292
|
await callprev(e)
|
|
@@ -167,13 +300,13 @@ async def wrap_aiter(
|
|
|
167
300
|
break
|
|
168
301
|
except BaseException as e:
|
|
169
302
|
if callable(callexit):
|
|
170
|
-
if not await ensure_async(callexit, threaded=threaded)(
|
|
303
|
+
if not await ensure_async(callexit, threaded=threaded)(iterable, e):
|
|
171
304
|
raise
|
|
172
305
|
else:
|
|
173
306
|
raise
|
|
174
307
|
finally:
|
|
175
308
|
if callable(callexit):
|
|
176
|
-
await ensure_async(callexit, threaded=threaded)(
|
|
309
|
+
await ensure_async(callexit, threaded=threaded)(iterable, None)
|
|
177
310
|
|
|
178
311
|
|
|
179
312
|
def acc_step(
|
|
@@ -202,7 +335,7 @@ def cut_iter(
|
|
|
202
335
|
yield stop, stop - start
|
|
203
336
|
|
|
204
337
|
|
|
205
|
-
def run_gen_step(
|
|
338
|
+
def run_gen_step[T](
|
|
206
339
|
gen_step: Generator[Any, Any, T] | Callable[[], Generator[Any, Any, T]],
|
|
207
340
|
*,
|
|
208
341
|
async_: bool = False,
|
|
@@ -221,27 +354,40 @@ def run_gen_step(
|
|
|
221
354
|
async def process():
|
|
222
355
|
try:
|
|
223
356
|
if threaded:
|
|
224
|
-
|
|
357
|
+
value = await to_thread(send, None)
|
|
225
358
|
else:
|
|
226
|
-
|
|
359
|
+
value = send(None)
|
|
227
360
|
while True:
|
|
361
|
+
if isinstance(value, YieldBase):
|
|
362
|
+
raise StopIteration(value)
|
|
228
363
|
try:
|
|
229
|
-
if callable(
|
|
230
|
-
|
|
231
|
-
if isawaitable(
|
|
232
|
-
|
|
364
|
+
if callable(value):
|
|
365
|
+
value = value()
|
|
366
|
+
if isawaitable(value):
|
|
367
|
+
value = await value
|
|
233
368
|
except BaseException as e:
|
|
234
369
|
if threaded:
|
|
235
|
-
|
|
370
|
+
value = await to_thread(throw, e)
|
|
236
371
|
else:
|
|
237
|
-
|
|
372
|
+
value = throw(e)
|
|
238
373
|
else:
|
|
239
374
|
if threaded:
|
|
240
|
-
|
|
375
|
+
value = await to_thread(send, value)
|
|
241
376
|
else:
|
|
242
|
-
|
|
377
|
+
value = send(value)
|
|
243
378
|
except StopIteration as e:
|
|
244
|
-
|
|
379
|
+
value = e.value
|
|
380
|
+
identity = False
|
|
381
|
+
try_call_me = True
|
|
382
|
+
if isinstance(value, YieldBase):
|
|
383
|
+
identity = value.identity
|
|
384
|
+
try_call_me = value.try_call_me
|
|
385
|
+
value = value.value
|
|
386
|
+
if callable(value) and try_call_me:
|
|
387
|
+
value = value()
|
|
388
|
+
if not identity and isawaitable(value):
|
|
389
|
+
value = await value
|
|
390
|
+
return value
|
|
245
391
|
finally:
|
|
246
392
|
if close is not None:
|
|
247
393
|
if threaded:
|
|
@@ -251,35 +397,43 @@ def run_gen_step(
|
|
|
251
397
|
result = process()
|
|
252
398
|
if as_iter:
|
|
253
399
|
async def wrap(result):
|
|
254
|
-
|
|
400
|
+
iterable = await result
|
|
255
401
|
try:
|
|
256
|
-
|
|
402
|
+
iterable = aiter(iterable)
|
|
257
403
|
except TypeError:
|
|
258
|
-
for val in iter(
|
|
404
|
+
for val in iter(iterable):
|
|
259
405
|
if isawaitable(val):
|
|
260
406
|
val = await val
|
|
261
407
|
yield val
|
|
262
408
|
else:
|
|
263
|
-
async for val in
|
|
409
|
+
async for val in iterable:
|
|
264
410
|
yield val
|
|
265
411
|
result = wrap(result)
|
|
266
412
|
return result
|
|
267
413
|
else:
|
|
268
414
|
try:
|
|
269
|
-
|
|
415
|
+
value = send(None)
|
|
270
416
|
while True:
|
|
417
|
+
if isinstance(value, YieldBase):
|
|
418
|
+
raise StopIteration(value)
|
|
271
419
|
try:
|
|
272
|
-
if callable(
|
|
273
|
-
|
|
420
|
+
if callable(value):
|
|
421
|
+
value = value()
|
|
274
422
|
except BaseException as e:
|
|
275
|
-
|
|
423
|
+
value = throw(e)
|
|
276
424
|
else:
|
|
277
|
-
|
|
425
|
+
value = send(value)
|
|
278
426
|
except StopIteration as e:
|
|
279
|
-
|
|
427
|
+
value = e.value
|
|
428
|
+
try_call_me = True
|
|
429
|
+
if isinstance(value, YieldBase):
|
|
430
|
+
try_call_me = value.try_call_me
|
|
431
|
+
value = value.value
|
|
432
|
+
if callable(value) and try_call_me:
|
|
433
|
+
value = value()
|
|
280
434
|
if as_iter:
|
|
281
|
-
|
|
282
|
-
return
|
|
435
|
+
value = iter(value)
|
|
436
|
+
return value
|
|
283
437
|
finally:
|
|
284
438
|
if close is not None:
|
|
285
439
|
close()
|
|
@@ -317,55 +471,52 @@ def run_gen_step_iter(
|
|
|
317
471
|
throw = gen.throw
|
|
318
472
|
if async_:
|
|
319
473
|
async def process():
|
|
320
|
-
async def extract(
|
|
321
|
-
yield_type = 0
|
|
474
|
+
async def extract(value):
|
|
322
475
|
identity = False
|
|
323
476
|
try_call_me = True
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
return yield_type,
|
|
477
|
+
yield_type = -1
|
|
478
|
+
if isinstance(value, YieldBase):
|
|
479
|
+
identity = value.identity
|
|
480
|
+
try_call_me = value.try_call_me
|
|
481
|
+
yield_type = value.yield_type
|
|
482
|
+
value = value.value
|
|
483
|
+
if try_call_me and callable(value):
|
|
484
|
+
value = value()
|
|
485
|
+
if not identity and isawaitable(value):
|
|
486
|
+
value = await value
|
|
487
|
+
return yield_type, value
|
|
335
488
|
try:
|
|
336
489
|
if threaded:
|
|
337
|
-
|
|
490
|
+
value = await to_thread(send, None)
|
|
338
491
|
else:
|
|
339
|
-
|
|
492
|
+
value = send(None)
|
|
340
493
|
while True:
|
|
341
494
|
try:
|
|
342
|
-
yield_type,
|
|
495
|
+
yield_type, value = await extract(value)
|
|
343
496
|
match yield_type:
|
|
344
497
|
case 1:
|
|
345
|
-
yield
|
|
498
|
+
yield value
|
|
346
499
|
case 2:
|
|
347
|
-
async for val in ensure_aiter(
|
|
500
|
+
async for val in ensure_aiter(value, threaded=threaded):
|
|
348
501
|
yield val
|
|
349
502
|
except BaseException as e:
|
|
350
503
|
if threaded:
|
|
351
|
-
|
|
504
|
+
value = await to_thread(throw, e)
|
|
352
505
|
else:
|
|
353
|
-
|
|
506
|
+
value = throw(e)
|
|
354
507
|
else:
|
|
355
508
|
if threaded:
|
|
356
|
-
|
|
509
|
+
value = await to_thread(send, value)
|
|
357
510
|
else:
|
|
358
|
-
|
|
511
|
+
value = send(value)
|
|
359
512
|
except StopIteration as e:
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
async for val in ensure_aiter(ret, threaded=threaded):
|
|
368
|
-
yield val
|
|
513
|
+
yield_type, value = await extract(e.value)
|
|
514
|
+
match yield_type:
|
|
515
|
+
case 1:
|
|
516
|
+
yield value
|
|
517
|
+
case 2:
|
|
518
|
+
async for val in ensure_aiter(value, threaded=threaded):
|
|
519
|
+
yield val
|
|
369
520
|
finally:
|
|
370
521
|
if close is not None:
|
|
371
522
|
if threaded:
|
|
@@ -374,41 +525,41 @@ def run_gen_step_iter(
|
|
|
374
525
|
close()
|
|
375
526
|
else:
|
|
376
527
|
def process():
|
|
377
|
-
def extract(
|
|
378
|
-
yield_type = 0
|
|
379
|
-
identity = False
|
|
528
|
+
def extract(value, /):
|
|
380
529
|
try_call_me = True
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
try_call_me =
|
|
384
|
-
yield_type
|
|
385
|
-
|
|
386
|
-
if
|
|
387
|
-
|
|
388
|
-
return yield_type,
|
|
530
|
+
yield_type = -1
|
|
531
|
+
if isinstance(value, YieldBase):
|
|
532
|
+
try_call_me = value.try_call_me
|
|
533
|
+
yield_type = value.yield_type
|
|
534
|
+
value = value.value
|
|
535
|
+
if try_call_me and callable(value):
|
|
536
|
+
value = value()
|
|
537
|
+
return yield_type, value
|
|
389
538
|
try:
|
|
390
|
-
|
|
539
|
+
value = send(None)
|
|
391
540
|
while True:
|
|
392
541
|
try:
|
|
393
|
-
yield_type,
|
|
542
|
+
yield_type, value = extract(value)
|
|
394
543
|
match yield_type:
|
|
544
|
+
case 0:
|
|
545
|
+
return value
|
|
395
546
|
case 1:
|
|
396
|
-
yield
|
|
547
|
+
yield value
|
|
397
548
|
case 2:
|
|
398
|
-
yield from
|
|
549
|
+
yield from value
|
|
399
550
|
except BaseException as e:
|
|
400
|
-
|
|
551
|
+
value = throw(e)
|
|
401
552
|
else:
|
|
402
|
-
|
|
553
|
+
value = send(value)
|
|
403
554
|
except StopIteration as e:
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
555
|
+
yield_type, value = extract(e.value)
|
|
556
|
+
match yield_type:
|
|
557
|
+
case 1:
|
|
558
|
+
yield value
|
|
559
|
+
case 2:
|
|
560
|
+
yield from value
|
|
561
|
+
case _:
|
|
562
|
+
return value
|
|
412
563
|
finally:
|
|
413
564
|
if close is not None:
|
|
414
565
|
close()
|
|
@@ -1,27 +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
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
20
19
|
Classifier: Programming Language :: Python :: 3 :: Only
|
|
21
20
|
Classifier: Topic :: Software Development
|
|
22
21
|
Classifier: Topic :: Software Development :: Libraries
|
|
23
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
24
|
-
Requires-Dist: python-asynctools
|
|
23
|
+
Requires-Dist: python-asynctools (>=0.0.9)
|
|
25
24
|
Project-URL: Repository, https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-iterutils
|
|
26
25
|
Description-Content-Type: text/markdown
|
|
27
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=rwD7tD31XxBl85Yo2pONeJoOng3aqYySh-I6CzEPILA,12467
|
|
3
|
-
iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
-
python_iterutils-0.0.8.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
5
|
-
python_iterutils-0.0.8.dist-info/METADATA,sha256=3BSfEd9eF0b_zmgOE_pCEO6BNQeIRRv9X1UgGBUADSY,1382
|
|
6
|
-
python_iterutils-0.0.8.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
|
|
7
|
-
python_iterutils-0.0.8.dist-info/RECORD,,
|
|
File without changes
|