python-iterutils 0.1.7__py3-none-any.whl → 0.1.8__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,24 +2,26 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 1, 7)
5
+ __version__ = (0, 1, 8)
6
6
  __all__ = [
7
7
  "Return", "Yield", "YieldFrom", "iterable", "async_iterable", "foreach", "async_foreach",
8
- "through", "async_through", "flatten", "async_flatten", "map", "filter", "reduce", "zip",
9
- "chunked", "iter_unique", "async_iter_unique", "wrap_iter", "wrap_aiter", "acc_step",
10
- "cut_iter", "run_gen_step", "run_gen_step_iter", "as_gen_step", "bfs_gen", "with_iter_next",
11
- "backgroud_loop",
8
+ "through", "async_through", "flatten", "async_flatten", "collect", "async_collect",
9
+ "group_collect", "async_group_collect", "map", "filter", "reduce", "zip", "chunked",
10
+ "iter_unique", "async_iter_unique", "wrap_iter", "wrap_aiter", "acc_step", "cut_iter",
11
+ "run_gen_step", "run_gen_step_iter", "as_gen_step", "bfs_gen", "with_iter_next", "backgroud_loop",
12
12
  ]
13
13
 
14
14
  from abc import ABC, abstractmethod
15
15
  from asyncio import create_task, sleep as async_sleep, to_thread
16
16
  from builtins import map as _map, filter as _filter, zip as _zip
17
- from collections import deque
17
+ from collections import defaultdict, deque
18
18
  from collections.abc import (
19
- AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable, Coroutine, Generator,
20
- Iterable, Iterator, MutableSet, Sequence,
19
+ AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable, Collection, Container,
20
+ Coroutine, Generator, Iterable, Iterator, Mapping, MutableMapping, MutableSet,
21
+ MutableSequence, Sequence, ValuesView,
21
22
  )
22
23
  from contextlib import asynccontextmanager, contextmanager, ExitStack, AsyncExitStack
24
+ from copy import copy
23
25
  from dataclasses import dataclass
24
26
  from itertools import batched, pairwise
25
27
  from inspect import isawaitable, iscoroutinefunction
@@ -27,10 +29,11 @@ from sys import _getframe
27
29
  from _thread import start_new_thread
28
30
  from time import sleep, time
29
31
  from types import FrameType
30
- from typing import overload, Any, AsyncContextManager, ContextManager, Literal
32
+ from typing import cast, overload, Any, AsyncContextManager, ContextManager, Literal
31
33
 
32
34
  from asynctools import (
33
35
  async_filter, async_map, async_reduce, async_zip, async_batched, ensure_async, ensure_aiter,
36
+ collect as async_collect,
34
37
  )
35
38
  from decotools import optional
36
39
  from texttools import format_time
@@ -96,7 +99,7 @@ async def async_foreach(
96
99
  iterable: Iterable | AsyncIterable,
97
100
  /,
98
101
  *iterables: Iterable | AsyncIterable,
99
- threaded: bool = True,
102
+ threaded: bool = False,
100
103
  ):
101
104
  value = ensure_async(value, threaded=threaded)
102
105
  if iterables:
@@ -127,7 +130,7 @@ async def async_through(
127
130
  iterable: Iterable | AsyncIterable,
128
131
  /,
129
132
  take_while: None | Callable = None,
130
- threaded: bool = True,
133
+ threaded: bool = False,
131
134
  ):
132
135
  iterable = ensure_aiter(iterable, threaded=threaded)
133
136
  if take_while is None:
@@ -177,7 +180,7 @@ async def async_flatten(
177
180
  iterable: Iterable | AsyncIterable,
178
181
  /,
179
182
  exclude_types: type | tuple[type, ...] = (Buffer, str),
180
- threaded: bool = True,
183
+ threaded: bool = False,
181
184
  ) -> AsyncIterator:
182
185
  async for e in ensure_aiter(iterable, threaded=threaded):
183
186
  if isinstance(e, (Iterable, AsyncIterable)) and not isinstance(e, exclude_types):
