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,59 +1,60 @@
1
- from typing import Callable, Optional, TypeVar
1
+ from typing import TypeVar
2
2
 
3
3
  from reactivex import Observable, abc
4
4
  from reactivex import operators as ops
5
+ from reactivex.internal import curry_flip
5
6
  from reactivex.typing import Predicate
6
7
 
7
8
  _T = TypeVar("_T")
8
9
 
9
10
 
11
+ @curry_flip
10
12
  def some_(
11
- predicate: Optional[Predicate[_T]] = None,
12
- ) -> Callable[[Observable[_T]], Observable[bool]]:
13
- def some(source: Observable[_T]) -> Observable[bool]:
14
- """Partially applied operator.
15
-
16
- Determines whether some element of an observable sequence satisfies a
17
- condition if present, else if some items are in the sequence.
18
-
19
- Example:
20
- >>> obs = some(source)
21
-
22
- Args:
23
- predicate -- A function to test each element for a condition.
24
-
25
- Returns:
26
- An observable sequence containing a single element
27
- determining whether some elements in the source sequence
28
- pass the test in the specified predicate if given, else if
29
- some items are in the sequence.
30
- """
31
-
32
- def subscribe(
33
- observer: abc.ObserverBase[bool],
34
- scheduler: Optional[abc.SchedulerBase] = None,
35
- ):
36
- def on_next(_: _T):
37
- observer.on_next(True)
38
- observer.on_completed()
39
-
40
- def on_error():
41
- observer.on_next(False)
42
- observer.on_completed()
43
-
44
- return source.subscribe(
45
- on_next, observer.on_error, on_error, scheduler=scheduler
46
- )
47
-
48
- if predicate:
49
- return source.pipe(
50
- ops.filter(predicate),
51
- some_(),
52
- )
53
-
54
- return Observable(subscribe)
55
-
56
- return some
13
+ source: Observable[_T],
14
+ predicate: Predicate[_T] | None = None,
15
+ ) -> Observable[bool]:
16
+ """Determines whether some element of an observable sequence satisfies a
17
+ condition if present, else if some items are in the sequence.
18
+
19
+ Examples:
20
+ >>> res = source.pipe(some())
21
+ >>> res = some()(source)
22
+ >>> res = source.pipe(some(lambda x: x > 3))
23
+
24
+ Args:
25
+ source: The source observable sequence.
26
+ predicate: A function to test each element for a condition.
27
+
28
+ Returns:
29
+ An observable sequence containing a single element
30
+ determining whether some elements in the source sequence
31
+ pass the test in the specified predicate if given, else if
32
+ some items are in the sequence.
33
+ """
34
+
35
+ def subscribe(
36
+ observer: abc.ObserverBase[bool],
37
+ scheduler: abc.SchedulerBase | None = None,
38
+ ):
39
+ def on_next(_: _T):
40
+ observer.on_next(True)
41
+ observer.on_completed()
42
+
43
+ def on_error():
44
+ observer.on_next(False)
45
+ observer.on_completed()
46
+
47
+ return source.subscribe(
48
+ on_next, observer.on_error, on_error, scheduler=scheduler
49
+ )
50
+
51
+ if predicate:
52
+ return source.pipe(
53
+ ops.filter(predicate),
54
+ ops.some(),
55
+ )
56
+
57
+ return Observable(subscribe)
57
58
 
58
59
 
59
60
  __all__ = ["some_"]
@@ -1,28 +1,30 @@
1
- from typing import Callable, 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
 
6
7
  _T = TypeVar("_T")
7
8
 
8
9
 
9
- def start_with_(*args: _T) -> Callable[[Observable[_T]], Observable[_T]]:
10
- def start_with(source: Observable[_T]) -> Observable[_T]:
11
- """Partially applied start_with operator.
10
+ @curry_flip
11
+ def start_with_(source: Observable[_T], *args: _T) -> Observable[_T]:
12
+ """Prepends a sequence of values to an observable sequence.
12
13
 
13
- Prepends a sequence of values to an observable sequence.
14
+ Example:
15
+ >>> result = source.pipe(start_with(1, 2, 3))
16
+ >>> result = start_with(1, 2, 3)(source)
14
17
 
15
- Example:
16
- >>> start_with(source)
18
+ Args:
19
+ source: The source observable sequence.
20
+ args: Values to prepend to the source sequence.
17
21
 
