python-iterutils 0.1.3.1__py3-none-any.whl → 0.1.5__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 +135 -16
- {python_iterutils-0.1.3.1.dist-info → python_iterutils-0.1.5.dist-info}/METADATA +2 -1
- python_iterutils-0.1.5.dist-info/RECORD +7 -0
- python_iterutils-0.1.3.1.dist-info/RECORD +0 -7
- {python_iterutils-0.1.3.1.dist-info → python_iterutils-0.1.5.dist-info}/LICENSE +0 -0
- {python_iterutils-0.1.3.1.dist-info → python_iterutils-0.1.5.dist-info}/WHEEL +0 -0
iterutils/__init__.py
CHANGED
|
@@ -2,30 +2,34 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
|
|
4
4
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
5
|
-
__version__ = (0, 1,
|
|
5
|
+
__version__ = (0, 1, 5)
|
|
6
6
|
__all__ = [
|
|
7
7
|
"Return", "Yield", "YieldFrom", "iterable", "async_iterable", "foreach", "async_foreach",
|
|
8
|
-
"through", "async_through", "flatten", "async_flatten", "map", "filter", "reduce", "
|
|
9
|
-
"iter_unique", "async_iter_unique", "wrap_iter", "wrap_aiter", "acc_step",
|
|
10
|
-
"run_gen_step", "run_gen_step_iter", "bfs_gen", "with_iter_next",
|
|
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", "bfs_gen", "with_iter_next", "backgroud_loop",
|
|
11
11
|
]
|
|
12
12
|
|
|
13
13
|
from abc import ABC, abstractmethod
|
|
14
|
-
from asyncio import to_thread
|
|
14
|
+
from asyncio import create_task, sleep as async_sleep, to_thread
|
|
15
|
+
from builtins import map as _map, filter as _filter, zip as _zip
|
|
15
16
|
from collections import deque
|
|
16
17
|
from collections.abc import (
|
|
17
|
-
AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable, Generator,
|
|
18
|
+
AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable, Coroutine, Generator,
|
|
18
19
|
Iterable, Iterator, MutableSet, Sequence,
|
|
19
20
|
)
|
|
20
|
-
from contextlib import contextmanager
|
|
21
|
+
from contextlib import asynccontextmanager, contextmanager, ExitStack, AsyncExitStack
|
|
21
22
|
from dataclasses import dataclass
|
|
22
23
|
from itertools import batched, pairwise
|
|
23
24
|
from inspect import isawaitable, iscoroutinefunction
|
|
24
|
-
from
|
|
25
|
+
from _thread import start_new_thread
|
|
26
|
+
from time import sleep, time
|
|
27
|
+
from typing import overload, Any, AsyncContextManager, ContextManager, Literal
|
|
25
28
|
|
|
26
29
|
from asynctools import (
|
|
27
30
|
async_filter, async_map, async_reduce, async_zip, async_batched, ensure_async, ensure_aiter,
|
|
28
31
|
)
|
|
32
|
+
from texttools import format_time
|
|
29
33
|
from undefined import undefined, Undefined
|
|
30
34
|
|
|
31
35
|
|
|
@@ -76,7 +80,7 @@ def foreach(
|
|
|
76
80
|
if not (isinstance(iterable, Iterable) and all(isinstance(it, Iterable) for it in iterables)):
|
|
77
81
|
return async_foreach(value, iterable, *iterables)
|
|
78
82
|
if iterables:
|
|
79
|
-
for args in
|
|
83
|
+
for args in _zip(iterable, *iterables):
|
|
80
84
|
value(*args)
|
|
81
85
|
else:
|
|
82
86
|
for arg in iterable:
|
|
@@ -110,8 +114,7 @@ def through(
|
|
|
110
114
|
for _ in iterable:
|
|
111
115
|
pass
|
|
112
116
|
else:
|
|
113
|
-
|
|
114
|
-
for v in map(take_while, iterable):
|
|
117
|
+
for v in _map(take_while, iterable):
|
|
115
118
|
if not v:
|
|
116
119
|
break
|
|
117
120
|
|
|
@@ -199,11 +202,10 @@ def map(
|
|
|
199
202
|
return async_map(function, iterable, *iterables)
|
|
200
203
|
if function is None:
|
|
201
204
|
if iterables:
|
|
202
|
-
return
|
|
205
|
+
return _zip(iterable, *iterables)
|
|
203
206
|
else:
|
|
204
207
|
return iterable
|
|
205
|
-
|
|
206
|
-
return map(function, iterable, *iterables)
|
|
208
|
+
return _map(function, iterable, *iterables)
|
|
207
209
|
|
|
208
210
|
|
|
209
211
|
def filter(
|
|
@@ -213,8 +215,7 @@ def filter(
|
|
|
213
215
|
):
|
|
214
216
|
if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
|
|
215
217
|
return async_filter(function, iterable)
|
|
216
|
-
|
|
217
|
-
return filter(function, iterable)
|
|
218
|
+
return _filter(function, iterable)
|
|
218
219
|
|
|
219
220
|
|
|
220
221
|
def reduce(
|
|
@@ -231,6 +232,16 @@ def reduce(
|
|
|
231
232
|
return reduce(function, iterable, initial)
|
|
232
233
|
|
|
233
234
|
|
|
235
|
+
def zip(
|
|
236
|
+
iterable: Iterable | AsyncIterable,
|
|
237
|
+
/,
|
|
238
|
+
*iterables: Iterable | AsyncIterable,
|
|
239
|
+
):
|
|
240
|
+
if isinstance(iterable, AsyncIterable) or any(isinstance(i, AsyncIterable) for i in iterables):
|
|
241
|
+
return async_zip(iterable, *iterables)
|
|
242
|
+
return _zip(iterable, *iterables)
|
|
243
|
+
|
|
244
|
+
|
|
234
245
|
@overload
|
|
235
246
|
def chunked[T](
|
|
236
247
|
iterable: Iterable[T],
|
|
@@ -757,3 +768,111 @@ def with_iter_next[T](
|
|
|
757
768
|
except StopIteration:
|
|
758
769
|
pass
|
|
759
770
|
|
|
771
|
+
|
|
772
|
+
@overload
|
|
773
|
+
def context[T](
|
|
774
|
+
func: Callable[..., T],
|
|
775
|
+
*ctxs: ContextManager,
|
|
776
|
+
async_: Literal[False] = False,
|
|
777
|
+
) -> T:
|
|
778
|
+
...
|
|
779
|
+
@overload
|
|
780
|
+
def context[T](
|
|
781
|
+
func: Callable[..., T] | Callable[..., Awaitable[T]],
|
|
782
|
+
*ctxs: ContextManager | AsyncContextManager,
|
|
783
|
+
async_: Literal[True],
|
|
784
|
+
) -> Coroutine[Any, Any, T]:
|
|
785
|
+
...
|
|
786
|
+
def context[T](
|
|
787
|
+
func: Callable[..., T] | Callable[..., Awaitable[T]],
|
|
788
|
+
*ctxs: ContextManager | AsyncContextManager,
|
|
789
|
+
async_: Literal[False, True] = False,
|
|
790
|
+
) -> T | Coroutine[Any, Any, T]:
|
|
791
|
+
if async_:
|
|
792
|
+
async def call():
|
|
793
|
+
args: list = []
|
|
794
|
+
add_arg = args.append
|
|
795
|
+
with ExitStack() as stack:
|
|
796
|
+
async with AsyncExitStack() as async_stack:
|
|
797
|
+
enter = stack.enter_context
|
|
798
|
+
async_enter = async_stack.enter_async_context
|
|
799
|
+
for ctx in ctxs:
|
|
800
|
+
if isinstance(ctx, AsyncContextManager):
|
|
801
|
+
add_arg(await async_enter(ctx))
|
|
802
|
+
else:
|
|
803
|
+
add_arg(enter(ctx))
|
|
804
|
+
ret = func(*args)
|
|
805
|
+
if isawaitable(ret):
|
|
806
|
+
ret = await ret
|
|
807
|
+
return ret
|
|
808
|
+
return call()
|
|
809
|
+
else:
|
|
810
|
+
with ExitStack() as stack:
|
|
811
|
+
return func(*map(stack.enter_context, ctxs)) # type: ignore
|
|
812
|
+
|
|
813
|
+
|
|
814
|
+
@overload
|
|
815
|
+
def backgroud_loop(
|
|
816
|
+
call: None | Callable = None,
|
|
817
|
+
/,
|
|
818
|
+
interval: int | float = 0.05,
|
|
819
|
+
*,
|
|
820
|
+
async_: Literal[False] = False,
|
|
821
|
+
) -> ContextManager:
|
|
822
|
+
...
|
|
823
|
+
@overload
|
|
824
|
+
def backgroud_loop(
|
|
825
|
+
call: None | Callable = None,
|
|
826
|
+
/,
|
|
827
|
+
interval: int | float = 0.05,
|
|
828
|
+
*,
|
|
829
|
+
async_: Literal[True],
|
|
830
|
+
) -> AsyncContextManager:
|
|
831
|
+
...
|
|
832
|
+
def backgroud_loop(
|
|
833
|
+
call: None | Callable = None,
|
|
834
|
+
/,
|
|
835
|
+
interval: int | float = 0.05,
|
|
836
|
+
*,
|
|
837
|
+
async_: Literal[False, True] = False,
|
|
838
|
+
) -> ContextManager | AsyncContextManager:
|
|
839
|
+
use_default_call = not callable(call)
|
|
840
|
+
if use_default_call:
|
|
841
|
+
start = time()
|
|
842
|
+
def call():
|
|
843
|
+
print(f"\r\x1b[K{format_time(time() - start)}", end="")
|
|
844
|
+
def run():
|
|
845
|
+
while running:
|
|
846
|
+
try:
|
|
847
|
+
yield call
|
|
848
|
+
except Exception:
|
|
849
|
+
pass
|
|
850
|
+
if interval > 0:
|
|
851
|
+
if async_:
|
|
852
|
+
yield async_sleep(interval)
|
|
853
|
+
else:
|
|
854
|
+
sleep(interval)
|
|
855
|
+
running = True
|
|
856
|
+
if async_:
|
|
857
|
+
async def actx():
|
|
858
|
+
nonlocal running
|
|
859
|
+
try:
|
|
860
|
+
task = create_task(run())
|
|
861
|
+
yield task
|
|
862
|
+
finally:
|
|
863
|
+
running = False
|
|
864
|
+
task.cancel()
|
|
865
|
+
if use_default_call:
|
|
866
|
+
print("\r\x1b[K", end="")
|
|
867
|
+
return asynccontextmanager(actx)()
|
|
868
|
+
else:
|
|
869
|
+
def ctx():
|
|
870
|
+
nonlocal running
|
|
871
|
+
try:
|
|
872
|
+
yield start_new_thread(run, ())
|
|
873
|
+
finally:
|
|
874
|
+
running = False
|
|
875
|
+
if use_default_call:
|
|
876
|
+
print("\r\x1b[K", end="")
|
|
877
|
+
return contextmanager(ctx)()
|
|
878
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-iterutils
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.5
|
|
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: Topic :: Software Development
|
|
|
21
21
|
Classifier: Topic :: Software Development :: Libraries
|
|
22
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
23
23
|
Requires-Dist: python-asynctools (>=0.0.10)
|
|
24
|
+
Requires-Dist: python-texttools (>=0.0.3)
|
|
24
25
|
Requires-Dist: python-undefined (>=0.0.3)
|
|
25
26
|
Project-URL: Repository, https://github.com/ChenyangGao/web-mount-packs/tree/main/python-module/python-iterutils
|
|
26
27
|
Description-Content-Type: text/markdown
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
2
|
+
iterutils/__init__.py,sha256=VRL_byJ8rSDBFDYPZFnxmG7AzDJ7EXC_i1AjYi_9RZM,26174
|
|
3
|
+
iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
|
+
python_iterutils-0.1.5.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
|
|
5
|
+
python_iterutils-0.1.5.dist-info/METADATA,sha256=tLN1tAcz_WipgczszAbxMcKFImyyiBehvVnjwY_8_sk,1426
|
|
6
|
+
python_iterutils-0.1.5.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
|
|
7
|
+
python_iterutils-0.1.5.dist-info/RECORD,,
|
|
@@ -1,7 +0,0 @@
|
|
|
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,,
|
|
File without changes
|
|
File without changes
|