@@ -187,6 +190,168 @@ async def async_flatten(
187
190
  yield e
188
191
 
189
192
 
193
+ @overload
194
+ def collect[K, V](
195
+ iterable: Iterable[tuple[K, V]] | Mapping[K, V],
196
+ /,
197
+ rettype: Callable[[Iterable[tuple[K, V]]], MutableMapping[K, V]],
198
+ ) -> MutableMapping[K, V]:
199
+ ...
200
+ @overload
201
+ def collect[T](
202
+ iterable: Iterable[T],
203
+ /,
204
+ rettype: Callable[[Iterable[T]], Collection[T]] = list,
205
+ ) -> Collection[T]:
206
+ ...
207
+ @overload
208
+ def collect[K, V](
209
+ iterable: AsyncIterable[tuple[K, V]],
210
+ /,
211
+ rettype: Callable[[Iterable[tuple[K, V]]], MutableMapping[K, V]],
212
+ ) -> Coroutine[Any, Any, MutableMapping[K, V]]:
213
+ ...
214
+ @overload
215
+ def collect[T](
216
+ iterable: AsyncIterable[T],
217
+ /,
218
+ rettype: Callable[[Iterable[T]], Collection[T]] = list,
219
+ ) -> Coroutine[Any, Any, Collection[T]]:
220
+ ...
221
+ def collect(
222
+ iterable: Iterable | AsyncIterable | Mapping,
223
+ /,
224
+ rettype: Callable[[Iterable], Collection] = list,
225
+ ) -> Collection | Coroutine[Any, Any, Collection]:
226
+ if not isinstance(iterable, Iterable):
227
+ return async_collect(iterable, rettype)
228
+ return rettype(iterable)
229
+
230
+
231
+ @overload
232
+ def group_collect[K, V, C: Container](
233
+ iterable: Iterable[tuple[K, V]],
234
+ mapping: None = None,
235
+ factory: None | C | Callable[[], C] = None,
236
+ ) -> dict[K, C]:
237
+ ...
238
+ @overload
239
+ def group_collect[K, V, C: Container, M: MutableMapping](
240
+ iterable: Iterable[tuple[K, V]],
241
+ mapping: M,
242
+ factory: None | C | Callable[[], C] = None,
243
+ ) -> M:
244
+ ...
245
+ @overload
246
+ def group_collect[K, V, C: Container](
247
+ iterable: AsyncIterable[tuple[K, V]],
248
+ mapping: None = None,
249
+ factory: None | C | Callable[[], C] = None,
250
+ ) -> Coroutine[Any, Any, dict[K, C]]:
251
+ ...
252
+ @overload
253
+ def group_collect[K, V, C: Container, M: MutableMapping](
254
+ iterable: AsyncIterable[tuple[K, V]],
255
+ mapping: M,
256
+ factory: None | C | Callable[[], C] = None,
257
+ ) -> Coroutine[Any, Any, M]:
258
+ ...
259
+ def group_collect[K, V, C: Container, M: MutableMapping](
260
+ iterable: Iterable[tuple[K, V]] | AsyncIterable[tuple[K, V]],
261
+ mapping: None | M = None,
262
+ factory: None | C | Callable[[], C] = None,
263
+ ) -> dict[K, C] | M | Coroutine[Any, Any, dict[K, C]] | Coroutine[Any, Any, M]:
264
+ if not isinstance(iterable, Iterable):
265
+ return async_group_collect(iterable, mapping, factory)
266
+ if factory is None:
267
+ if isinstance(mapping, defaultdict):
268
+ factory = mapping.default_factory
269
+ elif mapping:
270
+ factory = type(next(iter(ValuesView(mapping))))
271
+ else:
272
+ factory = cast(type[C], list)
273
+ elif callable(factory):
274
+ pass
275
+ elif isinstance(factory, Container):
276
+ factory = cast(Callable[[], C], lambda _obj=factory: copy(_obj))
277
+ else:
278
+ raise ValueError("can't determine factory")
279
+ factory = cast(Callable[[], C], factory)
280
+ if isinstance(factory, type):
281
+ factory_type = factory
282
+ else:
283
+ factory_type = type(factory())
284
+ if issubclass(factory_type, MutableSequence):
285
+ add = getattr(factory_type, "append")
286
+ else:
287
+ add = getattr(factory_type, "add")
288
+ if mapping is None:
289
+ mapping = cast(M, {})
290
+ for k, v in iterable:
291
+ try:
292
+ c = mapping[k]
293
+ except LookupError:
294
+ c = mapping[k] = factory()
295
+ add(c, v)
296
+ return mapping
297
+
298
+
299
+ @overload
300
+ async def async_group_collect[K, V, C: Container](
301
+ iterable: Iterable[tuple[K, V]] | AsyncIterable[tuple[K, V]],
302
+ mapping: None = None,
303
+ factory: None | C | Callable[[], C] = None,
304
+ threaded: bool = False,
305
+ ) -> dict[K, C]:
306
+ ...
307
+ @overload
308
+ async def async_group_collect[K, V, C: Container, M: MutableMapping](
309
+ iterable: Iterable[tuple[K, V]] | AsyncIterable[tuple[K, V]],
310
+ mapping: M,
311
+ factory: None | C | Callable[[], C] = None,
312
+ threaded: bool = False,
313
+ ) -> M:
314
+ ...
315
+ async def async_group_collect[K, V, C: Container, M: MutableMapping](
316
+ iterable: Iterable[tuple[K, V]] | AsyncIterable[tuple[K, V]],
317
+ mapping: None | M = None,
318
+ factory: None | C | Callable[[], C] = None,
319
+ threaded: bool = False,
320
+ ) -> dict[K, C] | M:
321
+ iterable = ensure_aiter(iterable, threaded=threaded)
322
+ if factory is None:
323
+ if isinstance(mapping, defaultdict):
324
+ factory = mapping.default_factory
325
+ elif mapping:
326
+ factory = type(next(iter(ValuesView(mapping))))
327
+ else:
328
+ factory = cast(type[C], list)
329
+ elif callable(factory):
330
+ pass
331
+ elif isinstance(factory, Container):
332
+ factory = cast(Callable[[], C], lambda _obj=factory: copy(_obj))
333
+ else:
334
+ raise ValueError("can't determine factory")
335
+ factory = cast(Callable[[], C], factory)
336
+ if isinstance(factory, type):
337
+ factory_type = factory
338
+ else:
339
+ factory_type = type(factory())
340
+ if issubclass(factory_type, MutableSequence):
341
+ add = getattr(factory_type, "append")
342
+ else:
343
+ add = getattr(factory_type, "add")
344
+ if mapping is None:
345
+ mapping = cast(M, {})
346
+ async for k, v in iterable:
347
+ try:
348
+ c = mapping[k]
349
+ except LookupError:
350
+ c = mapping[k] = factory()
351
+ add(c, v)
352
+ return mapping
353
+
354
+
190
355
  def map(
191
356
  function: None | Callable,
192
357
  iterable: Iterable | AsyncIterable,
@@ -400,7 +565,7 @@ async def wrap_aiter[T](
400
565
  callnext: None | Callable[[T], Any] = None,
401
566
  callenter: None | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
402
567
  callexit: None | Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] = None,
403
- threaded: bool = True,
568
+ threaded: bool = False,
404
569
  ) -> AsyncIterator[T]:
405
570
  callprev = ensure_async(callprev, threaded=threaded) if callable(callprev) else None
406
571
  callnext = ensure_async(callnext, threaded=threaded) if callable(callnext) else None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-iterutils
3
- Version: 0.1.7
3
+ Version: 0.1.8
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,7 @@ 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.10)
23
+ Requires-Dist: python-asynctools (>=0.0.10.1)
24
24
  Requires-Dist: python-decotools (>=0.0.2)
25
25
  Requires-Dist: python-texttools (>=0.0.3)
26
26
  Requires-Dist: python-undefined (>=0.0.3)
@@ -0,0 +1,7 @@
1
+ LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
+ iterutils/__init__.py,sha256=zcNPBE2QtJZyGlTr4n913Zwtd2OJAiAFdvEaYIur0kw,32751
3
+ iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ python_iterutils-0.1.8.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
+ python_iterutils-0.1.8.dist-info/METADATA,sha256=JuLFHrGXyrqYv-ajoNOpWuxXKAhAu9CMch5Mbscvf3E,1470
6
+ python_iterutils-0.1.8.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
+ python_iterutils-0.1.8.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
- iterutils/__init__.py,sha256=BR4ZaZouhl3o9e6ZrBLLEBRfNJzKik8Et-B38Lw_yf0,27444
3
- iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- python_iterutils-0.1.7.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
- python_iterutils-0.1.7.dist-info/METADATA,sha256=DkEirEtm5-ycdVDBZwb_o-0poNqQDA8Gv5QfJ5o4SwA,1468
6
- python_iterutils-0.1.7.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
- python_iterutils-0.1.7.dist-info/RECORD,,