18
- Returns:
19
- The source sequence prepended with the specified values.
20
- """
21
- start = reactivex.from_iterable(args)
22
- sequence = [start, source]
23
- return reactivex.concat(*sequence)
24
-
25
- return start_with
22
+ Returns:
23
+ The source sequence prepended with the specified values.
24
+ """
25
+ start = reactivex.from_iterable(args)
26
+ sequence = [start, source]
27
+ return reactivex.concat(*sequence)
26
28
 
27
29
 
28
30
  __all__ = ["start_with_"]
@@ -1,4 +1,4 @@
1
- from typing import Any, Callable, Optional, TypeVar
1
+ from typing import Any, TypeVar
2
2
 
3
3
  from reactivex import Observable, abc
4
4
  from reactivex.disposable import (
@@ -6,52 +6,55 @@ from reactivex.disposable import (
6
6
  SerialDisposable,
7
7
  SingleAssignmentDisposable,
8
8
  )
9
+ from reactivex.internal import curry_flip
9
10
 
10
11
  _T = TypeVar("_T")
11
12
 
12
13
 
14
+ @curry_flip
13
15
  def subscribe_on_(
16
+ source: Observable[_T],
14
17
  scheduler: abc.SchedulerBase,
15
- ) -> Callable[[Observable[_T]], Observable[_T]]:
16
- def subscribe_on(source: Observable[_T]) -> Observable[_T]:
17
- """Subscribe on the specified scheduler.
18
-
19
- Wrap the source sequence in order to run its subscription and
20
- unsubscription logic on the specified scheduler. This operation
21
- is not commonly used; see the remarks section for more
22
- information on the distinction between subscribe_on and
23
- observe_on.
24
-
25
- This only performs the side-effects of subscription and
26
- unsubscription on the specified scheduler. In order to invoke
27
- observer callbacks on a scheduler, use observe_on.
28
-
29
- Args:
30
- source: The source observable..
31
-
32
- Returns:
33
- The source sequence whose subscriptions and
34
- un-subscriptions happen on the specified scheduler.
35
- """
36
-
37
- def subscribe(
38
- observer: abc.ObserverBase[_T], _: Optional[abc.SchedulerBase] = None
39
- ):
40
- m = SingleAssignmentDisposable()
41
- d = SerialDisposable()
42
- d.disposable = m
43
-
44
- def action(scheduler: abc.SchedulerBase, state: Optional[Any] = None):
45
- d.disposable = ScheduledDisposable(
46
- scheduler, source.subscribe(observer)
47
- )
48
-
49
- m.disposable = scheduler.schedule(action)
50
- return d
51
-
52
- return Observable(subscribe)
53
-
54
- return subscribe_on
18
+ ) -> Observable[_T]:
19
+ """Subscribe on the specified scheduler.
20
+
21
+ Wrap the source sequence in order to run its subscription and
22
+ unsubscription logic on the specified scheduler. This operation
23
+ is not commonly used; see the remarks section for more
24
+ information on the distinction between subscribe_on and
25
+ observe_on.
26
+
27
+ This only performs the side-effects of subscription and
28
+ unsubscription on the specified scheduler. In order to invoke
29
+ observer callbacks on a scheduler, use observe_on.
30
+
31
+ Examples:
32
+ >>> res = source.pipe(subscribe_on(scheduler))
33
+ >>> res = subscribe_on(scheduler)(source)
34
+
35
+ Args:
36
+ source: The source observable.
37
+ scheduler: Scheduler to use for subscription/unsubscription.
38
+
39
+ Returns:
40
+ The source sequence whose subscriptions and
41
+ un-subscriptions happen on the specified scheduler.
42
+ """
43
+
44
+ def subscribe(observer: abc.ObserverBase[_T], _: abc.SchedulerBase | None = None):
45
+ m = SingleAssignmentDisposable()
46
+ d = SerialDisposable()
47
+ d.disposable = m
48
+
49
+ def action(scheduler: abc.SchedulerBase, state: Any | None = None):
50
+ d.disposable = ScheduledDisposable(
51
+ scheduler, source.subscribe(observer, scheduler=scheduler)
52
+ )
53
+
54
+ m.disposable = scheduler.schedule(action)
55
+ return d
56
+
57
+ return Observable(subscribe)
55
58
 
56
59
 
57
60
  __all__ = ["subscribe_on_"]
