python-iterutils 0.0.1__py3-none-any.whl → 0.0.2.2__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 CHANGED
@@ -2,16 +2,19 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 0, 1)
6
- __all__ = ["iterable", "async_iterable", "acc_step", "cut_iter", "asyncify_iter"]
5
+ __version__ = (0, 0, 2)
6
+ __all__ = [
7
+ "iterable", "async_iterable", "foreach", "async_foreach", "through", "async_through",
8
+ "wrap_iter", "wrap_aiter", "acc_step", "cut_iter",
9
+ ]
7
10
 
8
- from asyncio import to_thread
9
- from collections.abc import AsyncGenerator, AsyncIterable, Generator, Iterable, Iterator
10
- from typing import overload, Any, Optional, TypeVar
11
+ from collections.abc import AsyncIterable, AsyncIterator, Callable, Iterable, Iterator
12
+ from typing import Any, TypeVar
11
13
 
14
+ from asynctools import async_zip, ensure_async, ensure_aiter
12
15
 
13
- TI = TypeVar("TI")
14
- TO = TypeVar("TO")
16
+
17
+ T = TypeVar("T")
15
18
 
16
19
 
17
20
  def iterable(it, /) -> bool:
@@ -28,9 +31,77 @@ def async_iterable(it, /) -> bool:
28
31
  return False
29
32
 
30
33
 
34
+ def foreach(func: Callable, iterable, /, *iterables):
35
+ if iterables:
36
+ for args in zip(iterable, *iterables):
37
+ func(*args)
38
+ else:
39
+ for arg in iterable:
40
+ func(arg)
41
+
42
+
43
+ async def async_foreach(func: Callable, iterable, /, *iterables, threaded: bool = True):
44
+ func = ensure_async(func, threaded=threaded)
45
+ if iterables:
46
+ async for args in async_zip(iterable, *iterables, threaded=threaded):
47
+ await func(*args)
48
+ else:
49
+ async for arg in ensure_aiter(iterable, threaded=threaded):
50
+ await func(arg)
51
+
52
+
53
+ def through(it: Iterable, /):
54
+ for _ in it:
55
+ pass
56
+
57
+
58
+ async def async_through(
59
+ it: Iterable | AsyncIterable,
60
+ /,
61
+ threaded: bool = True,
62
+ ):
63
+ async for _ in ensure_aiter(it, threaded=threaded):
64
+ pass
65
+
66
+
67
+ def wrap_iter(
68
+ it: Iterable[T],
69
+ /,
70
+ callprev: None | Callable[[T], Any] = None,
71
+ callnext: None | Callable[[T], Any] = None,
72
+ ) -> Iterator[T]:
73
+ if not callable(callprev):
74
+ callprev = None
75
+ if not callable(callnext):
76
+ callnext = None
77
+ for e in it:
78
+ if callprev:
79
+ callprev(e)
80
+ yield e
81
+ if callnext:
82
+ callnext(e)
83
+
84
+
85
+ async def wrap_aiter(
86
+ it: Iterable[T] | AsyncIterable[T],
87
+ /,
88
+ callprev: None | Callable[[T], Any] = None,
89
+ callnext: None | Callable[[T], Any] = None,
90
+ threaded: bool = True,
91
+ ) -> AsyncIterator[T]:
92
+ callprev = ensure_async(callprev) if callable(callprev) else None
93
+ callnext = ensure_async(callnext) if callable(callnext) else None
94
+ async for e in ensure_aiter(it, threaded=threaded):
95
+ if callprev:
96
+ await callprev(e)
97
+ yield e
98
+ if callnext:
99
+ await callnext(e)
100
+
101
+
31
102
  def acc_step(
32
103
  start: int,
33
- stop: Optional[int] = None,
104
+ stop: None | int = None,
34
105
  step: int = 1,
35
106
  ) -> Iterator[tuple[int, int, int]]:
36
107
  if stop is None:
