python-iterutils 0.2__py3-none-any.whl → 0.2.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,14 +2,16 @@
2
2
  # encoding: utf-8
3
3
 
4
4
  __author__ = "ChenyangGao <https://chenyanggao.github.io>"
5
- __version__ = (0, 2)
5
+ __version__ = (0, 2, 1)
6
6
  __all__ = [
7
- "Return", "Yield", "YieldFrom", "iterable", "async_iterable", "foreach", "async_foreach",
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
- "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",
7
+ "Return", "Yield", "YieldFrom", "iterable", "async_iterable",
8
+ "foreach", "async_foreach", "through", "async_through", "flatten",
9
+ "async_flatten", "collect", "async_collect", "group_collect",
10
+ "async_group_collect", "map", "filter", "reduce", "zip", "chunked",
11
+ "iter_unique", "async_iter_unique", "wrap_iter", "wrap_aiter",
12
+ "acc_step", "cut_iter", "iter_gen_step", "iter_gen_step_async",
13
+ "run_gen_step", "run_gen_step_iter", "as_gen_step", "bfs_gen",
14
+ "with_iter_next", "backgroud_loop",
13
15
  ]
14
16
 
15
17
  from abc import ABC, abstractmethod
@@ -17,11 +19,14 @@ from asyncio import create_task, sleep as async_sleep, to_thread
17
19
  from builtins import map as _map, filter as _filter, zip as _zip
18
20
  from collections import defaultdict, deque
19
21
  from collections.abc import (
20
- AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable, Collection, Container,
21
- Coroutine, Generator, Iterable, Iterator, Mapping, MutableMapping, MutableSet,
22
- MutableSequence, Sequence, ValuesView,
22
+ AsyncIterable, AsyncIterator, Awaitable, Buffer, Callable,
23
+ Collection, Container, Coroutine, Generator, Iterable, Iterator,
24
+ Mapping, MutableMapping, MutableSet, MutableSequence, Sequence,
25
+ ValuesView,
26
+ )
27
+ from contextlib import (
28
+ asynccontextmanager, contextmanager, ExitStack, AsyncExitStack,
23
29
  )
24
- from contextlib import asynccontextmanager, contextmanager, ExitStack, AsyncExitStack
25
30
  from copy import copy
26
31
  from dataclasses import dataclass
27
32
  from itertools import batched, pairwise
@@ -30,11 +35,14 @@ from sys import _getframe
30
35
  from _thread import start_new_thread
31
36
  from time import sleep, time
32
37
  from types import FrameType
33
- from typing import cast, overload, Any, AsyncContextManager, ContextManager, Literal, Protocol
38
+ from typing import (
39
+ cast, overload, Any, AsyncContextManager, ContextManager, Literal,
40
+ Protocol,
41
+ )
34
42
 
35
43
  from asynctools import (
36
- async_filter, async_map, async_reduce, async_zip, async_batched, ensure_async, ensure_aiter,
37
- collect as async_collect,
44
+ async_filter, async_map, async_reduce, async_zip, async_batched,
45
+ ensure_async, ensure_aiter, collect as async_collect,
38
46
  )
39
47
  from decotools import optional
40
48
  from texttools import format_time
@@ -42,22 +50,27 @@ from undefined import undefined
42
50
 
43
51
 
44
52
  class SupportsBool(Protocol):
53
+ """
54
+ """
45
55
  def __bool__(self, /) -> bool: ...
46
56
 
47
57
 
48
58
  class Reraised(BaseException):
49
-
59
+ """
60
+ """
50
61
  def __init__(self, exc: BaseException, /):
51
62
  if isinstance(exc, Reraised):
52
63
  exc = exc.exception
53
64
  self.exception: BaseException = exc
54
65
 
55
66
 
56
- @dataclass(slots=True, frozen=True)
67
+ @dataclass(slots=True, frozen=True, unsafe_hash=True)
57
68
  class YieldBase(ABC):
69
+ """
70
+ """
58
71
  value: Any
59
- may_await: None | bool = True
60
- may_call: None | bool = True
72
+ may_await: None | bool | Literal[1] = False
73
+ may_call: None | bool | Literal[1] = None
61
74
 
62
75
  @property
63
76
  @abstractmethod
@@ -66,18 +79,29 @@ class YieldBase(ABC):
66
79
 
67
80
 