@@ -1,20 +1,37 @@
1
- from typing import Any, Callable, Optional
1
+ from typing import Any
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 Mapper
6
7
 
7
8
 
9
+ @curry_flip
8
10
  def sum_(
9
- key_mapper: Optional[Mapper[Any, float]] = None
10
- ) -> Callable[[Observable[Any]], Observable[float]]:
11
+ source: Observable[Any],
12
+ key_mapper: Mapper[Any, float] | None = None,
13
+ ) -> Observable[float]:
14
+ """Computes the sum of a sequence of values.
15
+
16
+ Examples:
17
+ >>> result = source.pipe(sum())
18
+ >>> result = sum()(source)
19
+ >>> result = source.pipe(sum(lambda x: x.value))
20
+
21
+ Args:
22
+ source: The source observable.
23
+ key_mapper: Optional mapper to extract numeric values.
24
+
25
+ Returns:
26
+ An observable sequence containing a single element with the sum.
27
+ """
11
28
  if key_mapper:
12
- return compose(ops.map(key_mapper), ops.sum())
29
+ return source.pipe(ops.map(key_mapper), ops.sum())
13
30
 
14
31
  def accumulator(prev: float, cur: float) -> float:
15
32
  return prev + cur
16
33
 
17
- return ops.reduce(seed=0, accumulator=accumulator)
34
+ return source.pipe(ops.reduce(seed=0, accumulator=accumulator))
18
35
 
19
36
 
20
37
  __all__ = ["sum_"]
@@ -1,5 +1,5 @@
1
1
  from asyncio import Future
2
- from typing import Any, Callable, Optional, TypeVar, Union
2
+ from typing import Any, TypeVar, Union
3
3
 
4
4
  from reactivex import Observable, abc, from_future
