reactivex 4.1.0__py3-none-any.whl → 5.0.0a2__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.
Files changed (219) hide show
  1. reactivex/__init__.py +35 -39
  2. reactivex/_version.py +1 -1
  3. reactivex/abc/disposable.py +3 -4
  4. reactivex/abc/observable.py +13 -6
  5. reactivex/abc/observer.py +2 -1
  6. reactivex/abc/periodicscheduler.py +7 -6
  7. reactivex/abc/scheduler.py +10 -9
  8. reactivex/abc/subject.py +5 -5
  9. reactivex/disposable/compositedisposable.py +4 -4
  10. reactivex/disposable/disposable.py +1 -2
  11. reactivex/disposable/multipleassignmentdisposable.py +2 -3
  12. reactivex/disposable/refcountdisposable.py +1 -2
  13. reactivex/disposable/serialdisposable.py +4 -5
  14. reactivex/disposable/singleassignmentdisposable.py +3 -4
  15. reactivex/internal/__init__.py +2 -0
  16. reactivex/internal/basic.py +2 -2
  17. reactivex/internal/concurrency.py +2 -1
  18. reactivex/internal/curry.py +59 -0
  19. reactivex/internal/exceptions.py +7 -12
  20. reactivex/internal/priorityqueue.py +2 -2
  21. reactivex/internal/utils.py +3 -2
  22. reactivex/notification.py +22 -21
  23. reactivex/observable/case.py +5 -6
  24. reactivex/observable/catch.py +3 -2
  25. reactivex/observable/combinelatest.py +4 -5
  26. reactivex/observable/concat.py +3 -2
  27. reactivex/observable/connectableobservable.py +7 -7
  28. reactivex/observable/defer.py +4 -3
  29. reactivex/observable/empty.py +3 -4
  30. reactivex/observable/forkjoin.py +5 -5
  31. reactivex/observable/fromcallback.py +4 -3
  32. reactivex/observable/fromfuture.py +2 -2
  33. reactivex/observable/fromiterable.py +4 -3
  34. reactivex/observable/generate.py +2 -2
  35. reactivex/observable/generatewithrelativetime.py +4 -3
  36. reactivex/observable/groupedobservable.py +4 -4
  37. reactivex/observable/ifthen.py +3 -2
  38. reactivex/observable/interval.py +1 -4
  39. reactivex/observable/marbles.py +18 -17
  40. reactivex/observable/mixins/__init__.py +32 -0
  41. reactivex/observable/mixins/combination.py +481 -0
  42. reactivex/observable/mixins/conditional.py +135 -0
  43. reactivex/observable/mixins/error_handling.py +130 -0
  44. reactivex/observable/mixins/filtering.py +1119 -0
  45. reactivex/observable/mixins/mathematical.py +277 -0
  46. reactivex/observable/mixins/multicasting.py +306 -0
  47. reactivex/observable/mixins/testing.py +193 -0
  48. reactivex/observable/mixins/time_based.py +209 -0
  49. reactivex/observable/mixins/transformation.py +632 -0
  50. reactivex/observable/mixins/utility.py +811 -0
  51. reactivex/observable/mixins/windowing.py +688 -0
  52. reactivex/observable/never.py +2 -2
  53. reactivex/observable/observable.py +72 -25
  54. reactivex/observable/onerrorresumenext.py +7 -6
  55. reactivex/observable/range.py +6 -6
  56. reactivex/observable/repeat.py +2 -2
  57. reactivex/observable/returnvalue.py +6 -5
  58. reactivex/observable/start.py +3 -2
  59. reactivex/observable/startasync.py +2 -1
  60. reactivex/observable/throw.py +3 -3
  61. reactivex/observable/timer.py +12 -12
  62. reactivex/observable/toasync.py +3 -2
  63. reactivex/observable/using.py +5 -4
  64. reactivex/observable/withlatestfrom.py +4 -5
  65. reactivex/observable/zip.py +7 -6
  66. reactivex/observer/autodetachobserver.py +4 -4
  67. reactivex/observer/observer.py +5 -4
  68. reactivex/observer/scheduledobserver.py +2 -2
  69. reactivex/operators/__init__.py +162 -208
  70. reactivex/operators/_all.py +23 -6
  71. reactivex/operators/_amb.py +88 -75
  72. reactivex/operators/_asobservable.py +20 -17
  73. reactivex/operators/_average.py +48 -45
  74. reactivex/operators/_buffer.py +81 -35
  75. reactivex/operators/_bufferwithtime.py +29 -9
  76. reactivex/operators/_bufferwithtimeorcount.py +27 -8
  77. reactivex/operators/_catch.py +33 -32
  78. reactivex/operators/_combinelatest.py +28 -20
  79. reactivex/operators/_concat.py +16 -13
  80. reactivex/operators/_contains.py +25 -6
  81. reactivex/operators/_count.py +24 -8
  82. reactivex/operators/_debounce.py +141 -138
  83. reactivex/operators/_defaultifempty.py +45 -42
  84. reactivex/operators/_delay.py +24 -23
  85. reactivex/operators/_delaysubscription.py +23 -21
  86. reactivex/operators/_delaywithmapper.py +10 -11
  87. reactivex/operators/_dematerialize.py +25 -21
  88. reactivex/operators/_distinct.py +50 -46
  89. reactivex/operators/_distinctuntilchanged.py +60 -57
  90. reactivex/operators/_do.py +123 -116
  91. reactivex/operators/_dowhile.py +3 -2
  92. reactivex/operators/_elementatordefault.py +57 -33
  93. reactivex/operators/_exclusive.py +59 -53
  94. reactivex/operators/_expand.py +82 -77
  95. reactivex/operators/_filter.py +63 -68
  96. reactivex/operators/_finallyaction.py +3 -2
  97. reactivex/operators/_find.py +49 -32
  98. reactivex/operators/_first.py +18 -11
  99. reactivex/operators/_firstordefault.py +5 -4
  100. reactivex/operators/_flatmap.py +89 -83
  101. reactivex/operators/_forkjoin.py +23 -18
  102. reactivex/operators/_groupby.py +27 -6
  103. reactivex/operators/_groupbyuntil.py +8 -5
  104. reactivex/operators/_groupjoin.py +7 -6
  105. reactivex/operators/_ignoreelements.py +20 -15
  106. reactivex/operators/_isempty.py +15 -4
  107. reactivex/operators/_join.py +6 -5
  108. reactivex/operators/_last.py +36 -31
  109. reactivex/operators/_lastordefault.py +8 -8
  110. reactivex/operators/_map.py +54 -39
  111. reactivex/operators/_materialize.py +30 -31
  112. reactivex/operators/_max.py +18 -11
  113. reactivex/operators/_maxby.py +5 -5
  114. reactivex/operators/_merge.py +132 -129
  115. reactivex/operators/_min.py +16 -10
  116. reactivex/operators/_minby.py +9 -8
  117. reactivex/operators/_multicast.py +9 -9
  118. reactivex/operators/_observeon.py +35 -31
  119. reactivex/operators/_onerrorresumenext.py +2 -1
  120. reactivex/operators/_pairwise.py +38 -34
  121. reactivex/operators/_partition.py +80 -73
  122. reactivex/operators/_pluck.py +4 -3
  123. reactivex/operators/_publish.py +36 -21
  124. reactivex/operators/_publishvalue.py +8 -7
  125. reactivex/operators/_reduce.py +16 -12
  126. reactivex/operators/_repeat.py +33 -30
  127. reactivex/operators/_replay.py +9 -9
  128. reactivex/operators/_retry.py +12 -10
  129. reactivex/operators/_sample.py +31 -27
  130. reactivex/operators/_scan.py +41 -39
  131. reactivex/operators/_sequenceequal.py +8 -7
  132. reactivex/operators/_single.py +20 -13
  133. reactivex/operators/_singleordefault.py +6 -5
  134. reactivex/operators/_skip.py +35 -32
  135. reactivex/operators/_skiplast.py +38 -34
  136. reactivex/operators/_skiplastwithtime.py +5 -4
  137. reactivex/operators/_skipuntil.py +40 -35
  138. reactivex/operators/_skipuntilwithtime.py +4 -3
  139. reactivex/operators/_skipwhile.py +65 -44
  140. reactivex/operators/_skipwithtime.py +50 -46
  141. reactivex/operators/_slice.py +58 -53
  142. reactivex/operators/_some.py +48 -47
  143. reactivex/operators/_startswith.py +17 -15
  144. reactivex/operators/_subscribeon.py +44 -41
  145. reactivex/operators/_sum.py +23 -6
  146. reactivex/operators/_switchlatest.py +71 -69
  147. reactivex/operators/_take.py +37 -33
  148. reactivex/operators/_takelast.py +37 -36
  149. reactivex/operators/_takelastbuffer.py +38 -37
  150. reactivex/operators/_takelastwithtime.py +60 -56
  151. reactivex/operators/_takeuntil.py +33 -32
  152. reactivex/operators/_takeuntilwithtime.py +42 -39
  153. reactivex/operators/_takewhile.py +108 -100
  154. reactivex/operators/_takewithtime.py +46 -41
  155. reactivex/operators/_throttlefirst.py +52 -45
  156. reactivex/operators/_timeinterval.py +40 -36
  157. reactivex/operators/_timeout.py +81 -79
  158. reactivex/operators/_timeoutwithmapper.py +6 -5
  159. reactivex/operators/_timestamp.py +24 -22
  160. reactivex/operators/_todict.py +51 -43
  161. reactivex/operators/_tofuture.py +24 -15
  162. reactivex/operators/_toiterable.py +33 -27
  163. reactivex/operators/_tomarbles.py +5 -5
  164. reactivex/operators/_toset.py +29 -19
  165. reactivex/operators/_whiledo.py +2 -1
  166. reactivex/operators/_window.py +100 -99
  167. reactivex/operators/_windowwithcount.py +56 -54
  168. reactivex/operators/_windowwithtime.py +95 -79
  169. reactivex/operators/_windowwithtimeorcount.py +85 -69
  170. reactivex/operators/_withlatestfrom.py +13 -9
  171. reactivex/operators/_zip.py +67 -63
  172. reactivex/operators/connectable/_refcount.py +4 -3
  173. reactivex/pipe.py +2 -1
  174. reactivex/run.py +8 -4
  175. reactivex/scheduler/catchscheduler.py +11 -10
  176. reactivex/scheduler/currentthreadscheduler.py +2 -3
  177. reactivex/scheduler/eventloop/asyncioscheduler.py +7 -6
  178. reactivex/scheduler/eventloop/asynciothreadsafescheduler.py +12 -14
  179. reactivex/scheduler/eventloop/eventletscheduler.py +4 -4
  180. reactivex/scheduler/eventloop/geventscheduler.py +4 -4
  181. reactivex/scheduler/eventloop/ioloopscheduler.py +4 -4
  182. reactivex/scheduler/eventloop/twistedscheduler.py +4 -4
  183. reactivex/scheduler/eventloopscheduler.py +9 -12
  184. reactivex/scheduler/historicalscheduler.py +1 -2
  185. reactivex/scheduler/immediatescheduler.py +5 -4
  186. reactivex/scheduler/mainloop/gtkscheduler.py +6 -7
  187. reactivex/scheduler/mainloop/pygamescheduler.py +4 -4
  188. reactivex/scheduler/mainloop/qtscheduler.py +6 -6
  189. reactivex/scheduler/mainloop/tkinterscheduler.py +4 -4
  190. reactivex/scheduler/mainloop/wxscheduler.py +7 -7
  191. reactivex/scheduler/newthreadscheduler.py +6 -8
  192. reactivex/scheduler/periodicscheduler.py +4 -4
  193. reactivex/scheduler/scheduleditem.py +4 -4
  194. reactivex/scheduler/scheduler.py +5 -5
  195. reactivex/scheduler/threadpoolscheduler.py +3 -3
  196. reactivex/scheduler/timeoutscheduler.py +5 -4
  197. reactivex/scheduler/trampoline.py +1 -2
  198. reactivex/scheduler/trampolinescheduler.py +5 -6
  199. reactivex/scheduler/virtualtimescheduler.py +4 -4
  200. reactivex/subject/asyncsubject.py +2 -2
  201. reactivex/subject/behaviorsubject.py +2 -2
  202. reactivex/subject/innersubscription.py +2 -2
  203. reactivex/subject/replaysubject.py +8 -8
  204. reactivex/subject/subject.py +4 -4
  205. reactivex/testing/coldobservable.py +5 -5
  206. reactivex/testing/hotobservable.py +6 -6
  207. reactivex/testing/marbles.py +21 -20
  208. reactivex/testing/mockdisposable.py +1 -3
  209. reactivex/testing/mockobserver.py +2 -2
  210. reactivex/testing/reactivetest.py +2 -2
  211. reactivex/testing/recorded.py +1 -1
  212. reactivex/testing/subscription.py +3 -3
  213. reactivex/testing/testscheduler.py +13 -12
  214. reactivex/typing.py +25 -14
  215. {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/METADATA +59 -26
  216. reactivex-5.0.0a2.dist-info/RECORD +236 -0
  217. {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/WHEEL +1 -1
  218. reactivex-4.1.0.dist-info/RECORD +0 -223
  219. {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/licenses/LICENSE +0 -0
@@ -1,42 +1,45 @@
1
- from typing import Callable, Optional, TypeVar
1
+ from typing import TypeVar
2
2
 
3
3
  import reactivex
4
4
  from reactivex import Observable
5
+ from reactivex.internal import curry_flip
5
6
  from reactivex.internal.utils import infinite
6
7
 
7
8
  _T = TypeVar("_T")
8
9
 
9
10
 
11
+ @curry_flip
10
12
  def repeat_(
11
- repeat_count: Optional[int] = None,
12
- ) -> Callable[[Observable[_T]], Observable[_T]]:
13
- def repeat(source: Observable[_T]) -> Observable[_T]:
14
- """Repeats the observable sequence a specified number of times.
15
- If the repeat count is not specified, the sequence repeats
16
- indefinitely.
17
-
18
- Examples:
19
- >>> repeated = source.repeat()
20
- >>> repeated = source.repeat(42)
21
-
22
- Args:
23
- source: The observable source to repeat.
24
-
25
- Returns:
26
- The observable sequence producing the elements of the given
27
- sequence repeatedly.
28
- """
29
-
30
- if repeat_count is None:
31
- gen = infinite()
32
- else:
33
- gen = range(repeat_count)
34
-
35
- return reactivex.defer(
36
- lambda _: reactivex.concat_with_iterable(source for _ in gen)
37
- )
38
-
39
- return repeat
13
+ source: Observable[_T],
14
+ repeat_count: int | None = None,
15
+ ) -> Observable[_T]:
16
+ """Repeats the observable sequence a specified number of times.
17
+ If the repeat count is not specified, the sequence repeats
18
+ indefinitely.
19
+
20
+ Examples:
21
+ >>> result = source.pipe(repeat())
22
+ >>> result = repeat()(source)
23
+ >>> result = source.pipe(repeat(42))
24
+
25
+ Args:
26
+ source: The observable source to repeat.
27
+ repeat_count: Optional number of times to repeat the sequence.
28
+ If not provided, repeats indefinitely.
29
+
30
+ Returns:
31
+ The observable sequence producing the elements of the given
32
+ sequence repeatedly.
33
+ """
34
+
35
+ if repeat_count is None:
36
+ gen = infinite()
37
+ else:
38
+ gen = range(repeat_count)
39
+
40
+ return reactivex.defer(
41
+ lambda _: reactivex.concat_with_iterable(source for _ in gen)
42
+ )
40
43
 
41
44
 
42
45
  __all = ["repeat"]
@@ -1,8 +1,8 @@
1
- from typing import Callable, Optional, TypeVar, Union
1
+ from collections.abc import Callable
2
+ from typing import TypeVar
2
3
 
3
- from reactivex import ConnectableObservable, Observable, abc
4
+ from reactivex import ConnectableObservable, Observable, abc, typing
4
5
  from reactivex import operators as ops
5
- from reactivex import typing
6
6
  from reactivex.subject import ReplaySubject
7
7
  from reactivex.typing import Mapper
8
8
 
@@ -11,12 +11,12 @@ _TResult = TypeVar("_TResult")
11
11
 
12
12
 
13
13
  def replay_(
14
- mapper: Optional[Mapper[Observable[_TSource], Observable[_TResult]]] = None,
15
- buffer_size: Optional[int] = None,
16
- window: Optional[typing.RelativeTime] = None,
17
- scheduler: Optional[abc.SchedulerBase] = None,
14
+ mapper: Mapper[Observable[_TSource], Observable[_TResult]] | None = None,
15
+ buffer_size: int | None = None,
16
+ window: typing.RelativeTime | None = None,
17
+ scheduler: abc.SchedulerBase | None = None,
18
18
  ) -> Callable[
19
- [Observable[_TSource]], Union[Observable[_TResult], ConnectableObservable[_TSource]]
19
+ [Observable[_TSource]], Observable[_TResult] | ConnectableObservable[_TSource]
20
20
  ]:
21
21
  """Returns an observable sequence that is the result of invoking the
22
22
  mapper on a connectable observable sequence that shares a single
@@ -52,7 +52,7 @@ def replay_(
52
52
  if mapper:
53
53
 
54
54
  def subject_factory(
55
- scheduler: Optional[abc.SchedulerBase] = None,
55
+ scheduler: abc.SchedulerBase | None = None,
56
56
  ) -> ReplaySubject[_TSource]:
57
57
  return ReplaySubject(buffer_size, window, scheduler)
58
58
 
@@ -1,25 +1,30 @@
1
- from typing import Callable, Optional, TypeVar
1
+ from typing import TypeVar
2
2
 
3
3
  import reactivex
4
4
  from reactivex import Observable
5
+ from reactivex.internal import curry_flip
5
6
  from reactivex.internal.utils import infinite
6
7
 
7
8
  _T = TypeVar("_T")
8
9
 
9
10
 
11
+ @curry_flip
10
12
  def retry_(
11
- retry_count: Optional[int] = None,
12
- ) -> Callable[[Observable[_T]], Observable[_T]]:
13
+ source: Observable[_T],
14
+ retry_count: int | None = None,
15
+ ) -> Observable[_T]:
13
16
  """Repeats the source observable sequence the specified number of
14
17
  times or until it successfully terminates. If the retry count is
15
18
  not specified, it retries indefinitely.
16
19
 
17
20
  Examples:
18
- >>> retried = retry()
19
- >>> retried = retry(42)
21
+ >>> result = source.pipe(retry())
22
+ >>> result = retry()(source)
23
+ >>> result = source.pipe(retry(42))
20
24
 
21
25
  Args:
22
- retry_count: [Optional] Number of times to retry the sequence.
26
+ source: The source observable sequence.
27
+ retry_count: Optional number of times to retry the sequence.
23
28
  If not provided, retry the sequence indefinitely.
24
29
 
25
30
  Returns:
@@ -32,10 +37,7 @@ def retry_(
32
37
  else:
33
38
  gen = range(retry_count)
34
39
 
35
- def retry(source: Observable[_T]) -> Observable[_T]:
36
- return reactivex.catch_with_iterable(source for _ in gen)
37
-
38
- return retry
40
+ return reactivex.catch_with_iterable(source for _ in gen)
39
41
 
40
42
 
41
43
  __all__ = ["retry_"]
@@ -1,8 +1,9 @@
1
- from typing import Any, Callable, Optional, TypeVar, Union, cast
1
+ from typing import Any, TypeVar, cast
2
2
 
3
3
  import reactivex
4
4
  from reactivex import Observable, abc, typing
5
5
  from reactivex.disposable import CompositeDisposable
6
+ from reactivex.internal import curry_flip
6
7
 
7
8
  _T = TypeVar("_T")
8
9
 
@@ -11,8 +12,8 @@ def sample_observable(
11
12
  source: Observable[_T], sampler: Observable[Any]
12
13
  ) -> Observable[_T]:
13
14
  def subscribe(
14
- observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None
15
- ):
15
+ observer: abc.ObserverBase[_T], scheduler: abc.SchedulerBase | None = None
16
+ ) -> abc.DisposableBase:
16
17
  at_end = False
17
18
  has_value = False
18
19
  value: _T = cast(_T, None)
@@ -50,31 +51,34 @@ def sample_observable(
50
51
  return Observable(subscribe)
51
52
 
52
53
 
54
+ @curry_flip
53
55
  def sample_(
54
- sampler: Union[typing.RelativeTime, Observable[Any]],
55
- scheduler: Optional[abc.SchedulerBase] = None,
56
- ) -> Callable[[Observable[_T]], Observable[_T]]:
57
- def sample(source: Observable[_T]) -> Observable[_T]:
58
- """Samples the observable sequence at each interval.
59
-
60
- Examples:
61
- >>> res = sample(source)
62
-
63
- Args:
64
- source: Source sequence to sample.
65
-
66
- Returns:
67
- Sampled observable sequence.
68
- """
69
-
70
- if isinstance(sampler, abc.ObservableBase):
71
- return sample_observable(source, sampler)
72
- else:
73
- return sample_observable(
74
- source, reactivex.interval(sampler, scheduler=scheduler)
75
- )
76
-
77
- return sample
56
+ source: Observable[_T],
57
+ sampler: typing.RelativeTime | Observable[Any],
58
+ scheduler: abc.SchedulerBase | None = None,
59
+ ) -> Observable[_T]:
60
+ """Samples the observable sequence at each interval.
61
+
62
+ Examples:
63
+ >>> res = source.pipe(sample(1.0))
64
+ >>> res = sample(1.0)(source)
65
+ >>> res = source.pipe(sample(other_observable))
66
+
67
+ Args:
68
+ source: Source sequence to sample.
69
+ sampler: Interval or observable to sample at.
70
+ scheduler: Scheduler to use.
71
+
72
+ Returns:
73
+ Sampled observable sequence.
74
+ """
75
+
76
+ if isinstance(sampler, abc.ObservableBase):
77
+ return sample_observable(source, sampler)
78
+ else:
79
+ return sample_observable(
80
+ source, reactivex.interval(sampler, scheduler=scheduler)
81
+ )
78
82
 
79
83
 
80
84
  __all__ = ["sample_"]
@@ -1,7 +1,8 @@
1
- from typing import Callable, Type, TypeVar, Union, cast
1
+ from typing import TypeVar, cast
2
2
 
3
3
  from reactivex import Observable, abc, defer
4
4
  from reactivex import operators as ops
5
+ from reactivex.internal import curry_flip
5
6
  from reactivex.internal.utils import NotSet
6
7
  from reactivex.typing import Accumulator
7
8
 
@@ -9,52 +10,53 @@ _T = TypeVar("_T")
9
10
  _TState = TypeVar("_TState")
10
11
 
11
12
 
13
+ @curry_flip
12
14
  def scan_(
13
- accumulator: Accumulator[_TState, _T], seed: Union[_TState, Type[NotSet]] = NotSet
14
- ) -> Callable[[Observable[_T]], Observable[_TState]]:
15
+ source: Observable[_T],
16
+ accumulator: Accumulator[_TState, _T],
17
+ seed: _TState | type[NotSet] = NotSet,
18
+ ) -> Observable[_TState]:
19
+ """Applies an accumulator function over an observable sequence and
20
+ returns each intermediate result.
21
+
22
+ Examples:
23
+ >>> result = source.pipe(scan(lambda acc, x: acc + x, 0))
24
+ >>> result = scan(lambda acc, x: acc + x, 0)(source)
25
+ >>> result = source.pipe(scan(lambda acc, x: acc + x))
26
+
27
+ Args:
28
+ source: The observable source to scan.
29
+ accumulator: An accumulator function to invoke on each element.
30
+ seed: Optional initial accumulator value.
31
+
32
+ Returns:
33
+ An observable sequence containing the accumulated values.
34
+ """
15
35
  has_seed = seed is not NotSet
16
36
 
17
- def scan(source: Observable[_T]) -> Observable[_TState]:
18
- """Partially applied scan operator.
37
+ def factory(scheduler: abc.SchedulerBase) -> Observable[_TState]:
38
+ has_accumulation = False
39
+ accumulation: _TState = cast(_TState, None)
19
40
 
20
- Applies an accumulator function over an observable sequence and
21
- returns each intermediate result.
41
+ def projection(x: _T) -> _TState:
42
+ nonlocal has_accumulation
43
+ nonlocal accumulation
22
44
 
23
- Examples:
24
- >>> scanned = scan(source)
45
+ if has_accumulation:
46
+ accumulation = accumulator(accumulation, x)
47
+ else:
48
+ accumulation = (
49
+ accumulator(cast(_TState, seed), x)
50
+ if has_seed
51
+ else cast(_TState, x)
52
+ )
53
+ has_accumulation = True
25
54
 
26
- Args:
27
- source: The observable source to scan.
55
+ return accumulation
28
56
 
29
- Returns:
30
- An observable sequence containing the accumulated values.
31
- """
57
+ return source.pipe(ops.map(projection))
32
58
 
33
- def factory(scheduler: abc.SchedulerBase) -> Observable[_TState]:
34
- has_accumulation = False
35
- accumulation: _TState = cast(_TState, None)
36
-
37
- def projection(x: _T) -> _TState:
38
- nonlocal has_accumulation
39
- nonlocal accumulation
40
-
41
- if has_accumulation:
42
- accumulation = accumulator(accumulation, x)
43
- else:
44
- accumulation = (
45
- accumulator(cast(_TState, seed), x)
46
- if has_seed
47
- else cast(_TState, x)
48
- )
49
- has_accumulation = True
50
-
51
- return accumulation
52
-
53
- return source.pipe(ops.map(projection))
54
-
55
- return defer(factory)
56
-
57
- return scan
59
+ return defer(factory)
58
60
 
59
61
 
60
62
  __all__ = ["scan_"]
@@ -1,4 +1,5 @@
1
- from typing import Callable, Iterable, List, Optional, TypeVar, Union
1
+ from collections.abc import Callable, Iterable
2
+ from typing import TypeVar
2
3
 
3
4
  import reactivex
4
5
  from reactivex import Observable, abc, typing
@@ -9,8 +10,8 @@ _T = TypeVar("_T")
9
10
 
10
11
 
11
12
  def sequence_equal_(
12
- second: Union[Observable[_T], Iterable[_T]],
13
- comparer: Optional[typing.Comparer[_T]] = None,
13
+ second: Observable[_T] | Iterable[_T],
14
+ comparer: typing.Comparer[_T] | None = None,
14
15
  ) -> Callable[[Observable[_T]], Observable[bool]]:
15
16
  comparer_ = comparer or default_comparer
16
17
  second_ = (
@@ -43,12 +44,12 @@ def sequence_equal_(
43
44
 
44
45
  def subscribe(
45
46
  observer: abc.ObserverBase[bool],
46
- scheduler: Optional[abc.SchedulerBase] = None,
47
- ):
47
+ scheduler: abc.SchedulerBase | None = None,
48
+ ) -> abc.DisposableBase:
48
49
  donel = [False]
49
50
  doner = [False]
50
- ql: List[_T] = []
51
- qr: List[_T] = []
51
+ ql: list[_T] = []
52
+ qr: list[_T] = []
52
53
 
53
54
  def on_next1(x: _T) -> None:
54
55
  if len(qr) > 0:
@@ -1,25 +1,32 @@
1
- from typing import Callable, Optional, TypeVar, cast
1
+ from typing import TypeVar, cast
2
2
 
3
- from reactivex import Observable, compose
3
+ from reactivex import Observable
4
4
  from reactivex import operators as ops
5
+ from reactivex.internal import curry_flip
5
6
  from reactivex.typing import Predicate
6
7
 
8
+ from ._singleordefault import single_or_default_async_
9
+
7
10
  _T = TypeVar("_T")
8
11
 
9
12
 
13
+ @curry_flip
10
14
  def single_(
11
- predicate: Optional[Predicate[_T]] = None,
12
- ) -> Callable[[Observable[_T]], Observable[_T]]:
15
+ source: Observable[_T],
16
+ predicate: Predicate[_T] | None = None,
17
+ ) -> Observable[_T]:
13
18
  """Returns the only element of an observable sequence that satisfies the
14
19
  condition in the optional predicate, and reports an exception if there
15
20
  is not exactly one element in the observable sequence.
16
21
 
17
- Example:
18
- >>> res = single()
19
- >>> res = single(lambda x: x == 42)
22
+ Examples:
23
+ >>> res = source.pipe(single())
24
+ >>> res = single()(source)
25
+ >>> res = source.pipe(single(lambda x: x == 42))
20
26
 
21
27
  Args:
22
- predicate -- [Optional] A predicate function to evaluate for
28
+ source: The source observable sequence.
29
+ predicate: [Optional] A predicate function to evaluate for
23
30
  elements in the source sequence.
24
31
 
25
32
  Returns:
@@ -28,12 +35,12 @@ def single_(
28
35
  """
29
36
 
30
37
  if predicate:
31
- return compose(ops.filter(predicate), ops.single())
38
+ return source.pipe(ops.filter(predicate), ops.single())
32
39
  else:
33
- return cast(
34
- Callable[[Observable[_T]], Observable[_T]],
35
- ops.single_or_default_async(False),
36
- )
40
+ # single_or_default_async_(False) returns
41
+ # Callable[[Observable[_T]], Observable[_T]] but the type checker
42
+ # cannot infer it. This cast is safe - implementation preserves type.
43
+ return cast(Observable[_T], single_or_default_async_(False)(source))
37
44
 
38
45
 
39
46
  __all__ = ["single_"]
@@ -1,4 +1,5 @@
1
- from typing import Callable, Optional, TypeVar, cast
1
+ from collections.abc import Callable
2
+ from typing import TypeVar, cast
2
3
 
3
4
  from reactivex import Observable, abc, compose
4
5
  from reactivex import operators as ops
@@ -9,13 +10,13 @@ _T = TypeVar("_T")
9
10
 
10
11
 
11
12
  def single_or_default_async_(
12
- has_default: bool = False, default_value: Optional[_T] = None
13
+ has_default: bool = False, default_value: _T | None = None
13
14
  ) -> Callable[[Observable[_T]], Observable[_T]]:
14
15
  def single_or_default_async(source: Observable[_T]) -> Observable[_T]:
15
16
  def subscribe(
16
17
  observer: abc.ObserverBase[_T],
17
- scheduler: Optional[abc.SchedulerBase] = None,
18
- ):
18
+ scheduler: abc.SchedulerBase | None = None,
19
+ ) -> abc.DisposableBase:
19
20
  value = cast(_T, default_value)