68
81
  class Return(YieldBase):
82
+ """
83
+ """
84
+ __slots__ = ()
69
85
  yield_type = 0
70
86
 
71
87
 
72
88
  class Yield(YieldBase):
89
+ """
90
+ """
91
+ __slots__ = ()
73
92
  yield_type = 1
74
93
 
75
94
 
76
95
  class YieldFrom(YieldBase):
96
+ """
97
+ """
98
+ __slots__ = ()
77
99
  yield_type = 2
78
100
 
79
101
 
80
102
  def iterable(iterable, /) -> bool:
103
+ """
104
+ """
81
105
  try:
82
106
  return isinstance(iter(iterable), Iterable)
83
107
  except TypeError:
@@ -85,6 +109,8 @@ def iterable(iterable, /) -> bool:
85
109
 
86
110
 
87
111
  def async_iterable(iterable, /) -> bool:
112
+ """
113
+ """
88
114
  try:
89
115
  return isinstance(iter(iterable), AsyncIterable)
90
116
  except TypeError:
@@ -97,6 +123,8 @@ def foreach(
97
123
  /,
98
124
  *iterables: Iterable | AsyncIterable,
99
125
  ):
126
+ """
127
+ """
100
128
  if not (isinstance(iterable, Iterable) and all(isinstance(it, Iterable) for it in iterables)):
101
129
  return async_foreach(value, iterable, *iterables)
102
130
  if iterables:
@@ -114,6 +142,8 @@ async def async_foreach(
114
142
  *iterables: Iterable | AsyncIterable,
115
143
  threaded: bool = False,
116
144
  ):
145
+ """
146
+ """
117
147
  value = ensure_async(value, threaded=threaded)
118
148
  if iterables:
119
149
  async for args in async_zip(iterable, *iterables, threaded=threaded):
@@ -128,6 +158,8 @@ def through(
128
158
  /,
129
159
  take_while: None | Callable = None,
130
160
  ):
161
+ """
162
+ """
131
163
  if not isinstance(iterable, Iterable):
132
164
  return async_through(iterable, take_while)
133
165
  if take_while is None:
@@ -145,6 +177,8 @@ async def async_through(
145
177
  take_while: None | Callable = None,
146
178
  threaded: bool = False,
147
179
  ):
180
+ """
181
+ """
148
182
  iterable = ensure_aiter(iterable, threaded=threaded)
149
183
  if take_while is None:
150
184
  async for _ in iterable:
@@ -178,6 +212,8 @@ def flatten(
178
212
  /,
179
213
  exclude_types: type | tuple[type, ...] = (Buffer, str),
180
214
  ) -> Iterator | AsyncIterator:
215
+ """
216
+ """
181
217
  if not isinstance(iterable, Iterable):
182
218
  return async_flatten(iterable, exclude_types)
183
219
  def gen(iterable):
@@ -195,6 +231,8 @@ async def async_flatten(
195
231
  exclude_types: type | tuple[type, ...] = (Buffer, str),
196
232
  threaded: bool = False,
197
233
  ) -> AsyncIterator:
234
+ """
235
+ """
198
236
  async for e in ensure_aiter(iterable, threaded=threaded):
199
237
  if isinstance(e, (Iterable, AsyncIterable)) and not isinstance(e, exclude_types):
200
238
  async for e in async_flatten(e, exclude_types, threaded=threaded):
@@ -236,6 +274,8 @@ def collect(
236
274
  /,
237
275
  rettype: Callable[[Iterable], Collection] = list,
238
276
  ) -> Collection | Coroutine[Any, Any, Collection]:
277
+ """
278
+ """
239
279
  if not isinstance(iterable, Iterable):
240
280
  return async_collect(iterable, rettype)
241
281
  return rettype(iterable)
@@ -274,6 +314,8 @@ def group_collect[K, V, C: Container, M: MutableMapping](
274
314
  mapping: None | M = None,
275
315
  factory: None | C | Callable[[], C] = None,
276
316
  ) -> dict[K, C] | M | Coroutine[Any, Any, dict[K, C]] | Coroutine[Any, Any, M]:
317
+ """
318
+ """
277
319
  if not isinstance(iterable, Iterable):
278
320
  return async_group_collect(iterable, mapping, factory)
279
321
  if factory is None:
