python-iterutils 0.1.2__tar.gz → 0.1.3__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.1.2
3
+ Version: 0.1.3
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
@@ -20,7 +20,8 @@ Classifier: Programming Language :: Python :: 3 :: Only
20
20
  Classifier: Topic :: Software Development
21
21
  Classifier: Topic :: Software Development :: Libraries
22
22
  Classifier: Topic :: Software Development :: Libraries :: Python Modules
23
- Requires-Dist: python-asynctools (>=0.0.9)
23
+ Requires-Dist: python-asynctools (>=0.0.10)
24
+ Requires-Dist: python-undefined (>=0.0.3)
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
 
@@ -2,28 +2,31 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 1, 2)
5
+ __version__ = (0, 1, 3)
6
6
  __all__ = [
7
7
  "Return", "Yield", "YieldFrom", "iterable", "async_iterable", "foreach", "async_foreach",
8
- "through", "async_through", "flatten", "async_flatten", "iter_unique", "async_iter_unique",
9
- "chunked", "wrap_iter", "wrap_aiter", "acc_step", "cut_iter", "run_gen_step",
10
- "run_gen_step_iter", "bfs_gen",
8
+ "through", "async_through", "flatten", "async_flatten", "map", "filter", "reduce", "chunked",
9
+ "iter_unique", "async_iter_unique", "wrap_iter", "wrap_aiter", "acc_step", "cut_iter",
10
+ "run_gen_step", "run_gen_step_iter", "bfs_gen", "with_iter_next",
11
11
  ]
12
12
 
13
-
14
13
  from abc import ABC, abstractmethod
15
14
  from asyncio import to_thread
16
15
  from collections import deque
17
16
  from collections.abc import (
18
- AsyncIterable, AsyncIterator, Buffer, Callable, Generator,
17
+ AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable, Generator,
19
18
  Iterable, Iterator, MutableSet, Sequence,
20
19
  )
20
+ from contextlib import contextmanager
21
21
  from dataclasses import dataclass
22
22
  from itertools import batched, pairwise
23
- from inspect import isawaitable
24
- from typing import overload, Any, Literal
23
+ from inspect import isawaitable, iscoroutinefunction
24
+ from typing import overload, Any, ContextManager, Literal
25
25
 
26
- from asynctools import async_map, async_zip, async_batched, ensure_async, ensure_aiter
26
+ from asynctools import (
27
+ async_filter, async_map, async_reduce, async_zip, async_batched, ensure_async, ensure_aiter,
28
+ )
29
+ from undefined import undefined, Undefined
27
30
 
28
31
 
29
32
  @dataclass(slots=True, frozen=True)
@@ -107,6 +110,7 @@ def through(
107
110
  for _ in iterable:
108
111
  pass
109
112
  else:
113
+ from builtins import map
110
114
  for v in map(take_while, iterable):
111
115
  if not v:
112
116
  break
@@ -137,20 +141,20 @@ def flatten(
137
141
  iterable: Iterable,
138
142
  /,
139
143
  exclude_types: type | tuple[type, ...] = (Buffer, str),
140
- ) -> Iterable:
144
+ ) -> Iterator:
141
145
  ...
142
146
  @overload
143
147
  def flatten(
144
148
  iterable: AsyncIterable,
145
149
  /,
146
150
  exclude_types: type | tuple[type, ...] = (Buffer, str),
147
- ) -> AsyncIterable:
151
+ ) -> AsyncIterator:
148
152
  ...
149
153
  def flatten(
150
154
  iterable: Iterable | AsyncIterable,
151
155
  /,
152
156
  exclude_types: type | tuple[type, ...] = (Buffer, str),
153
- ) -> Iterable | AsyncIterable:
157
+ ) -> Iterator | AsyncIterator:
154
158
  if not isinstance(iterable, Iterable):
155
159
  return async_flatten(iterable, exclude_types)
156
160
  def gen(iterable):