20
21
  seen_value = False
21
22
 
@@ -47,7 +48,7 @@ def single_or_default_async_(
47
48
 
48
49
 
49
50
  def single_or_default_(
50
- predicate: Optional[Predicate[_T]] = None, default_value: _T = None
51
+ predicate: Predicate[_T] | None = None, default_value: _T = None
51
52
  ) -> Callable[[Observable[_T]], Observable[_T]]:
52
53
  """Returns the only element of an observable sequence that matches
53
54
  the predicate, or a default value if no such element exists this
@@ -1,50 +1,53 @@
1
- from typing import Callable, Optional, TypeVar
1
+ from typing import TypeVar
2
2
 
3
3
  from reactivex import Observable, abc
4
- from reactivex.internal import ArgumentOutOfRangeException
4
+ from reactivex.internal import ArgumentOutOfRangeException, curry_flip
5
5
 
6
6
  _T = TypeVar("_T")
7
7
 
8
8
 
9
- def skip_(count: int) -> Callable[[Observable[_T]], Observable[_T]]:
10
- if count < 0:
11
- raise ArgumentOutOfRangeException()
12
-
13
- def skip(source: Observable[_T]) -> Observable[_T]:
14
- """The skip operator.
9
+ @curry_flip
10
+ def skip_(source: Observable[_T], count: int) -> Observable[_T]:
11
+ """Bypasses a specified number of elements in an observable sequence
12
+ and then returns the remaining elements.
15
13
 
16
- Bypasses a specified number of elements in an observable sequence
17
- and then returns the remaining elements.
14
+ Examples:
15
+ >>> result = source.pipe(skip(5))
16
+ >>> result = skip(5)(source)
18
17
 
19
- Args:
20
- source: The source observable.
18
+ Args:
19
+ source: The source observable.
20
+ count: The number of elements to skip.
21
21
 
22
- Returns:
23
- An observable sequence that contains the elements that occur
24
- after the specified index in the input sequence.
25
- """
22
+ Returns:
23
+ An observable sequence that contains the elements that occur
24
+ after the specified index in the input sequence.
26
25
 
27
- def subscribe(
28
- observer: abc.ObserverBase[_T],
29
- scheduler: Optional[abc.SchedulerBase] = None,
30
- ):
31
- remaining = count
26
+ Raises:
27
+ ArgumentOutOfRangeException: If count is negative.
28
+ """
29
+ if count < 0:
30
+ raise ArgumentOutOfRangeException()
32
31
 
33
- def on_next(value: _T) -> None:
34
- nonlocal remaining
32
+ def subscribe(
33
+ observer: abc.ObserverBase[_T],
34
+ scheduler: abc.SchedulerBase | None = None,
35
+ ) -> abc.DisposableBase:
36
+ remaining = count
35
37
 
36
- if remaining <= 0:
37
- observer.on_next(value)
38
- else:
39
- remaining -= 1
38
+ def on_next(value: _T) -> None:
39
+ nonlocal remaining
40
40
 
41
- return source.subscribe(
42
- on_next, observer.on_error, observer.on_completed, scheduler=scheduler
43
- )
41
+ if remaining <= 0:
42
+ observer.on_next(value)
43
+ else:
44
+ remaining -= 1
44
45
 
45
- return Observable(subscribe)
46
+ return source.subscribe(
47
+ on_next, observer.on_error, observer.on_completed, scheduler=scheduler
48
+ )
46
49
 
47
- return skip
50
+ return Observable(subscribe)
48
51
 
49
52
 
50
53
  __all__ = ["skip_"]
@@ -1,52 +1,56 @@
1
- from typing import Callable, List, Optional, TypeVar
1
+ from typing import TypeVar
2
2
 
3
3
  from reactivex import Observable, abc
4
+ from reactivex.internal import curry_flip
4
5
 
5
6
  _T = TypeVar("_T")
6
7
 
7
8
 
8
- def skip_last_(count: int) -> Callable[[Observable[_T]], Observable[_T]]:
9
- def skip_last(source: Observable[_T]) -> Observable[_T]:
10
- """Bypasses a specified number of elements at the end of an
11
- observable sequence.
9
+ @curry_flip
10
+ def skip_last_(source: Observable[_T], count: int) -> Observable[_T]:
11
+ """Bypasses a specified number of elements at the end of an
12
+ observable sequence.
12
13
 
13
- This operator accumulates a queue with a length enough to store
14
- the first `count` elements. As more elements are received,
15
- elements are taken from the front of the queue and produced on
16
- the result sequence. This causes elements to be delayed.
14
+ This operator accumulates a queue with a length enough to store
15
+ the first `count` elements. As more elements are received,
16
+ elements are taken from the front of the queue and produced on
17
+ the result sequence. This causes elements to be delayed.
17
18
 
18
- Args:
19
- count: Number of elements to bypass at the end of the
20
- source sequence.
19
+ Examples:
20
+ >>> res = source.pipe(skip_last(5))
21
+ >>> res = skip_last(5)(source)
21
22
 
22
- Returns:
23
- An observable sequence containing the source sequence
24
- elements except for the bypassed ones at the end.
25
- """
23
+ Args:
24
+ source: Source observable.
25
+ count: Number of elements to bypass at the end of the
26
+ source sequence.
26
27
 
27
- def subscribe(
28
- observer: abc.ObserverBase[_T],
29
- scheduler: Optional[abc.SchedulerBase] = None,
30
- ):
31
- q: List[_T] = []
28
+ Returns:
29
+ An observable sequence containing the source sequence
30
+ elements except for the bypassed ones at the end.
31
+ """
32
32
 
33
- def on_next(value: _T) -> None:
34
- front = None
35
- with source.lock:
36
- q.append(value)
37
- if len(q) > count:
38
- front = q.pop(0)
33
+ def subscribe(
34
+ observer: abc.ObserverBase[_T],
35
+ scheduler: abc.SchedulerBase | None = None,
36
+ ) -> abc.DisposableBase:
37
+ q: list[_T] = []
39
38
 
40
- if front is not None:
41
- observer.on_next(front)
39
+ def on_next(value: _T) -> None:
40
+ front = None
41
+ with source.lock:
42
+ q.append(value)
43
+ if len(q) > count:
44
+ front = q.pop(0)
42
45
 
43
- return source.subscribe(
44
- on_next, observer.on_error, observer.on_completed, scheduler=scheduler
45
- )
46
+ if front is not None:
47
+ observer.on_next(front)
46
48
 
47
- return Observable(subscribe)
49
+ return source.subscribe(
50
+ on_next, observer.on_error, observer.on_completed, scheduler=scheduler
51
+ )
48
52
 
49
- return skip_last
53
+ return Observable(subscribe)
50
54
 
51
55
 
52
56
  __all__ = ["skip_last_"]