python-iterutils 0.1.4__tar.gz → 0.1.6__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.4
3
+ Version: 0.1.6
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
@@ -2,12 +2,13 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 1, 4)
5
+ __version__ = (0, 1, 6)
6
6
  __all__ = [
7
7
  "Return", "Yield", "YieldFrom", "iterable", "async_iterable", "foreach", "async_foreach",
8
8
  "through", "async_through", "flatten", "async_flatten", "map", "filter", "reduce", "zip",
9
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",
10
+ "cut_iter", "run_gen_step", "run_gen_step_iter", "as_gen_step", "bfs_gen", "with_iter_next",
11
+ "backgroud_loop",
11
12
  ]
12
13
 
13
14
  from abc import ABC, abstractmethod
@@ -15,10 +16,10 @@ from asyncio import create_task, sleep as async_sleep, to_thread
15
16
  from builtins import map as _map, filter as _filter, zip as _zip
16
17
  from collections import deque
17
18
  from collections.abc import (
18
- AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable, Generator,
19
+ AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable, Coroutine, Generator,
19
20
  Iterable, Iterator, MutableSet, Sequence,
20
21
  )
21
- from contextlib import asynccontextmanager, contextmanager
22
+ from contextlib import asynccontextmanager, contextmanager, ExitStack, AsyncExitStack
22
23
  from dataclasses import dataclass
23
24
  from itertools import batched, pairwise
24
25
  from inspect import isawaitable, iscoroutinefunction
@@ -29,6 +30,7 @@ from typing import overload, Any, AsyncContextManager, ContextManager, Literal
29
30
  from asynctools import (
30
31
  async_filter, async_map, async_reduce, async_zip, async_batched, ensure_async, ensure_aiter,
31
32
  )
33
+ from decotools import optional
32
34
  from texttools import format_time
33
35
  from undefined import undefined, Undefined
34
36
 
@@ -681,6 +683,21 @@ def run_gen_step_iter(
681
683
  return process()
682
684
 
683
685
 
686
+ @optional
687
+ def as_gen_step(
688
+ func: Callable,
689
+ /,
690
+ async_: bool = False,
691
+ iter: bool = False,
692
+ ) -> Callable:
693
+ def wrapper(*args, **kwds):
694
+ if iter:
695
+ return run_gen_step_iter(func(*args, **kwds), async_=async_) # type: ignore
696
+ else:
697
+ return run_gen_step(func(*args, **kwds), async_=async_)
698
+ return wrapper
699
+
700
+
684
701
  @overload
685
702
  def bfs_gen[T](
686
703
  initial: T,
@@ -769,6 +786,48 @@ def with_iter_next[T](
769
786
  pass
770
787
 
771
788
 
789
+ @overload
790
+ def context[T](
791
+ func: Callable[..., T],
792
+ *ctxs: ContextManager,
793
+ async_: Literal[False] = False,
794
+ ) -> T:
795
+ ...
796
+ @overload
797
+ def context[T](
798
+ func: Callable[..., T] | Callable[..., Awaitable[T]],
799
+ *ctxs: ContextManager | AsyncContextManager,
800
+ async_: Literal[True],
801
+ ) -> Coroutine[Any, Any, T]:
802
+ ...
803
+ def context[T](
804
+ func: Callable[..., T] | Callable[..., Awaitable[T]],
805
+ *ctxs: ContextManager | AsyncContextManager,
806
+ async_: Literal[False, True] = False,
807
+ ) -> T | Coroutine[Any, Any, T]:
808
+ if async_:
809
+ async def call():
810
+ args: list = []
811
+ add_arg = args.append
812
+ with ExitStack() as stack:
813
+ async with AsyncExitStack() as async_stack:
814
+ enter = stack.enter_context
815
+ async_enter = async_stack.enter_async_context
816
+ for ctx in ctxs:
817
+ if isinstance(ctx, AsyncContextManager):
818
+ add_arg(await async_enter(ctx))
819
+ else:
820
+ add_arg(enter(ctx))
821
+ ret = func(*args)
822
+ if isawaitable(ret):
823
+ ret = await ret
824
+ return ret
825
+ return call()
826
+ else:
827
+ with ExitStack() as stack:
828
+ return func(*map(stack.enter_context, ctxs)) # type: ignore
829
+
830
+
772
831
  @overload
773
832
  def backgroud_loop(
774
833
  call: None | Callable = None,
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "python-iterutils"
3
- version = "0.1.4"
3
+ version = "0.1.6"
4
4
  description = "Python another itertools."
5
5
  authors = ["ChenyangGao <wosiwujm@gmail.com>"]
6
6
  license = "MIT"