python-iterutils 0.1.2.1__py3-none-any.whl → 0.1.3.1__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,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
@@ -176,6 +180,88 @@ async def async_flatten(
176
180
  yield e
177
181
 
178
182
 
183
+ def map(
184
+ function: None | 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
+ if function is None:
195
+ if iterables:
196
+ return async_zip(iterable, *iterables)
197
+ else:
198
+ return iterable
199
+ return async_map(function, iterable, *iterables)
200
+ if function is None:
201
+ if iterables:
202
+ return zip(iterable, *iterables)
203
+ else:
204
+ return iterable
205
+ from builtins import map
206
+ return map(function, iterable, *iterables)
207
+
208
+
209
+ def filter(
210
+ function: None | Callable,
211
+ iterable: Iterable | AsyncIterable,
212
+ /,
213
+ ):
214
+ if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
215
+ return async_filter(function, iterable)
216
+ from builtins import filter
217
+ return filter(function, iterable)
218
+
219
+
220
+ def reduce(
221
+ function: Callable,
222
+ iterable: Iterable | AsyncIterable,
223
+ initial = undefined,
224
+ /,
225
+ ):
226
+ if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
227
+ return async_reduce(function, iterable, initial)
228
+ from functools import reduce
229
+ if initial is undefined:
230
+ return reduce(function, iterable)
231
+ return reduce(function, iterable, initial)
232
+
233
+
234
+ @overload
235
+ def chunked[T](
236
+ iterable: Iterable[T],
237
+ n: int = 1,
238
+ /,
239
+ ) -> Iterator[Sequence[T]]:
240
+ ...
241
+ @overload
242
+ def chunked[T](
243
+ iterable: AsyncIterable[T],
244
+ n: int = 1,
245
+ /,
246
+ ) -> AsyncIterator[Sequence[T]]:
247
+ ...
248
+ def chunked[T](
249
+ iterable: Iterable[T] | AsyncIterable[T],
250
+ n: int = 1,
251
+ /,
252
+ ) -> Iterator[Sequence[T]] | AsyncIterator[Sequence[T]]:
253
+ if n < 0:
254
+ n = 1
255
+ if isinstance(iterable, Sequence):
256
+ if n == 1:
257
+ return ((e,) for e in iterable)
258
+ return (iterable[i:j] for i, j in pairwise(range(0, len(iterable)+n, n)))
259
+ elif isinstance(iterable, Iterable):
260
+ return batched(iterable, n)
261
+ else:
262
+ return async_batched(iterable, n)
263
+
264
+
179
265
  @overload
180
266
  def iter_unique[T](
181
267
  iterable: Iterable[T],
@@ -223,37 +309,6 @@ async def async_iter_unique[T](
223
309
  add(e)
224
310
 
225
311
 
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
312
  @overload
258
313
  def wrap_iter[T](
259
314
  iterable: Iterable[T],
@@ -656,3 +711,49 @@ def bfs_gen[T](
656
711
  push(args)
657
712
  args = yield val
658
713
 
714
+
715
+ @overload
716
+ def with_iter_next[T](
717
+ iterable: Iterable[T],
718
+ /,
719
+ async_: Literal[False] = False,
720
+ ) -> ContextManager[Callable[[], T]]:
721
+ ...
722
+ @overload
723
+ def with_iter_next[T](
724
+ iterable: AsyncIterable[T],
725
+ /,
726
+ async_: Literal[False] = False,
727
+ ) -> ContextManager[Callable[[], Awaitable[T]]]:
728
+ ...
729
+ @overload
730
+ def with_iter_next[T](
731
+ iterable: Iterable[T] | AsyncIterable[T],
732
+ /,
733
+ async_: Literal[True],
734
+ ) -> ContextManager[Callable[[], Awaitable[T]]]:
735
+ ...
736
+ @contextmanager
737
+ def with_iter_next[T](
738
+ iterable: Iterable[T] | AsyncIterable[T],
739
+ /,
740
+ async_: Literal[False, True] = False,
741
+ ):
742
+ if async_:
743
+ get_next: Callable[[], T] | Callable[[], Awaitable[T]] = ensure_aiter(iterable).__anext__
744
+ elif isinstance(iterable, Iterable):
745
+ get_next = iter(iterable).__next__
746
+ else:
747
+ get_next = aiter(iterable).__anext__
748
+ async_ = True
749
+ if async_:
750
+ try:
751
+ yield get_next
752
+ except StopAsyncIteration:
753
+ pass
754
+ else:
755
+ try:
756
+ yield get_next
757
+ except StopIteration:
758
+ pass
759
+
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-iterutils
3
- Version: 0.1.2.1
3
+ Version: 0.1.3.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
@@ -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
 
@@ -0,0 +1,7 @@
1
+ LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
+ iterutils/__init__.py,sha256=jZgTbKqNqCxwkMFObL6Hl-AEeMoIPV7BT7_HcgO6Sxc,22576
3
+ iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ python_iterutils-0.1.3.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
+ python_iterutils-0.1.3.1.dist-info/METADATA,sha256=vEPfbqRtNvKF6Hdh6B9NTAmQsZX5s9aqCK8mUc9nOyo,1386
6
+ python_iterutils-0.1.3.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
+ python_iterutils-0.1.3.1.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
- iterutils/__init__.py,sha256=IXbHP7Gsl2kFxzJ__wFihqulcFuAec6nRe1yQrZynMQ,19786
3
- iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- python_iterutils-0.1.2.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
- python_iterutils-0.1.2.1.dist-info/METADATA,sha256=elEGJWssbe3O36Ecb0Vo9MqtN4bxKl08pL7mNCQuxXM,1343
6
- python_iterutils-0.1.2.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
- python_iterutils-0.1.2.1.dist-info/RECORD,,