python-iterutils 0.0.4.4__tar.gz → 0.0.5__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-iterutils
3
- Version: 0.0.4.4
3
+ Version: 0.0.5
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
@@ -2,10 +2,11 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 0, 4)
5
+ __version__ = (0, 0, 5)
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
 
11
12
  from asyncio import to_thread
@@ -13,7 +14,7 @@ from collections.abc import (
13
14
  AsyncIterable, AsyncIterator, Awaitable, Callable, Generator, Iterable, Iterator,
14
15
  )
15
16
  from inspect import isawaitable
16
- from typing import Any, TypeVar
17
+ from typing import overload, Any, Literal, TypeVar
17
18
 
18
19
  from asynctools import async_zip, ensure_async, ensure_aiter
19
20
 
@@ -21,6 +22,18 @@ from asynctools import async_zip, ensure_async, ensure_aiter
21
22
  T = TypeVar("T")
22
23
 
23
24
 
25
+ class Yield:
26
+
27
+ def __init__(self, value, /):
28
+ self.value = value
29
+
30
+
31
+ class YieldFrom:
32
+
33
+ def __init__(self, value, /):
34
+ self.value = value
35
+
36
+
24
37
  def iterable(it, /) -> bool:
25
38
  try:
26
39
  return isinstance(iter(it), Iterable)
@@ -168,7 +181,7 @@ def cut_iter(
168
181
 
169
182
 
170
183
  def run_gen_step(
171
- gen_step: Generator[Callable, Any, T] | Callable[[], Generator[Callable, Any, T]],
184
+ gen_step: Generator[Any, Any, T] | Callable[[], Generator[Any, Any, T]],
172
185
  *,
173
186
  async_: bool = False,
174
187
  threaded: bool = False,
@@ -191,9 +204,14 @@ def run_gen_step(
191
204
  func = send(None)
192
205
  while True:
193
206
  try:
194
- ret = func()
195
- if isawaitable(ret):
196
- ret = await ret
207
+ if isawaitable(func):
208
+ ret = await func
209
+ elif callable(func):
210
+ ret = func()
211
+ if isawaitable(ret):
212
+ ret = await ret
213
+ else:
214
+ ret = func
197
215
  except BaseException as e:
198
216
  if threaded:
199
217
  func = await to_thread(throw, e)
@@ -233,7 +251,7 @@ def run_gen_step(
233
251
  func = send(None)
234
252
  while True:
235
253
  try:
236
- ret = func()
254
+ ret = func() if callable(func) else func
237
255
  except BaseException as e:
238
256
  func = throw(e)
239
257
  else:
@@ -247,3 +265,112 @@ def run_gen_step(
247
265
  if close is not None:
248
266
  close()
249
267
 
268
+
269
+ @overload
270
+ def run_gen_step_iter(
271
+ gen_step: Generator | Callable[[], Generator],
272
+ threaded: bool = False,
273
+ *,
274
+ async_: Literal[False] = False,
275
+ ) -> Iterator:
276
+ ...
277
+ @overload
278
+ def run_gen_step_iter(
279
+ gen_step: Generator | Callable[[], Generator],
280
+ threaded: bool = False,
281
+ *,
282
+ async_: Literal[True],
283
+ ) -> AsyncIterator:
284
+ ...
285
+ def run_gen_step_iter(
286
+ gen_step: Generator | Callable[[], Generator],
287
+ threaded: bool = False,
288
+ *,
289
+ async_: bool = False,
290
+ ) -> Iterator | AsyncIterator:
291
+ if callable(gen_step):
292
+ gen = gen_step()
293
+ close = gen.close
294
+ else:
295
+ gen = gen_step
296
+ close = None
297
+ send = gen.send
298
+ throw = gen.throw
299
+ if async_:
300
+ async def process():
301
+ try:
302
+ if threaded:
303
+ func = await to_thread(send, None)
304
+ else:
305
+ func = send(None)
306
+ 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
+ try:
315
+ if isawaitable(func):
316
+ ret = await func
317
+ elif callable(func):
318
+ ret = func()
319
+ if isawaitable(ret):
320
+ ret = await ret
321
+ else:
322
+ ret = func
323
+ except BaseException as e:
324
+ if threaded:
325
+ func = await to_thread(throw, e)
326
+ else:
327
+ func = throw(e)
328
+ else:
329
+ if yield_type == 1:
330
+ yield ret
331
+ elif yield_type == 2:
332
+ async for val in ensure_aiter(ret, threaded=threaded):
333
+ 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
+ finally:
341
+ if close is not None:
342
+ if threaded:
343
+ await to_thread(close)
344
+ else:
345
+ close()
346
+ else:
347
+ def process():
348
+ try:
349
+ func = send(None)
350
+ 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
+ try:
359
+ ret = func() if callable(func) else func
360
+ except BaseException as e:
361
+ func = throw(e)
362
+ else:
363
+ if yield_type == 1:
364
+ yield ret
365
+ elif yield_type == 2:
366
+ yield from ret
367
+ func = send(ret)
368
+ except StopIteration as e:
369
+ return e.value
370
+ except GeneratorExit:
371
+ pass
372
+ finally:
373
+ if close is not None:
374
+ close()
375
+ return process()
376
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-iterutils"
3
- version = "0.0.4.4"
3
+ version = "0.0.5"
4
4
  description = "Python another itertools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"