@@ -331,6 +373,8 @@ async def async_group_collect[K, V, C: Container, M: MutableMapping](
331
373
  factory: None | C | Callable[[], C] = None,
332
374
  threaded: bool = False,
333
375
  ) -> dict[K, C] | M:
376
+ """
377
+ """
334
378
  iterable = ensure_aiter(iterable, threaded=threaded)
335
379
  if factory is None:
336
380
  if isinstance(mapping, defaultdict):
@@ -370,7 +414,9 @@ def map(
370
414
  iterable: Iterable | AsyncIterable,
371
415
  /,
372
416
  *iterables: Iterable | AsyncIterable,
373
- ):
417
+ ):
418
+ """
419
+ """
374
420
  if (
375
421
  iscoroutinefunction(function) or
376
422
  isinstance(iterable, AsyncIterable) or
@@ -395,6 +441,8 @@ def filter(
395
441
  iterable: Iterable | AsyncIterable,
396
442
  /,
397
443
  ):
444
+ """
445
+ """
398
446
  if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
399
447
  return async_filter(function, iterable)
400
448
  return _filter(function, iterable)
@@ -406,6 +454,8 @@ def reduce(
406
454
  initial: Any = undefined,
407
455
  /,
408
456
  ):
457
+ """
458
+ """
409
459
  if iscoroutinefunction(function) or isinstance(iterable, AsyncIterable):
410
460
  return async_reduce(function, iterable, initial)
411
461
  from functools import reduce
@@ -419,6 +469,8 @@ def zip(
419
469
  /,
420
470
  *iterables: Iterable | AsyncIterable,
421
471
  ):
472
+ """
473
+ """
422
474
  if isinstance(iterable, AsyncIterable) or any(isinstance(i, AsyncIterable) for i in iterables):
423
475
  return async_zip(iterable, *iterables)
424
476
  return _zip(iterable, *iterables)
@@ -443,6 +495,8 @@ def chunked[T](
443
495
  n: int = 1,
444
496
  /,
445
497
  ) -> Iterator[Sequence[T]] | AsyncIterator[Sequence[T]]:
498
+ """
499
+ """
446
500
  if n < 0:
447
501
  n = 1
448
502
  if isinstance(iterable, Sequence):
@@ -474,6 +528,8 @@ def iter_unique[T](
474
528
  /,
475
529
  seen: None | MutableSet = None,
476
530
  ) -> Iterator[T] | AsyncIterator[T]:
531
+ """
532
+ """
477
533
  if not isinstance(iterable, Iterable):
478
534
  return async_iter_unique(iterable, seen)
479
535
  if seen is None:
@@ -493,6 +549,8 @@ async def async_iter_unique[T](
493
549
  seen: None | MutableSet = None,
494
550
  threaded: bool = False,
495
551
  ) -> AsyncIterator[T]:
552
+ """
553
+ """
496
554
  if seen is None:
497
555
  seen = set()
498
556
  add = seen.add
@@ -508,8 +566,6 @@ def wrap_iter[T](
508
566
  /,
509
567
  callprev: None | Callable[[T], Any] = None,
510
568
  callnext: None | Callable[[T], Any] = None,
511
- callenter: None | Callable[[Iterable[T]], Any] = None,
512
- callexit: None | Callable[[Iterable[T], None | BaseException], Any] = None,
513
569
  ) -> Iterator[T]:
514
570
  ...
515
571
  @overload
@@ -518,8 +574,6 @@ def wrap_iter[T](
518
574
  /,
519
575
  callprev: None | Callable[[T], Any] = None,
520
576
  callnext: None | Callable[[T], Any] = None,
521
- callenter: None | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
522
- callexit: None | Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] = None,
523
577
  ) -> AsyncIterator[T]:
524
578
  ...
525
579
  def wrap_iter[T](
@@ -527,47 +581,24 @@ def wrap_iter[T](
527
581
  /,
528
582
  callprev: None | Callable[[T], Any] = None,
529
583
  callnext: None | Callable[[T], Any] = None,
530
- callenter: None | Callable[[Iterable[T]], Any] | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
531
- callexit: ( None | Callable[[Iterable[T], None | BaseException], Any] |
532
- Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] ) = None,
533
584
  ) -> Iterator[T] | AsyncIterator[T]:
585
+ """
586
+ """
534
587
  if not isinstance(iterable, Iterable):