5
5
  from reactivex.disposable import (
@@ -7,84 +7,86 @@ from reactivex.disposable import (
7
7
  SerialDisposable,
8
8
  SingleAssignmentDisposable,
9
9
  )
10
+ from reactivex.internal import curry_flip
10
11
 
11
12
  _T = TypeVar("_T")
12
13
 
13
14
 
14
- def switch_latest_() -> (
15
- Callable[[Observable[Union[Observable[_T], "Future[_T]"]]], Observable[_T]]
16
- ):
17
- def switch_latest(
18
- source: Observable[Union[Observable[_T], "Future[_T]"]]
19
- ) -> Observable[_T]:
20
- """Partially applied switch_latest operator.
21
-
22
- Transforms an observable sequence of observable sequences into
23
- an observable sequence producing values only from the most
24
- recent observable sequence.
25
-
26
- Returns:
27
- An observable sequence that at any point in time produces
28
- the elements of the most recent inner observable sequence
29
- that has been received.
30
- """
31
-
32
- def subscribe(
33
- observer: abc.ObserverBase[_T],
34
- scheduler: Optional[abc.SchedulerBase] = None,
35
- ) -> abc.DisposableBase:
36
- inner_subscription = SerialDisposable()
37
- has_latest = [False]
38
- is_stopped = [False]
39
- latest = [0]
40
-
41
- def on_next(inner_source: Union[Observable[_T], "Future[_T]"]) -> None:
42
- nonlocal source
43
-
44
- d = SingleAssignmentDisposable()
45
- with source.lock:
46
- latest[0] += 1
47
- _id = latest[0]
48
- has_latest[0] = True
49
- inner_subscription.disposable = d
50
-
51
- # Check if Future or Observable
52
- if isinstance(inner_source, Future):
53
- obs = from_future(inner_source)
54
- else:
55
- obs = inner_source
56
-
57
- def on_next(x: Any) -> None:
58
- if latest[0] == _id:
59
- observer.on_next(x)
60
-
61
- def on_error(e: Exception) -> None:
62
- if latest[0] == _id:
63
- observer.on_error(e)
64
-
65
- def on_completed() -> None:
66
- if latest[0] == _id:
67
- has_latest[0] = False
68
- if is_stopped[0]:
69
- observer.on_completed()
70
-
71
- d.disposable = obs.subscribe(
72
- on_next, on_error, on_completed, scheduler=scheduler
73
- )
15
+ @curry_flip
16
+ def switch_latest_(
17
+ source: Observable[Union[Observable[_T], "Future[_T]"]],
18
+ ) -> Observable[_T]:
19
+ """Transforms an observable sequence of observable sequences into
20
+ an observable sequence producing values only from the most
21
+ recent observable sequence.
22
+
23
+ Examples:
24
+ >>> res = source.pipe(switch_latest())
25
+ >>> res = switch_latest()(source)
26
+
27
+ Args:
28
+ source: Source observable of observables.
29
+
30
+ Returns:
31
+ An observable sequence that at any point in time produces
32
+ the elements of the most recent inner observable sequence
33
+ that has been received.
34
+ """
35
+
36
+ def subscribe(
37
+ observer: abc.ObserverBase[_T],
38
+ scheduler: abc.SchedulerBase | None = None,
39
+ ) -> abc.DisposableBase:
40
+ inner_subscription = SerialDisposable()
41
+ has_latest = [False]
42
+ is_stopped = [False]
43
+ latest = [0]
44
+
45
+ def on_next(inner_source: Union[Observable[_T], "Future[_T]"]) -> None:
46
+ nonlocal source
47
+
48
+ d = SingleAssignmentDisposable()
49
+ with source.lock:
50
+ latest[0] += 1
51
+ _id = latest[0]
52
+ has_latest[0] = True
53
+ inner_subscription.disposable = d
54
+
55
+ # Check if Future or Observable
56
+ if isinstance(inner_source, Future):
57
+ obs = from_future(inner_source)
58
+ else:
59
+ obs = inner_source
60
+
61
+ def on_next(x: Any) -> None:
62
+ if latest[0] == _id:
63
+ observer.on_next(x)
64
+
65
+ def on_error(e: Exception) -> None:
66
+ if latest[0] == _id:
67
+ observer.on_error(e)
74
68
 
75
69
  def on_completed() -> None:
76
- is_stopped[0] = True
77
- if not has_latest[0]:
78
- observer.on_completed()
70
+ if latest[0] == _id:
71
+ has_latest[0] = False
72
+ if is_stopped[0]:
73
+ observer.on_completed()
79
74
 
80
- subscription = source.subscribe(
81
- on_next, observer.on_error, on_completed, scheduler=scheduler
75
+ d.disposable = obs.subscribe(
76
+ on_next, on_error, on_completed, scheduler=scheduler
82
77
  )
83
- return CompositeDisposable(subscription, inner_subscription)
84
78
 
85
- return Observable(subscribe)
79
+ def on_completed() -> None:
80
+ is_stopped[0] = True
81
+ if not has_latest[0]:
82
+ observer.on_completed()
86
83
 
87
- return switch_latest
84
+ subscription = source.subscribe(
85
+ on_next, observer.on_error, on_completed, scheduler=scheduler
86
+ )
87
+ return CompositeDisposable(subscription, inner_subscription)
88
+
89
+ return Observable(subscribe)
88
90
 
89
91
 
90
92
  __all__ = ["switch_latest_"]
@@ -1,53 +1,57 @@
1
- from typing import Callable, Optional, TypeVar
1
+ from typing import TypeVar
2
2
 
3
3
  from reactivex import Observable, abc, empty
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 take_(count: int) -> Callable[[Observable[_T]], Observable[_T]]:
10
- if count < 0:
11
- raise ArgumentOutOfRangeException()
12
-
13
- def take(source: Observable[_T]) -> Observable[_T]:
14
- """Returns a specified number of contiguous elements from the start of
15
- an observable sequence.
9
+ @curry_flip
10
+ def take_(source: Observable[_T], count: int) -> Observable[_T]:
11
+ """Returns a specified number of contiguous elements from the start of
12
+ an observable sequence.
16
13
 
17
- >>> take(source)
14
+ Example:
15
+ >>> result = source.pipe(take(5))
16
+ >>> result = take(5)(source)
18
17
 
19
- Keyword arguments:
20
- count -- The number of elements to return.
18
+ Args:
19
+ source: The source observable sequence.
20
+ count: The number of elements to return.
21
21
 
22
- Returns an observable sequence that contains the specified number of
22
+ Returns:
23
+ An observable sequence that contains the specified number of
23
24
  elements from the start of the input sequence.
24
- """
25
25
 
26
- if not count:
27
- return empty()
26
+ Raises:
27
+ ArgumentOutOfRangeException: If count is negative.
28
+ """
29
+ if count < 0:
30
+ raise ArgumentOutOfRangeException()
28
31
 
29
- def subscribe(
30
- observer: abc.ObserverBase[_T],
31
- scheduler: Optional[abc.SchedulerBase] = None,
32
- ):
33
- remaining = count
32
+ if not count:
33
+ return empty()
34
34
 
35
- def on_next(value: _T) -> None:
36
- nonlocal remaining
35
+ def subscribe(
36
+ observer: abc.ObserverBase[_T],
37
+ scheduler: abc.SchedulerBase | None = None,
38
+ ):
39
+ remaining = count
37
40
 
38
- if remaining > 0:
39
- remaining -= 1
40
- observer.on_next(value)
41
- if not remaining:
42
- observer.on_completed()
41
+ def on_next(value: _T) -> None:
42
+ nonlocal remaining
43
43
 
44
- return source.subscribe(
45
- on_next, observer.on_error, observer.on_completed, scheduler=scheduler
46
- )
44
+ if remaining > 0:
45
+ remaining -= 1
46
+ observer.on_next(value)
47
+ if not remaining:
48
+ observer.on_completed()
47
49
 
48
- return Observable(subscribe)
50
+ return source.subscribe(
51
+ on_next, observer.on_error, observer.on_completed, scheduler=scheduler
52
+ )
49
53
 
50
- return take
54
+ return Observable(subscribe)
51
55
 
52
56
 
53
57
  __all__ = ["take_"]
@@ -1,55 +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 take_last_(count: int) -> Callable[[Observable[_T]], Observable[_T]]:
9
- def take_last(source: Observable[_T]) -> Observable[_T]:
10
- """Returns a specified number of contiguous elements from the end of an
11
- observable sequence.
9
+ @curry_flip
10
+ def take_last_(source: Observable[_T], count: int) -> Observable[_T]:
11
+ """Returns a specified number of contiguous elements from the end of an
12
+ observable sequence.
12
13
 
13
- Example:
14
- >>> res = take_last(source)
14
+ Examples:
15
+ >>> res = source.pipe(take_last(5))
16
+ >>> res = take_last(5)(source)
15
17
 
16
- This operator accumulates a buffer with a length enough to store
17
- elements count elements. Upon completion of the source sequence, this
18
- buffer is drained on the result sequence. This causes the elements to be
19
- delayed.
18
+ This operator accumulates a buffer with a length enough to store
19
+ elements count elements. Upon completion of the source sequence, this
20
+ buffer is drained on the result sequence. This causes the elements to be
21
+ delayed.
20
22
 
21
- Args:
22
- source: Number of elements to take from the end of the source
23
+ Args:
24
+ source: The source observable sequence.
25
+ count: Number of elements to take from the end of the source
23
26
  sequence.
24
27
 
25
- Returns:
26
- An observable sequence containing the specified number of elements
27
- from the end of the source sequence.
28
- """
28
+ Returns:
29
+ An observable sequence containing the specified number of elements
30
+ from the end of the source sequence.
31
+ """
29
32
 
30
- def subscribe(
31
- observer: abc.ObserverBase[_T],
32
- scheduler: Optional[abc.SchedulerBase] = None,
33
- ) -> abc.DisposableBase:
34
- q: List[_T] = []
33
+ def subscribe(
34
+ observer: abc.ObserverBase[_T],
35
+ scheduler: abc.SchedulerBase | None = None,
36
+ ) -> abc.DisposableBase:
37
+ q: list[_T] = []
35
38
 
36
- def on_next(x: _T) -> None:
37
- q.append(x)
38
- if len(q) > count:
39
- q.pop(0)
39
+ def on_next(x: _T) -> None:
40
+ q.append(x)
41
+ if len(q) > count:
42
+ q.pop(0)
40
43
 
41
- def on_completed():
42
- while q:
43
- observer.on_next(q.pop(0))
44
- observer.on_completed()
44
+ def on_completed():
45
+ while q:
46
+ observer.on_next(q.pop(0))
47
+ observer.on_completed()
45
48
 
46
- return source.subscribe(
47
- on_next, observer.on_error, on_completed, scheduler=scheduler
48
- )
49
+ return source.subscribe(
50
+ on_next, observer.on_error, on_completed, scheduler=scheduler
51
+ )
49
52
 
50
- return Observable(subscribe)
51
-
52
- return take_last
53
+ return Observable(subscribe)
53
54
 
54
55
 
55
56
  __all__ = ["take_last_"]