python-iterutils 0.0.1__tar.gz → 0.0.2.1__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.1
3
+ Version: 0.0.2.1
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
@@ -0,0 +1,132 @@
1
+ #!/usr/bin/env python3
2
+ # encoding: utf-8
3
+
4
+ __author__ = "ChenyangGao <https://chenyanggao.github.io>"
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
+ ]
10
+
11
+ from collections.abc import AsyncIterable, AsyncIterator, Callable, Iterable, Iterator
12
+ from typing import Any, TypeVar
13
+
14
+ from asynctools import async_zip, ensure_async, ensure_aiter
15
+
16
+
17
+ T = TypeVar("T")
18
+
19
+
20
+ def iterable(it, /) -> bool:
21
+ try:
22
+ return isinstance(iter(it), Iterable)
23
+ except TypeError:
24
+ return False
25
+
26
+
27
+ def async_iterable(it, /) -> bool:
28
+ try:
29
+ return isinstance(iter(it), AsyncIterable)
30
+ except TypeError:
31
+ return False
32
+
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
+
102
+ def acc_step(
103
+ start: int,
104
+ stop: None | int = None,
105
+ step: int = 1,
106
+ ) -> Iterator[tuple[int, int, int]]:
107
+ if stop is None:
108
+ start, stop = 0, start
109
+ for i in range(start + step, stop, step):
110
+ yield start, (start := i), step
111
+ if start != stop:
112
+ yield start, stop, stop - start
113
+
114
+
115
+ def cut_iter(
116
+ start: int,
117
+ stop: None | int = None,
118
+ step: int = 1,
119
+ ) -> Iterator[tuple[int, int]]:
120
+ if stop is None:
121
+ start, stop = 0, start
122
+ for start in range(start + step, stop, step):
123
+ yield start, step
124
+ if start != stop:
125
+ yield stop, stop - start
126
+
127
+
128
+ async def iter_to_aiter():
129
+ for i in it:
130
+ yield i
131
+
132
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-iterutils"
3
- version = "0.0.1"
3
+ version = "0.0.2.1"
4
4
  description = "Python another itertools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"
@@ -1,109 +0,0 @@
1
- #!/usr/bin/env python3
2
- # encoding: utf-8
3
-
4
- __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 0, 1)
6
- __all__ = ["iterable", "async_iterable", "acc_step", "cut_iter", "asyncify_iter"]
7
-
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
-
12
-
13
- TI = TypeVar("TI")
14
- TO = TypeVar("TO")
15
-
16
-
17
- def iterable(it, /) -> bool:
18
- try:
19
- return isinstance(iter(it), Iterable)
20
- except TypeError:
21
- return False
22
-
23
-
24
- def async_iterable(it, /) -> bool:
25
- try:
26
- return isinstance(iter(it), AsyncIterable)
27
- except TypeError:
28
- return False
29
-
30
-
31
- def acc_step(
32
- start: int,
33
- stop: Optional[int] = None,
34
- step: int = 1,
35
- ) -> Iterator[tuple[int, int, int]]:
36
- if stop is None:
37
- start, stop = 0, start
38
- for i in range(start + step, stop, step):
39
- yield start, (start := i), step
40
- if start != stop:
41
- yield start, stop, stop - start
42
-
43
-
44
- def cut_iter(
45
- start: int,
46
- stop: Optional[int] = None,
47
- step: int = 1,
48
- ) -> Iterator[tuple[int, int]]:
49
- if stop is None:
50
- start, stop = 0, start
51
- for start in range(start + step, stop, step):
52
- yield start, step
53
- if start != stop:
54
- yield stop, stop - start
55
-
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
-