@@ -176,6 +180,78 @@ async def async_flatten(
176
180
  yield e
177
181
 
178
182
 
183
+ def map(
184
+ function: Callable,
185
+ iterable: Iterable | AsyncIterable,
186
+ /,
187
+ *iterables: Iterable | AsyncIterable,
188
+ ):
189
+ if (
190
+ iscoroutinefunction(function) or
191
+ isinstance(iterable, AsyncIterable) or
192
+ any(isinstance(i, AsyncIterable) for i in iterables)
193
+ ):
194
+ return async_map(function, iterable, *iterables)
195
+ from builtins import map
196
+ return map(function, iterable, *iterables)
197
+
198
+
199
+ def filter(
200
+ function: Callable,
201
+ iterable: Iterable | AsyncIterable,
202
+ /,
203
+ ):
204
+ if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
205
+ return async_filter(function, iterable)
206
+ from builtins import filter
207
+ return filter(function, iterable)
208
+
209
+
210
+ def reduce(
211
+ function: Callable,
212
+ iterable: Iterable | AsyncIterable,
213
+ initial = undefined,
214
+ /,
215
+ ):
216
+ if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
217
+ return async_reduce(function, iterable, initial)
218
+ from functools import reduce
219
+ if initial is undefined:
220
+ return reduce(function, iterable)
221
+ return reduce(function, iterable, initial)
222
+
223
+
224
+ @overload
225
+ def chunked[T](
226
+ iterable: Iterable[T],
227
+ n: int = 1,
228
+ /,
229
+ ) -> Iterator[Sequence[T]]:
230
+ ...
231
+ @overload
232
+ def chunked[T](
233
+ iterable: AsyncIterable[T],
234
+ n: int = 1,
235
+ /,
236
+ ) -> AsyncIterator[Sequence[T]]:
237
+ ...
238
+ def chunked[T](
239
+ iterable: Iterable[T] | AsyncIterable[T],
240
+ n: int = 1,
241
+ /,
242
+ ) -> Iterator[Sequence[T]] | AsyncIterator[Sequence[T]]:
243
+ if n < 0:
244
+ n = 1
245
+ if isinstance(iterable, Sequence):
246
+ if n == 1:
247
+ return ((e,) for e in iterable)
248
+ return (iterable[i:j] for i, j in pairwise(range(0, len(iterable)+n, n)))
249
+ elif isinstance(iterable, Iterable):
250
+ return batched(iterable, n)
251
+ else:
252
+ return async_batched(iterable, n)
253
+
254
+
179
255
  @overload
180
256
  def iter_unique[T](
181
257
  iterable: Iterable[T],
@@ -223,37 +299,6 @@ async def async_iter_unique[T](
223
299
  add(e)
224
300
 
225
301
 
226
- @overload
227
- def chunked[T](
228
- iterable: Iterable[T],
229
- n: int = 1,
230
- /,
231
- ) -> Iterator[Sequence[T]]:
232
- ...
233
- @overload
234
- def chunked[T](
235
- iterable: AsyncIterable[T],
236
- n: int = 1,
237
- /,
238
- ) -> AsyncIterator[Sequence[T]]:
239
- ...
240
- def chunked[T](
241
- iterable: Iterable[T] | AsyncIterable[T],
242
- n: int = 1,
243
- /,
244
- ) -> Iterator[Sequence[T]] | AsyncIterator[Sequence[T]]:
245
- if n < 0:
246
- n = 1
247
- if isinstance(iterable, Sequence):
248
- if n == 1:
249
- return ((e,) for e in iterable)
250
- return (iterable[i:j] for i, j in pairwise(range(0, len(iterable)+n, n)))
251
- elif isinstance(iterable, Iterable):
252
- return batched(iterable, n)
253
- else:
254
- return async_batched(iterable, n)
255
-
256
-
257
302
  @overload
258
303
  def wrap_iter[T](
259
304
  iterable: Iterable[T],
@@ -656,3 +701,49 @@ def bfs_gen[T](
656
701
  push(args)
657
702
  args = yield val
658
703
 
704
+
705
+ @overload
706
+ def with_iter_next[T](
707
+ iterable: Iterable[T],
708
+ /,
709
+ async_: Literal[False] = False,
710
+ ) -> ContextManager[Callable[[], T]]:
711
+ ...
712
+ @overload
713
+ def with_iter_next[T](
714
+ iterable: AsyncIterable[T],
715
+ /,
716
+ async_: Literal[False] = False,
717
+ ) -> ContextManager[Callable[[], Awaitable[T]]]:
718
+ ...
719
+ @overload
720
+ def with_iter_next[T](
721
+ iterable: Iterable[T] | AsyncIterable[T],
722
+ /,
723
+ async_: Literal[True],
724
+ ) -> ContextManager[Callable[[], Awaitable[T]]]:
725
+ ...
726
+ @contextmanager
727
+ def with_iter_next[T](
728
+ iterable: Iterable[T] | AsyncIterable[T],
729
+ /,
730
+ async_: Literal[False, True] = False,
731
+ ):
732
+ if async_:
733
+ get_next: Callable[[], T] | Callable[[], Awaitable[T]] = ensure_aiter(iterable).__anext__
734
+ elif isinstance(iterable, Iterable):
735
+ get_next = iter(iterable).__next__
736
+ else:
737
+ get_next = aiter(iterable).__anext__
738
+ async_ = True
739
+ if async_:
740
+ try:
741
+ yield get_next
742
+ except StopAsyncIteration:
743
+ pass
744
+ else:
745
+ try:
746
+ yield get_next
747
+ except StopIteration:
748
+ pass
749
+
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-iterutils"
3
- version = "0.1.2"
3
+ version = "0.1.3"
4
4
  description = "Python another itertools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"
@@ -27,7 +27,8 @@ include = [
27
27
 
28
28
  [tool.poetry.dependencies]
29
29
  python = "^3.12"
30
- python-asynctools = ">=0.0.9"
30
+ python-asynctools = ">=0.0.10"
31
+ python-undefined = ">=0.0.3"
31
32
 
32
33
  [build-system]
33
34
  requires = ["poetry-core"]