535
588
  return wrap_aiter(
536
589
  iterable,
537
590
  callprev=callprev,
538
591
  callnext=callnext,
539
- callenter=callenter, # type: ignore
540
- callexit=callexit, # type: ignore
541
592
  )
542
593
  if not callable(callprev):
543
594
  callprev = None
544
595
  if not callable(callnext):
545
596
  callnext = None
546
597
  def gen():
547
- try:
548
- if callable(callenter):
549
- callenter(iterable)
550
- for e in iterable:
551
- if callprev:
552
- try:
553
- callprev(e)
554
- except (StopIteration, GeneratorExit):
555
- break
556
- yield e
557
- if callnext:
558
- try:
559
- callnext(e)
560
- except (StopIteration, GeneratorExit):
561
- break
562
- except BaseException as e:
563
- if callable(callexit):
564
- if not callexit(iterable, e):
565
- raise
566
- else:
567
- raise
568
- finally:
569
- if callable(callexit):
570
- callexit(iterable, None)
598
+ for e in iterable:
599
+ callprev and callprev(e)
600
+ yield e
601
+ callnext and callnext(e)
571
602
  return gen()
572
603
 
573
604
 
@@ -576,34 +607,16 @@ async def wrap_aiter[T](
576
607
  /,
577
608
  callprev: None | Callable[[T], Any] = None,
578
609
  callnext: None | Callable[[T], Any] = None,
579
- callenter: None | Callable[[Iterable[T] | AsyncIterable[T]], Any] = None,
580
- callexit: None | Callable[[Iterable[T] | AsyncIterable[T], None | BaseException], Any] = None,
581
610
  threaded: bool = False,
582
611
  ) -> AsyncIterator[T]:
612
+ """
613
+ """
583
614
  callprev = ensure_async(callprev, threaded=threaded) if callable(callprev) else None
584
615
  callnext = ensure_async(callnext, threaded=threaded) if callable(callnext) else None
585
- try:
586
- async for e in ensure_aiter(iterable, threaded=threaded):
587
- if callprev:
588
- try:
589
- await callprev(e)
590
- except (StopAsyncIteration, GeneratorExit):
591
- break
592
- yield e
593
- if callnext:
594
- try:
595
- await callnext(e)
596
- except (StopAsyncIteration, GeneratorExit):
597
- break
598
- except BaseException as e:
599
- if callable(callexit):
600
- if not await ensure_async(callexit, threaded=threaded)(iterable, e):
601
- raise
602
- else:
603
- raise
604
- finally:
605
- if callable(callexit):
606
- await ensure_async(callexit, threaded=threaded)(iterable, None)
616
+ async for e in ensure_aiter(iterable, threaded=threaded):
617
+ callprev and await callprev(e)
618
+ yield e
619
+ callnext and await callnext(e)
607
620
 
608
621
 
