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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-iterutils
3
- Version: 0.0.5
3
+ Version: 0.0.7
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,19 +2,20 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 0, 5)
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 Yield:
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
- def __init__(self, value, /):
34
- self.value = value
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(func: Callable, iterable, /, *iterables):
60
+ def foreach(ret: Callable, iterable, /, *iterables):
52
61
  if iterables:
53
62
  for args in zip(iterable, *iterables):
54
- func(*args)
63
+ ret(*args)
55
64
  else:
56
65
  for arg in iterable:
57
- func(arg)
66
+ ret(arg)
58
67
 
59
68
 
60
- async def async_foreach(func: Callable, iterable, /, *iterables, threaded: bool = True):
61
- func = ensure_async(func, threaded=threaded)
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 func(*args)
73
+ await ret(*args)
65
74
  else:
66
75
  async for arg in ensure_aiter(iterable, threaded=threaded):
67
- await func(arg)
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
- func = await to_thread(send, None)
211
+ ret = await to_thread(send, None)
203
212
  else:
204
- func = send(None)
213
+ ret = send(None)
205
214
  while True:
206
215
  try:
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
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
- func = await to_thread(throw, e)
222
+ ret = await to_thread(throw, e)
218
223
  else:
219
- func = throw(e)
224
+ ret = throw(e)
220
225
  else:
221
226
  if threaded:
222
- func = await to_thread(send, ret)
227
+ ret = await to_thread(send, ret)
223
228
  else:
224
- func = send(ret)
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
- func = send(None)
256
+ ret = send(None)
252
257
  while True:
253
258
  try:
254
- ret = func() if callable(func) else func
259
+ if callable(ret):
260
+ ret = ret()
255
261
  except BaseException as e:
256
- func = throw(e)
262
+ ret = throw(e)
257
263
  else:
258
- func = send(ret)
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
- func = await to_thread(send, None)
322
+ ret = await to_thread(send, None)
304
323
  else:
305
- func = send(None)
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
- 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
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
- func = await to_thread(throw, e)
336
+ ret = await to_thread(throw, e)
326
337
  else:
327
- func = throw(e)
338
+ ret = throw(e)
328
339
  else:
329
- if yield_type == 1:
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
- elif yield_type == 2:
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
- func = send(None)
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 = func() if callable(func) else func
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
- func = throw(e)
383
+ ret = throw(e)
362
384
  else:
363
- if yield_type == 1:
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
- elif yield_type == 2:
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()
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-iterutils"
3
- version = "0.0.5"
3
+ version = "0.0.7"
4
4
  description = "Python another itertools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"