@@ -43,7 +114,7 @@ def acc_step(
43
114
 
44
115
  def cut_iter(
45
116
  start: int,
46
- stop: Optional[int] = None,
117
+ stop: None | int = None,
47
118
  step: int = 1,
48
119
  ) -> Iterator[tuple[int, int]]:
49
120
  if stop is None:
@@ -53,57 +124,3 @@ def cut_iter(
53
124
  if start != stop:
54
125
  yield stop, stop - start
55
126
 
56
-
57
- @overload
58
- async def _asyncify_iter(it: Generator[TI, TO, Any], /, wait_for_thread: bool) -> AsyncGenerator[TI, TO]: ...
59
- @overload
60
- async def _asyncify_iter(it: Iterable[TO], /, wait_for_thread: bool) -> AsyncGenerator[Any, TO]: ...
61
- async def _asyncify_iter(it, /, wait_for_thread: bool = False):
62
- if wait_for_thread:
63
- if isinstance(it, Generator):
64
- send = it.send
65
- def nextval(val):
66
- try:
67
- return send(val), None
68
- except BaseException as e:
69
- return None, e
70
- else:
71
- getnext = iter(it).__next__
72
- def nextval(val):
73
- try:
74
- return getnext(), None
75
- except BaseException as e:
76
- return None, e
77
- val = None
78
- while True:
79
- yield_val, exc = await to_thread(nextval, val)
80
- if exc is None:
81
- yield yield_val
82
- elif isinstance(exc, StopIteration):
83
- break
84
- else:
85
- raise exc
86
- elif isinstance(it, Generator):
87
- send = it.send
88
- val = None
89
- try:
90
- while True:
91
- val = yield send(val)
92
- except StopIteration:
93
- pass
94
- else:
95
- for val in it:
96
- yield val
97
-
98
-
99
- @overload
100
- def asyncify_iter(it: AsyncIterable[TO], /, wait_for_thread: bool) -> AsyncIterable[TO]: ...
101
- @overload
102
- def asyncify_iter(it: Generator[TI, TO, Any], /, wait_for_thread: bool) -> AsyncGenerator[TI, TO]: ...
103
- @overload
104
- def asyncify_iter(it: Iterable[TO], /, wait_for_thread: bool) -> AsyncGenerator[Any, TO]: ...
105
- def asyncify_iter(it, /, wait_for_thread: bool = False):
106
- if isinstance(it, AsyncIterable):
107
- return it
108
- return _asyncify_iter(it, wait_for_thread=wait_for_thread)
109
-
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-iterutils
3
- Version: 0.0.1
3
+ Version: 0.0.2.2
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
@@ -21,6 +21,7 @@ Classifier: Programming Language :: Python :: 3 :: Only
21
21
  Classifier: Topic :: Software Development
22
22
  Classifier: Topic :: Software Development :: Libraries
23
23
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
24
+ Requires-Dist: python-asynctools
24
25
  Project-URL: Repository, https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-iterutils
25
26
  Description-Content-Type: text/markdown
26
27
 
@@ -0,0 +1,7 @@
1
+ LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
+ iterutils/__init__.py,sha256=z5sIhwNu0U7YrxxF2WSxGtZjJu3kU2d6f2LXLwTJqH8,3119
3
+ iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ python_iterutils-0.0.2.2.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
+ python_iterutils-0.0.2.2.dist-info/METADATA,sha256=pl-dTESGVeFhCx4uvb67K8NAtwXR7Fe5vU5tLuRQ5s4,1384
6
+ python_iterutils-0.0.2.2.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
7
+ python_iterutils-0.0.2.2.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
- iterutils/__init__.py,sha256=rlt5eSf9A7_58WR8dDYgS-Fe40nHMGiwurUeymnuyro,3123
3
- iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- python_iterutils-0.0.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
- python_iterutils-0.0.1.dist-info/METADATA,sha256=wByxjlr3955Z05zMMiOncJ2dwkA86vHRsV72UXn2D1I,1349
6
- python_iterutils-0.0.1.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
7
- python_iterutils-0.0.1.dist-info/RECORD,,