609
622
  def acc_step(
@@ -611,6 +624,8 @@ def acc_step(
611
624
  stop: None | int = None,
612
625
  step: int = 1,
613
626
  ) -> Iterator[tuple[int, int, int]]:
627
+ """
628
+ """
614
629
  if stop is None:
615
630
  start, stop = 0, start
616
631
  for i in range(start + step, stop, step):
@@ -624,6 +639,8 @@ def cut_iter(
624
639
  stop: None | int = None,
625
640
  step: int = 1,
626
641
  ) -> Iterator[tuple[int, int]]:
642
+ """
643
+ """
627
644
  if stop is None:
628
645
  start, stop = 0, start
629
646
  for start in range(start + step, stop, step):
@@ -652,23 +669,25 @@ def _get_async(back: int = 2) -> bool:
652
669
  @overload
653
670
  def call_as_async[**Args, T: Coroutine](
654
671
  func: Callable[Args, T], /,
655
- may_await: None | bool = False,
672
+ may_await: bool | Literal[1] = False,
656
673
  threaded: bool = False,
657
674
  ) -> Callable[Args, T]:
658
675
  ...
659
676
  @overload
660
677
  def call_as_async[**Args, T](
661
678
  func: Callable[Args, T], /,
662
- may_await: None | bool = False,
679
+ may_await: bool | Literal[1] = False,
663
680
  threaded: bool = False,
664
681
  ) -> Callable[Args, Coroutine[Any, Any, T]]:
665
682
  ...
666
683
  def call_as_async[**Args, T](
667
684
  func: Callable[Args, T],
668
685
  /,
669
- may_await: None | bool = False,
686
+ may_await: bool | Literal[1] = False,
670
687
  threaded: bool = False,
671
688
  ) -> Callable[Args, T] | Callable[Args, Coroutine[Any, Any, T]]:
689
+ """
690
+ """
672
691
  if iscoroutinefunction(func):
673
692
  return func
674
693
  def wraps(*args, **kwds):
@@ -681,7 +700,7 @@ def call_as_async[**Args, T](
681
700
  value = await to_thread(wraps, *args, **kwds)
682
701
  else:
683
702
  value = wraps(*args, **kwds)
684
- if may_await is None or may_await and isawaitable(value):
703
+ if may_await is 1 or may_await and isawaitable(value):
685
704
  value = await value
686
705
  return value
687
706
  return wrapper
@@ -689,140 +708,131 @@ def call_as_async[**Args, T](
689
708
 
690
709
  def iter_gen_step(
691
710
  gen_step: Generator | Callable[[], Generator],
692
- simple: bool = False,
711
+ may_call: bool | Literal[1] = True,
693
712
  ):
694
- gen = gen_step() if callable(gen_step) else gen_step
695
- send = gen.send
696
- throw = gen.throw
697
- close = gen.close
713
+ """
714
+ """
715
+ if callable(gen_step):
716
+ gen_step = gen_step()
717
+ send = gen_step.send
718
+ throw = gen_step.throw
719
+ close = gen_step.close
698
720
  value: Any = None
699
- if simple:
700
- try:
701
- while True:
702
- yield (value := send(value))
703
- except StopIteration as e:
704
- yield e.value
705
- finally:
706
- close()
707
- else:
708
- try:
709
- while True:
710
- if isinstance(value, YieldBase):
711
- raise StopIteration(value)
712
- try:
713
- if callable(value):
714
- value = value()
715
- except BaseException as e:
716
- value = throw(e)
717
- else:
718
- value = send(value)
719
- yield value
720
- except StopIteration as e:
721
- may_call: None | bool = True
722
- value = e.value
721
+ try:
722
+ while True:
723
723
  if isinstance(value, YieldBase):
724
- may_call = value.may_call
725
- value = value.value
726
- if may_call is None or may_call and callable(value):
727
- try:
724
+ raise StopIteration(value)
725
+ try:
726
+ if may_call is 1 or may_call and callable(value):
728
727
  value = value()
729
- except BaseException as e:
730
- try:
731
- value = throw(e)
732
- except BaseException as e:
733
- raise Reraised(e) from e
728
+ except BaseException as e:
729
+ value = throw(e)
730
+ else:
731
+ value = send(value)
734
732
  yield value
735
- finally:
736
- close()
733
+ except StopIteration as e:
734
+ value = e.value
735
+ if isinstance(value, YieldBase):
736
+ maybe_callable = value.may_call
737
+ if maybe_callable is not None:
738
+ may_call = maybe_callable
739
+ value = value.value
740
+ if may_call is 1 or may_call and callable(value):
741
+ try:
742
+ value = value()
743
+ except BaseException as e:
744
+ try:
745
+ value = throw(e)
746
+ except BaseException as e:
747
+ raise Reraised(e) from e
748
+ yield value
749
+ finally:
750
+ close()
737
751
 
738
752
 
739
753
  async def iter_gen_step_async(
740
754
  gen_step: Generator | Callable[[], Generator],
755
+ may_await: bool | Literal[1] = True,
756
+ may_call: bool | Literal[1] = True,
741
757
  threaded: bool = False,
742
- simple: bool = False,
743
758
  ):
744
- gen = gen_step() if callable(gen_step) else gen_step
745
- send: Callable = gen.send
746
- throw: Callable = gen.throw
747
- close: Callable = call_as_async(gen.close, threaded=threaded)
759
+ """
760
+ """
761
+ if callable(gen_step):
762
+ gen_step = gen_step()
763
+ send: Callable = call_as_async(gen_step.send, threaded=threaded)
764
+ throw: Callable = call_as_async(gen_step.throw, threaded=threaded)
765
+ close: Callable = call_as_async(gen_step.close, threaded=threaded)
748
766
  value: Any = None
749
- if simple:
750
- send = call_as_async(send, may_await=None, threaded=threaded)
751
- throw = call_as_async(throw, may_await=None, threaded=threaded)
752
- try:
753
- while True:
754
- yield (value := await send(value))
755
- except BaseException as e:
756
- if isinstance(e, Reraised):
757
- e = e.exception
758
- if isinstance(e, StopIteration):
759
- yield e.value
767
+ try:
768
+ while True:
769
+ if isinstance(value, YieldBase):
770
+ raise StopIteration(value)
771
+ try:
772
+ if may_call is 1 or may_call and callable(value):
773
+ value = await call_as_async(
774
+ value, may_await=may_await, threaded=threaded)()
775
+ elif may_await is 1 or may_await and isawaitable(value):
776
+ value = await value
777
+ except BaseException as e:
778
+ if isinstance(e, Reraised):
779
+ e = e.exception
780
+ value = await throw(e)
760
781
  else:
761
- raise
762
- finally:
763
- await close()
764
- else:
765
- send = call_as_async(send, threaded=threaded)
766
- throw = call_as_async(throw, threaded=threaded)
767
- try:
768
- while True:
769
- if isinstance(value, YieldBase):
770
- raise StopIteration(value)
782
+ value = await send(value)
783
+ yield value
784
+ except BaseException as e:
785
+ if isinstance(e, Reraised):
786
+ e = e.exception
787
+ if isinstance(e, StopIteration):
788
+ value = e.value
789
+ if isinstance(value, YieldBase):
790
+ maybe_awaitable = value.may_await
791
+ if maybe_awaitable is not None:
792
+ may_await = maybe_awaitable
793
+ maybe_callable = value.may_call
794
+ if maybe_callable is not None:
795
+ may_call = maybe_callable
796
+ value = value.value
797
+ try:
798
+ if may_call is 1 or may_call and callable(value):
799
+ value = await call_as_async(
800
+ value, may_await=may_await, threaded=threaded)()
801
+ elif may_await is 1 or may_await and isawaitable(value):
802
+ value = await value
803
+ except BaseException as e:
771
804
  try:
772
- if callable(value):
773
- value = await call_as_async(
774
- value, may_await=True, threaded=threaded)()
775
- elif isawaitable(value):
776
- value = await value
777
- except BaseException as e:
778
- if isinstance(e, Reraised):
779
- e = e.exception
780
805
  value = await throw(e)
781
- else:
782
- value = await send(value)
783
- yield value
784
- except BaseException as e:
785
- if isinstance(e, Reraised):
786
- e = e.exception
787
- if isinstance(e, StopIteration):
788
- may_await: None | bool = True
789
- may_call: None | bool = True
790
- value = e.value
791
- if isinstance(value, YieldBase):
792
- may_await = value.may_await
793
- may_call = value.may_call
794
- value = value.value
795
- try:
796
- if may_call is None or may_call and callable(value):
797
- value = await call_as_async(
798
- value, may_await=may_await, threaded=threaded)()
799
- elif may_await is None or may_await and isawaitable(value):
800
- value = await value
801
806
  except BaseException as e:
802
- try:
803
- value = await throw(e)
804
- except BaseException as e:
805
- raise Reraised(e) from e
806
- yield value
807
- else:
808
- raise
809
- finally:
810
- await close()
807
+ raise Reraised(e) from e
808
+ yield value
809
+ else:
810
+ raise
811
+ finally:
812
+ await close()
811
813
 
812
814
 
813
815
  def run_gen_step(
814
816
  gen_step: Generator | Callable[[], Generator],
815
- simple: bool = False,
817
+ may_await: bool | Literal[1] = True,
818
+ may_call: bool | Literal[1] = True,
816
819
  threaded: bool = False,
817
820
  running_flag: None | SupportsBool | Callable[[], SupportsBool] | Callable[[], Awaitable[SupportsBool]] = None,
818
821
  *,
819
822
  async_: None | bool = None,
820
823
  ):
824
+ """
825
+ """
821
826
  if async_ is None:
822
827
  async_ = _get_async()
823
828
  if async_:
824
829
  async def process():
825
- gen = iter_gen_step_async(gen_step, simple=simple, threaded=threaded)
830
+ gen = iter_gen_step_async(
831
+ gen_step,
832
+ may_await=may_await,
833
+ may_call=may_call,
834
+ threaded=threaded,
835
+ )
826
836
  try:
827
837
  if running_flag is None:
828
838
  async for value in gen:
@@ -849,7 +859,7 @@ def run_gen_step(
849
859
  raise
850
860
  return process()
851
861
  else:
852
- gen = iter_gen_step(gen_step, simple=simple)
862
+ gen = iter_gen_step(gen_step, may_call=may_call)
853
863
  try:
854
864
  if running_flag is None:
855
865
  for value in gen:
@@ -874,7 +884,8 @@ def run_gen_step(
874
884
  @overload
875
885
  def run_gen_step_iter(
876
886
  gen_step: Generator | Callable[[], Generator],
877
- simple: bool = False,
887
+ may_await: bool | Literal[1] = True,
888
+ may_call: bool | Literal[1] = True,
878
889
  threaded: bool = False,
879
890
  *,
880
891
  async_: None = None,
@@ -883,7 +894,8 @@ def run_gen_step_iter(
883
894
  @overload
884
895
  def run_gen_step_iter(
885
896
  gen_step: Generator | Callable[[], Generator],
886
- simple: bool = False,
897
+ may_await: bool | Literal[1] = True,
898
+ may_call: bool | Literal[1] = True,
887
899
  threaded: bool = False,
888
900
  *,
889
901
  async_: Literal[False],
@@ -892,7 +904,8 @@ def run_gen_step_iter(
892
904
  @overload
893
905
  def run_gen_step_iter(
894
906
  gen_step: Generator | Callable[[], Generator],
895
- simple: bool = False,
907
+ may_await: bool | Literal[1] = True,
908
+ may_call: bool | Literal[1] = True,
896
909
  threaded: bool = False,
897
910
  *,
898
911
  async_: Literal[True],
@@ -900,34 +913,43 @@ def run_gen_step_iter(
900
913
  ...
901
914
  def run_gen_step_iter(
902
915
  gen_step: Generator | Callable[[], Generator],
903
- simple: bool = False,
916
+ may_await: bool | Literal[1] = True,
917
+ may_call: bool | Literal[1] = True,
904
918
  threaded: bool = False,
905
919
  *,
906
920
  async_: None | bool = None,
907
921
  ) -> Iterator | AsyncIterator:
922
+ """
923
+ """
908
924
  if async_ is None:
909
925
  async_ = _get_async()
910
926
  gen = gen_step() if callable(gen_step) else gen_step
911
927
  send: Callable = gen.send
912
928
  throw: Callable = gen.throw
913
929
  close: Callable = gen.close
930
+ default_may_await = may_await
931
+ default_may_call = may_call
914
932
  if async_:
915
933
  send = call_as_async(send, threaded=threaded)
916
934
  throw = call_as_async(throw, threaded=threaded)
917
935
  close = call_as_async(close, threaded=threaded)
918
936
  async def aextract(value, /):
919
- may_await: None | bool = None if simple else False
920
- may_call: None | bool = not simple
921
937
  yield_type = -1
938
+ may_await = default_may_await
939
+ may_call = default_may_call
922
940
  if isinstance(value, YieldBase):
923
- yield_type = value.yield_type
924
- may_await = value.may_await
925
- may_call = value.may_call
926
- value = value.value
927
- if may_call is None or may_call and callable(value):
941
+ yield_type = value.yield_type
942
+ maybe_awaitable = value.may_await
943
+ if maybe_awaitable is not None:
944
+ may_await = maybe_awaitable
945
+ maybe_callable = value.may_call
946
+ if maybe_callable is not None:
947
+ may_call = maybe_callable
948
+ value = value.value
949
+ if may_call is 1 or may_call and callable(value):
928
950
  value = await call_as_async(
929
951
  value, may_await=may_await, threaded=threaded)()
930
- elif may_await is None or may_await and isawaitable(value):
952
+ elif may_await is 1 or may_await and isawaitable(value):
931
953
  value = await value
932
954
  return yield_type, value
933
955
  async def aprocess():
@@ -973,13 +995,15 @@ def run_gen_step_iter(
973
995
  return aprocess()
974
996
  else:
975
997
  def extract(value, /):
976
- may_call: None | bool = not simple
977
998
  yield_type = -1
999
+ may_call = default_may_call
978
1000
  if isinstance(value, YieldBase):
979
1001
  yield_type = value.yield_type
980
- may_call = value.may_call
1002
+ maybe_callable = value.may_call
1003
+ if maybe_callable is not None:
1004
+ may_call = maybe_callable
981
1005
  value = value.value
982
- if may_call is None or may_call and callable(value):
1006
+ if may_call is 1 or may_call and callable(value):
983
1007
  value = value()
984
1008
  return yield_type, value
985
1009
  def process():
@@ -1021,7 +1045,8 @@ def as_gen_step(
1021
1045
  func: Callable,
1022
1046
  /,
1023
1047
  iter: bool = False,
1024
- simple: bool = False,
1048
+ may_await: bool | Literal[1] = True,
1049
+ may_call: bool | Literal[1] = True,
1025
1050
  threaded: bool = False,
1026
1051
  running_flag: None | SupportsBool | Callable[[], SupportsBool] | Callable[[], Awaitable[SupportsBool]] = None,
1027
1052
  *,
@@ -1033,14 +1058,16 @@ def as_gen_step(
1033
1058
  if iter:
1034
1059
  return run_gen_step_iter(
1035
1060
  func(*args, **kwds),
1036
- simple=simple,
1061
+ may_await=may_await,
1062
+ may_call=may_call,
1037
1063
  threaded=threaded,
1038
1064
  async_=async_, # type: ignore
1039
1065
  )
1040
1066
  else:
1041
1067
  return run_gen_step(
1042
1068
  func(*args, **kwds),
1043
- simple=simple,
1069
+ may_await=may_await,
1070
+ may_call=may_call,
1044
1071
  threaded=threaded,
1045
1072
  running_flag=running_flag,
1046
1073
  async_=async_,
@@ -1117,6 +1144,8 @@ def with_iter_next[T](
1117
1144
  /,
1118
1145
  async_: Literal[False, True] = False,
1119
1146
  ):
1147
+ """
1148
+ """
1120
1149
  if async_:
1121
1150
  get_next: Callable[[], T] | Callable[[], Awaitable[T]] = ensure_aiter(iterable).__anext__
1122
1151
  elif isinstance(iterable, Iterable):
@@ -1155,6 +1184,8 @@ def context[T](
1155
1184
  *ctxs: ContextManager | AsyncContextManager,
1156
1185
  async_: Literal[False, True] = False,
1157
1186
  ) -> T | Coroutine[Any, Any, T]:
1187
+ """
1188
+ """
1158
1189
  if async_:
1159
1190
  async def call():
1160
1191
  args: list = []
@@ -1203,6 +1234,8 @@ def backgroud_loop(
1203
1234
  *,
1204
1235
  async_: Literal[False, True] = False,
1205
1236
  ) -> ContextManager | AsyncContextManager:
1237
+ """
1238
+ """
1206
1239
  use_default_call = not callable(call)
1207
1240
  if use_default_call:
1208
1241
  start = time()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: python-iterutils
3
- Version: 0.2
3
+ Version: 0.2.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
@@ -0,0 +1,7 @@
1
+ LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
+ iterutils/__init__.py,sha256=_veJbrFYJld_cVSYbBnR37dSbGi2aSDAkNmLUEvuiXE,37134
3
+ iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
+ python_iterutils-0.2.1.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
+ python_iterutils-0.2.1.dist-info/METADATA,sha256=C55LpIsT807qqeehnsAZ7ZS-za5Gb03eltgrdYiN5vM,1467
6
+ python_iterutils-0.2.1.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
+ python_iterutils-0.2.1.dist-info/RECORD,,
@@ -1,7 +0,0 @@
1
- LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
2
- iterutils/__init__.py,sha256=LEkMyVkA2qLrVtJDuTXgUz0cUSexnjyEcJ0skHehf4M,38403
3
- iterutils/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
4
- python_iterutils-0.2.dist-info/LICENSE,sha256=o5242_N2TgDsWwFhPn7yr8YJNF7XsJM5NxUMtcT97bc,1100
5
- python_iterutils-0.2.dist-info/METADATA,sha256=EYmtSSWyFbN7QMzuv79s2UKsPoJ3fNvr_SmLsL8SnlE,1465
6
- python_iterutils-0.2.dist-info/WHEEL,sha256=Nq82e9rUAnEjt98J6MlVmMCZb-t9cYE2Ir1kpBmnWfs,88
7
- python_iterutils-0.2.dist-info/RECORD,,