python-iterutils 0.1.8__tar.gz → 0.1.10__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.
- {python_iterutils-0.1.8 → python_iterutils-0.1.10}/PKG-INFO +2 -2
- {python_iterutils-0.1.8 → python_iterutils-0.1.10}/iterutils/__init__.py +196 -133
- {python_iterutils-0.1.8 → python_iterutils-0.1.10}/pyproject.toml +2 -2
- {python_iterutils-0.1.8 → python_iterutils-0.1.10}/LICENSE +0 -0
- {python_iterutils-0.1.8 → python_iterutils-0.1.10}/iterutils/py.typed +0 -0
- {python_iterutils-0.1.8 → python_iterutils-0.1.10}/readme.md +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: python-iterutils
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.10
|
|
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.
|
|
23
|
+
Requires-Dist: python-asynctools (>=0.1.2)
|
|
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)
|
|
@@ -2,13 +2,14 @@
|
|
|
2
2
|
# encoding: utf-8
|
|
3
3
|
|
|
4
4
|
__author__ = "ChenyangGao <https://chenyanggao.github.io>"
|
|
5
|
-
__version__ = (0, 1,
|
|
5
|
+
__version__ = (0, 1, 10)
|
|
6
6
|
__all__ = [
|
|
7
7
|
"Return", "Yield", "YieldFrom", "iterable", "async_iterable", "foreach", "async_foreach",
|
|
8
8
|
"through", "async_through", "flatten", "async_flatten", "collect", "async_collect",
|
|
9
9
|
"group_collect", "async_group_collect", "map", "filter", "reduce", "zip", "chunked",
|
|
10
10
|
"iter_unique", "async_iter_unique", "wrap_iter", "wrap_aiter", "acc_step", "cut_iter",
|
|
11
|
-
"
|
|
11
|
+
"iter_gen_step", "iter_gen_step_async", "run_gen_step", "run_gen_step_iter",
|
|
12
|
+
"as_gen_step", "bfs_gen", "with_iter_next", "backgroud_loop",
|
|
12
13
|
]
|
|
13
14
|
|
|
14
15
|
from abc import ABC, abstractmethod
|
|
@@ -52,6 +53,12 @@ class YieldBase(ABC):
|
|
|
52
53
|
...
|
|
53
54
|
|
|
54
55
|
|
|
56
|
+
class Reraised(BaseException):
|
|
57
|
+
|
|
58
|
+
def __init__(self, exc: BaseException, /):
|
|
59
|
+
self.exception = exc
|
|
60
|
+
|
|
61
|
+
|
|
55
62
|
class Return(YieldBase):
|
|
56
63
|
yield_type = 0
|
|
57
64
|
|
|
@@ -636,110 +643,163 @@ def _get_async(back: int = 2) -> bool:
|
|
|
636
643
|
return False
|
|
637
644
|
|
|
638
645
|
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
async_: None | bool = None,
|
|
646
|
+
@overload
|
|
647
|
+
def call_as_async[**Args, T: Coroutine](
|
|
648
|
+
func: Callable[Args, T], /,
|
|
643
649
|
threaded: bool = False,
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
650
|
+
) -> Callable[Args, T]:
|
|
651
|
+
...
|
|
652
|
+
@overload
|
|
653
|
+
def call_as_async[**Args, T](
|
|
654
|
+
func: Callable[Args, T], /,
|
|
655
|
+
threaded: bool = False,
|
|
656
|
+
) -> Callable[Args, Coroutine[Any, Any, T]]:
|
|
657
|
+
...
|
|
658
|
+
def call_as_async[**Args, T](
|
|
659
|
+
func: Callable[Args, T],
|
|
660
|
+
/,
|
|
661
|
+
threaded: bool = False,
|
|
662
|
+
) -> Callable[Args, T] | Callable[Args, Coroutine[Any, Any, T]]:
|
|
663
|
+
if iscoroutinefunction(func):
|
|
664
|
+
return func
|
|
665
|
+
def wraps(*args, **kwds):
|
|
666
|
+
try:
|
|
667
|
+
return func(*args, **kwds)
|
|
668
|
+
except (StopIteration, StopAsyncIteration) as e:
|
|
669
|
+
raise Reraised(e) from e
|
|
670
|
+
if threaded:
|
|
671
|
+
async def wrapper(*args, **kwds):
|
|
672
|
+
return await to_thread(wraps, *args, **kwds)
|
|
673
|
+
else:
|
|
674
|
+
async def wrapper(*args, **kwds):
|
|
675
|
+
return wraps(*args, **kwds)
|
|
676
|
+
return wrapper
|
|
677
|
+
|
|
678
|
+
|
|
679
|
+
def iter_gen_step(
|
|
680
|
+
gen_step: Generator | Callable[[], Generator],
|
|
681
|
+
):
|
|
648
682
|
if callable(gen_step):
|
|
649
683
|
gen = gen_step()
|
|
650
|
-
close = gen.close
|
|
651
684
|
else:
|
|
652
685
|
gen = gen_step
|
|
653
|
-
|
|
654
|
-
send = gen.send
|
|
686
|
+
send = gen.send
|
|
655
687
|
throw = gen.throw
|
|
656
|
-
|
|
657
|
-
|
|
688
|
+
close = gen.close
|
|
689
|
+
try:
|
|
690
|
+
value = send(None)
|
|
691
|
+
while True:
|
|
692
|
+
if isinstance(value, YieldBase):
|
|
693
|
+
raise StopIteration(value)
|
|
658
694
|
try:
|
|
659
|
-
if
|
|
660
|
-
value = await to_thread(send, None)
|
|
661
|
-
else:
|
|
662
|
-
value = send(None)
|
|
663
|
-
while True:
|
|
664
|
-
if isinstance(value, YieldBase):
|
|
665
|
-
raise StopIteration(value)
|
|
666
|
-
try:
|
|
667
|
-
if callable(value):
|
|
668
|
-
value = value()
|
|
669
|
-
if isawaitable(value):
|
|
670
|
-
value = await value
|
|
671
|
-
except BaseException as e:
|
|
672
|
-
if threaded:
|
|
673
|
-
value = await to_thread(throw, e)
|
|
674
|
-
else:
|
|
675
|
-
value = throw(e)
|
|
676
|
-
else:
|
|
677
|
-
if threaded:
|
|
678
|
-
value = await to_thread(send, value)
|
|
679
|
-
else:
|
|
680
|
-
value = send(value)
|
|
681
|
-
except StopIteration as e:
|
|
682
|
-
value = e.value
|
|
683
|
-
identity = False
|
|
684
|
-
try_call_me = True
|
|
685
|
-
if isinstance(value, YieldBase):
|
|
686
|
-
identity = value.identity
|
|
687
|
-
try_call_me = value.try_call_me
|
|
688
|
-
value = value.value
|
|
689
|
-
if callable(value) and try_call_me:
|
|
695
|
+
if callable(value):
|
|
690
696
|
value = value()
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
except TypeError:
|
|
707
|
-
for val in iter(iterable):
|
|
708
|
-
if isawaitable(val):
|
|
709
|
-
val = await val
|
|
710
|
-
yield val
|
|
711
|
-
else:
|
|
712
|
-
async for val in iterable:
|
|
713
|
-
yield val
|
|
714
|
-
result = wrap(result)
|
|
715
|
-
return result
|
|
716
|
-
else:
|
|
717
|
-
try:
|
|
718
|
-
value = send(None)
|
|
719
|
-
while True:
|
|
720
|
-
if isinstance(value, YieldBase):
|
|
721
|
-
raise StopIteration(value)
|
|
697
|
+
except BaseException as e:
|
|
698
|
+
value = throw(e)
|
|
699
|
+
else:
|
|
700
|
+
value = send(value)
|
|
701
|
+
yield value
|
|
702
|
+
except StopIteration as e:
|
|
703
|
+
value = e.value
|
|
704
|
+
try_call_me = True
|
|
705
|
+
if isinstance(value, YieldBase):
|
|
706
|
+
try_call_me = value.try_call_me
|
|
707
|
+
value = value.value
|
|
708
|
+
if callable(value) and try_call_me:
|
|
709
|
+
try:
|
|
710
|
+
value = value()
|
|
711
|
+
except BaseException as e:
|
|
722
712
|
try:
|
|
723
|
-
if callable(value):
|
|
724
|
-
value = value()
|
|
725
|
-
except BaseException as e:
|
|
726
713
|
value = throw(e)
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
714
|
+
except BaseException as e:
|
|
715
|
+
raise Reraised(e) from e
|
|
716
|
+
yield value
|
|
717
|
+
except BaseException as e:
|
|
718
|
+
raise Reraised(e) from e
|
|
719
|
+
finally:
|
|
720
|
+
close()
|
|
721
|
+
|
|
722
|
+
|
|
723
|
+
async def iter_gen_step_async(
|
|
724
|
+
gen_step: Generator | Callable[[], Generator],
|
|
725
|
+
threaded: bool = False,
|
|
726
|
+
):
|
|
727
|
+
if callable(gen_step):
|
|
728
|
+
gen = gen_step()
|
|
729
|
+
else:
|
|
730
|
+
gen = gen_step
|
|
731
|
+
send: Callable = call_as_async(gen.send, threaded=threaded)
|
|
732
|
+
throw: Callable = call_as_async(gen.throw, threaded=threaded)
|
|
733
|
+
close: Callable = call_as_async(gen.close, threaded=threaded)
|
|
734
|
+
try:
|
|
735
|
+
value = await send(None)
|
|
736
|
+
while True:
|
|
737
|
+
if isinstance(value, YieldBase):
|
|
738
|
+
raise StopIteration(value)
|
|
739
|
+
try:
|
|
740
|
+
if callable(value):
|
|
741
|
+
value = await call_as_async(value, threaded=threaded)()
|
|
742
|
+
if isawaitable(value):
|
|
743
|
+
value = await value
|
|
744
|
+
except BaseException as e:
|
|
745
|
+
if isinstance(e, Reraised):
|
|
746
|
+
e = e.exception
|
|
747
|
+
value = await throw(e)
|
|
748
|
+
else:
|
|
749
|
+
value = await send(value)
|
|
750
|
+
yield value
|
|
751
|
+
except BaseException as e:
|
|
752
|
+
if isinstance(e, Reraised):
|
|
753
|
+
e = e.exception
|
|
754
|
+
if isinstance(e, StopIteration):
|
|
730
755
|
value = e.value
|
|
756
|
+
identity = False
|
|
731
757
|
try_call_me = True
|
|
732
758
|
if isinstance(value, YieldBase):
|
|
759
|
+
identity = value.identity
|
|
733
760
|
try_call_me = value.try_call_me
|
|
734
761
|
value = value.value
|
|
735
|
-
|
|
736
|
-
value
|
|
737
|
-
|
|
738
|
-
|
|
762
|
+
try:
|
|
763
|
+
if callable(value) and try_call_me:
|
|
764
|
+
value = await call_as_async(value, threaded=threaded)()
|
|
765
|
+
if not identity and isawaitable(value):
|
|
766
|
+
value = await value
|
|
767
|
+
except BaseException as e:
|
|
768
|
+
try:
|
|
769
|
+
value = await throw(e)
|
|
770
|
+
except BaseException as e:
|
|
771
|
+
raise Reraised(e) from e
|
|
772
|
+
yield value
|
|
773
|
+
else:
|
|
774
|
+
raise
|
|
775
|
+
finally:
|
|
776
|
+
await close()
|
|
777
|
+
|
|
778
|
+
|
|
779
|
+
def run_gen_step[T](
|
|
780
|
+
gen_step: Generator | Callable[[], Generator],
|
|
781
|
+
*,
|
|
782
|
+
async_: None | bool = None,
|
|
783
|
+
threaded: bool = False,
|
|
784
|
+
):
|
|
785
|
+
if async_ is None:
|
|
786
|
+
async_ = _get_async()
|
|
787
|
+
if async_:
|
|
788
|
+
async def process():
|
|
789
|
+
try:
|
|
790
|
+
async for value in iter_gen_step_async(gen_step, threaded=threaded):
|
|
791
|
+
pass
|
|
792
|
+
return value
|
|
793
|
+
except Reraised as e:
|
|
794
|
+
raise e.exception
|
|
795
|
+
return process()
|
|
796
|
+
else:
|
|
797
|
+
try:
|
|
798
|
+
for value in iter_gen_step(gen_step):
|
|
799
|
+
pass
|
|
739
800
|
return value
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
close()
|
|
801
|
+
except Reraised as e:
|
|
802
|
+
raise e.exception
|
|
743
803
|
|
|
744
804
|
|
|
745
805
|
@overload
|
|
@@ -776,33 +836,32 @@ def run_gen_step_iter(
|
|
|
776
836
|
async_ = _get_async()
|
|
777
837
|
if callable(gen_step):
|
|
778
838
|
gen = gen_step()
|
|
779
|
-
close = gen.close
|
|
780
839
|
else:
|
|
781
840
|
gen = gen_step
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
841
|
+
send: Callable = gen.send
|
|
842
|
+
throw: Callable = gen.throw
|
|
843
|
+
close: Callable = gen.close
|
|
785
844
|
if async_:
|
|
845
|
+
send = call_as_async(send, threaded=threaded)
|
|
846
|
+
throw = call_as_async(throw, threaded=threaded)
|
|
847
|
+
close = call_as_async(close, threaded=threaded)
|
|
786
848
|
async def process():
|
|
787
849
|
async def extract(value):
|
|
788
850
|
identity = False
|
|
789
851
|
try_call_me = True
|
|
790
852
|
yield_type = -1
|
|
791
853
|
if isinstance(value, YieldBase):
|
|
792
|
-
identity
|
|
854
|
+
identity = value.identity
|
|
793
855
|
try_call_me = value.try_call_me
|
|
794
|
-
yield_type
|
|
795
|
-
value
|
|
856
|
+
yield_type = value.yield_type
|
|
857
|
+
value = value.value
|
|
796
858
|
if try_call_me and callable(value):
|
|
797
|
-
value = value()
|
|
859
|
+
value = await call_as_async(value, threaded=threaded)()
|
|
798
860
|
if not identity and isawaitable(value):
|
|
799
861
|
value = await value
|
|
800
862
|
return yield_type, value
|
|
801
863
|
try:
|
|
802
|
-
|
|
803
|
-
value = await to_thread(send, None)
|
|
804
|
-
else:
|
|
805
|
-
value = send(None)
|
|
864
|
+
value = await send(None)
|
|
806
865
|
while True:
|
|
807
866
|
try:
|
|
808
867
|
yield_type, value = await extract(value)
|
|
@@ -813,29 +872,31 @@ def run_gen_step_iter(
|
|
|
813
872
|
async for val in ensure_aiter(value, threaded=threaded):
|
|
814
873
|
yield val
|
|
815
874
|
except BaseException as e:
|
|
816
|
-
if
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
value = throw(e)
|
|
875
|
+
if isinstance(e, Reraised):
|
|
876
|
+
e = e.exception
|
|
877
|
+
value = await throw(e)
|
|
820
878
|
else:
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
879
|
+
value = await send(value)
|
|
880
|
+
except BaseException as e:
|
|
881
|
+
if isinstance(e, Reraised):
|
|
882
|
+
e = e.exception
|
|
883
|
+
if isinstance(e, StopIteration):
|
|
884
|
+
try:
|
|
885
|
+
yield_type, value = await extract(e.value)
|
|
886
|
+
match yield_type:
|
|
887
|
+
case 1:
|
|
888
|
+
yield value
|
|
889
|
+
case 2:
|
|
890
|
+
async for val in ensure_aiter(value, threaded=threaded):
|
|
891
|
+
yield val
|
|
892
|
+
except BaseException as e:
|
|
893
|
+
if isinstance(e, Reraised):
|
|
894
|
+
e = e.exception
|
|
895
|
+
await throw(e)
|
|
896
|
+
else:
|
|
897
|
+
raise
|
|
833
898
|
finally:
|
|
834
|
-
|
|
835
|
-
if threaded:
|
|
836
|
-
await to_thread(close)
|
|
837
|
-
else:
|
|
838
|
-
close()
|
|
899
|
+
await close()
|
|
839
900
|
else:
|
|
840
901
|
def process():
|
|
841
902
|
def extract(value, /):
|
|
@@ -865,17 +926,19 @@ def run_gen_step_iter(
|
|
|
865
926
|
else:
|
|
866
927
|
value = send(value)
|
|
867
928
|
except StopIteration as e:
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
874
|
-
|
|
875
|
-
|
|
929
|
+
try:
|
|
930
|
+
yield_type, value = extract(e.value)
|
|
931
|
+
match yield_type:
|
|
932
|
+
case 1:
|
|
933
|
+
yield value
|
|
934
|
+
case 2:
|
|
935
|
+
yield from value
|
|
936
|
+
case _:
|
|
937
|
+
return value
|
|
938
|
+
except BaseException as e:
|
|
939
|
+
throw(e)
|
|
876
940
|
finally:
|
|
877
|
-
|
|
878
|
-
close()
|
|
941
|
+
close()
|
|
879
942
|
return process()
|
|
880
943
|
|
|
881
944
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "python-iterutils"
|
|
3
|
-
version = "0.1.
|
|
3
|
+
version = "0.1.10"
|
|
4
4
|
description = "Python another itertools."
|
|
5
5
|
authors = ["ChenyangGao <wosiwujm@gmail.com>"]
|
|
6
6
|
license = "MIT"
|
|
@@ -27,7 +27,7 @@ include = [
|
|
|
27
27
|
|
|
28
28
|
[tool.poetry.dependencies]
|
|
29
29
|
python = "^3.12"
|
|
30
|
-
python-asynctools = ">=0.
|
|
30
|
+
python-asynctools = ">=0.1.2"
|
|
31
31
|
python-decotools = ">=0.0.2"
|
|
32
32
|
python-texttools = ">=0.0.3"
|
|
33
33
|
python-undefined = ">=0.0.3"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|