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,12 +1,9 @@
1
- from typing import Optional
2
-
3
1
  from reactivex import Observable, abc, timer, typing
4
2
 
5
3
 
6
4
  def interval_(
7
- period: typing.RelativeTime, scheduler: Optional[abc.SchedulerBase] = None
5
+ period: typing.RelativeTime, scheduler: abc.SchedulerBase | None = None
8
6
  ) -> Observable[int]:
9
-
10
7
  return timer(period, period, scheduler)
11
8
 
12
9
 
@@ -1,7 +1,8 @@
1
1
  import re
2
2
  import threading
3
+ from collections.abc import Mapping
3
4
  from datetime import datetime, timedelta
4
- from typing import Any, List, Mapping, Optional, Tuple, Union
5
+ from typing import Any
5
6
 
6
7
  from reactivex import Notification, Observable, abc, notification, typing
7
8
  from reactivex.disposable import CompositeDisposable, Disposable
@@ -34,9 +35,9 @@ def hot(
34
35
  string: str,
35
36
  timespan: typing.RelativeTime = 0.1,
36
37
  duetime: typing.AbsoluteOrRelativeTime = 0.0,
37
- lookup: Optional[Mapping[Union[str, float], Any]] = None,
38
- error: Optional[Exception] = None,
39
- scheduler: Optional[abc.SchedulerBase] = None,
38
+ lookup: Mapping[str | float, Any] | None = None,
39
+ error: Exception | None = None,
40
+ scheduler: abc.SchedulerBase | None = None,
40
41
  ) -> Observable[Any]:
41
42
  _scheduler = scheduler or new_thread_scheduler
42
43
 
@@ -54,10 +55,10 @@ def hot(
54
55
 
55
56
  lock = threading.RLock()
56
57
  is_stopped = False
57
- observers: List[abc.ObserverBase[Any]] = []
58
+ observers: list[abc.ObserverBase[Any]] = []
58
59
 
59
60
  def subscribe(
60
- observer: abc.ObserverBase[Any], scheduler: Optional[abc.SchedulerBase] = None
61
+ observer: abc.ObserverBase[Any], scheduler: abc.SchedulerBase | None = None
61
62
  ) -> abc.DisposableBase:
62
63
  # should a hot observable already completed or on error
63
64
  # re-push on_completed/on_error at subscription time?
@@ -100,22 +101,22 @@ def hot(
100
101
  def from_marbles(
101
102
  string: str,
102
103
  timespan: typing.RelativeTime = 0.1,
103
- lookup: Optional[Mapping[Union[str, float], Any]] = None,
104
- error: Optional[Exception] = None,
105
- scheduler: Optional[abc.SchedulerBase] = None,
104
+ lookup: Mapping[str | float, Any] | None = None,
105
+ error: Exception | None = None,
106
+ scheduler: abc.SchedulerBase | None = None,
106
107
  ) -> Observable[Any]:
107
108
  messages = parse(
108
109
  string, timespan=timespan, lookup=lookup, error=error, raise_stopped=True
109
110
  )
110
111
 
111
112
  def subscribe(
112
- observer: abc.ObserverBase[Any], scheduler_: Optional[abc.SchedulerBase] = None
113
+ observer: abc.ObserverBase[Any], scheduler_: abc.SchedulerBase | None = None
113
114
  ) -> abc.DisposableBase:
114
115
  _scheduler = scheduler or scheduler_ or new_thread_scheduler
115
116
  disp = CompositeDisposable()
116
117
 
117
118
  def schedule_msg(
118
- message: Tuple[typing.RelativeTime, Notification[Any]]
119
+ message: tuple[typing.RelativeTime, Notification[Any]],
119
120
  ) -> None:
120
121
  duetime, notification = message
121
122
 
@@ -137,10 +138,10 @@ def parse(
137
138
  string: str,
138
139
  timespan: typing.RelativeTime = 1.0,
139
140
  time_shift: typing.RelativeTime = 0.0,
140
- lookup: Optional[Mapping[Union[str, float], Any]] = None,
141
- error: Optional[Exception] = None,
141
+ lookup: Mapping[str | float, Any] | None = None,
142
+ error: Exception | None = None,
142
143
  raise_stopped: bool = False,
143
- ) -> List[Tuple[typing.RelativeTime, notification.Notification[Any]]]:
144
+ ) -> list[tuple[typing.RelativeTime, notification.Notification[Any]]]:
144
145
  """Convert a marble diagram string to a list of messages.
145
146
 
146
147
  Each character in the string will advance time by timespan
@@ -209,7 +210,7 @@ def parse(
209
210
  string = string.replace(" ", "")
210
211
 
211
212
  # try to cast a string to an int, then to a float
212
- def try_number(element: str) -> Union[float, str]:
213
+ def try_number(element: str) -> float | str:
213
214
  try:
214
215
  return int(element)
215
216
  except ValueError:
@@ -220,7 +221,7 @@ def parse(
220
221
 
221
222
  def map_element(
222
223
  time: typing.RelativeTime, element: str
223
- ) -> Tuple[typing.RelativeTime, Notification[Any]]:
224
+ ) -> tuple[typing.RelativeTime, Notification[Any]]:
224
225
  if element == "|":
225
226
  return (time, notification.OnCompleted())
226
227
  elif element == "#":
@@ -242,7 +243,7 @@ def parse(
242
243
  is_stopped = True
243
244
 
244
245
  iframe = 0
245
- messages: List[Tuple[typing.RelativeTime, Notification[Any]]] = []
246
+ messages: list[tuple[typing.RelativeTime, Notification[Any]]] = []
246
247
 
247
248
  for results in tokens.findall(string):
248
249
  timestamp = iframe * timespan + time_shift
@@ -0,0 +1,32 @@
1
+ """Mixins for Observable method chaining.
2
+
3
+ This module contains mixin classes that provide operator methods for Observable.
4
+ Each mixin focuses on a specific category of operators, making the codebase
5
+ more maintainable and organized.
6
+ """
7
+
8
+ from .combination import CombinationMixin
9
+ from .conditional import ConditionalMixin
10
+ from .error_handling import ErrorHandlingMixin
11
+ from .filtering import FilteringMixin
12
+ from .mathematical import MathematicalMixin
13
+ from .multicasting import MulticastingMixin
14
+ from .testing import TestingMixin
15
+ from .time_based import TimeBasedMixin
16
+ from .transformation import TransformationMixin
17
+ from .utility import UtilityMixin
18
+ from .windowing import WindowingMixin
19
+
20
+ __all__ = [
21
+ "CombinationMixin",
22
+ "ConditionalMixin",
23
+ "ErrorHandlingMixin",
24
+ "FilteringMixin",
25
+ "MathematicalMixin",
26
+ "MulticastingMixin",
27
+ "TestingMixin",
28
+ "TimeBasedMixin",
29
+ "TransformationMixin",
30
+ "UtilityMixin",
31
+ "WindowingMixin",
32
+ ]
@@ -0,0 +1,481 @@
1
+ """Combination operators mixin for Observable."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable, Iterable
6
+ from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast
7
+
8
+ if TYPE_CHECKING:
9
+ from asyncio import Future
10
+
11
+ from reactivex.observable import Observable
12
+
13
+
14
+ _T = TypeVar("_T", covariant=True)
15
+ _T2 = TypeVar("_T2")
16
+
17
+
18
+ class CombinationMixin(Generic[_T]):
19
+ """Mixin providing combination operators for Observable.
20
+
21
+ This mixin adds operators that combine multiple observable sequences,
22
+ including merge, concat, zip, and various other combination strategies.
23
+ """
24
+
25
+ def _as_observable(self) -> Observable[_T]:
26
+ """Cast mixin instance to Observable preserving type parameter.
27
+
28
+ This is safe because this mixin is only ever used as part of the Observable
29
+ class through multiple inheritance. At runtime, `self` in mixin methods will
30
+ always be an Observable[_T] instance. The type checker cannot infer this
31
+ because it analyzes mixins in isolation.
32
+
33
+ Returns:
34
+ The instance cast to Observable[_T] for type-safe method access.
35
+ """
36
+ return cast("Observable[_T]", self)
37
+
38
+ def merge(
39
+ self, *sources: Observable[_T], max_concurrent: int | None = None
40
+ ) -> Observable[_T]:
41
+ """Merge with other observables.
42
+
43
+ Merges an observable sequence of observable sequences into an observable
44
+ sequence, limiting the number of concurrent subscriptions to inner sequences.
45
+
46
+ Examples:
47
+ Fluent style:
48
+ >>> result = source.merge(other1, other2)
49
+ >>> result = source.merge(other, max_concurrent=2)
50
+
51
+ Equivalent pipe style:
52
+ >>> from reactivex import operators as ops
53
+ >>> result = source.pipe(ops.merge(other1, other2))
54
+
55
+ Args:
56
+ *sources: Observable sequences to merge with the source.
57
+ max_concurrent: Maximum number of concurrent subscriptions.
58
+
59
+ Returns:
60
+ The observable sequence that merges the elements of the observable
61
+ sequences.
62
+
63
+ See Also:
64
+ - :func:`merge <reactivex.operators.merge>`
65
+ - :meth:`concat`
66
+ - :meth:`combine_latest`
67
+ """
68
+ from reactivex import operators as ops
69
+
70
+ return self._as_observable().pipe(
71
+ ops.merge(*sources, max_concurrent=max_concurrent)
72
+ )
73
+
74
+ def concat(self, *sources: Observable[_T]) -> Observable[_T]:
75
+ """Concatenate with other observables.
76
+
77
+ Concatenates all the observable sequences.
78
+
79
+ Examples:
80
+ Fluent style:
81
+ >>> result = source.concat(other1, other2)
82
+
83
+ Equivalent pipe style:
84
+ >>> from reactivex import operators as ops
85
+ >>> result = source.pipe(ops.concat(other1, other2))
86
+
87
+ Args:
88
+ *sources: Observable sequences to concatenate with the source.
89
+
90
+ Returns:
91
+ An observable sequence that contains the elements of each given
92
+ sequence, in sequential order.
93
+
94
+ See Also:
95
+ - :func:`concat <reactivex.operators.concat>`
96
+ - :meth:`merge`
97
+ - :meth:`concat_map`
98
+ """
99
+ from reactivex import operators as ops
100
+
101
+ return self._as_observable().pipe(ops.concat(*sources))
102
+
103
+ def zip(self, *sources: Observable[Any]) -> Observable[Any]:
104
+ """Zip with other observables.
105
+
106
+ Merges the specified observable sequences into one observable sequence
107
+ by creating a tuple whenever all of the observable sequences have
108
+ produced an element at a corresponding index.
109
+
110
+ Examples:
111
+ Fluent style:
112
+ >>> result = source.zip(other1, other2)
113
+
114
+ Equivalent pipe style:
115
+ >>> from reactivex import operators as ops
116
+ >>> result = source.pipe(ops.zip(other1, other2))
117
+
118
+ Args:
119
+ *sources: Observable sequences to zip with the source.
120
+
121
+ Returns:
122
+ An observable sequence containing the result of combining elements
123
+ of the sources as tuples.
124
+
125
+ See Also:
126
+ - :func:`zip <reactivex.operators.zip>`
127
+ - :meth:`combine_latest`
128
+ - :meth:`with_latest_from`
129
+ """
130
+ from reactivex import operators as ops
131
+
132
+ return self._as_observable().pipe(ops.zip(*sources))
133
+
134
+ def combine_latest(self, *sources: Observable[Any]) -> Observable[Any]:
135
+ """Combine latest values from observables.
136
+
137
+ Merges the specified observable sequences into one observable sequence
138
+ by creating a tuple whenever any of the observable sequences produces
139
+ an element.
140
+
141
+ Examples:
142
+ Fluent style:
143
+ >>> result = source.combine_latest(other1, other2)
144
+
145
+ Equivalent pipe style:
146
+ >>> from reactivex import operators as ops
147
+ >>> result = source.pipe(ops.combine_latest(other1, other2))
148
+
149
+ Args:
150
+ *sources: Observable sequences to combine with the source.
151
+
152
+ Returns:
153
+ An observable sequence containing the result of combining elements
154
+ of the sources as tuples.
155
+
156
+ See Also:
157
+ - :func:`combine_latest <reactivex.operators.combine_latest>`
158
+ - :meth:`zip`
159
+ - :meth:`with_latest_from`
160
+ """
161
+ from reactivex import operators as ops
162
+
163
+ return self._as_observable().pipe(ops.combine_latest(*sources))
164
+
165
+ def with_latest_from(self, *sources: Observable[Any]) -> Observable[Any]:
166
+ """Combine with latest values from other observables.
167
+
168
+ Merges the specified observable sequences into one observable sequence
169
+ by creating a tuple only when the first observable sequence (self)
170
+ produces an element.
171
+
172
+ Examples:
173
+ Fluent style:
174
+ >>> result = source.with_latest_from(other1, other2)
175
+
176
+ Equivalent pipe style:
177
+ >>> from reactivex import operators as ops
178
+ >>> result = source.pipe(ops.with_latest_from(other1, other2))
179
+
180
+ Args:
181
+ *sources: Observable sequences whose latest values to include.
182
+
183
+ Returns:
184
+ An observable sequence containing the result of combining the source
185
+ with the latest values from other sources as tuples.
186
+
187
+ See Also:
188
+ - :func:`with_latest_from <reactivex.operators.with_latest_from>`
189
+ - :meth:`combine_latest`
190
+ """
191
+ from reactivex import operators as ops
192
+
193
+ return self._as_observable().pipe(ops.with_latest_from(*sources))
194
+
195
+ def start_with(self, *args: Any) -> Observable[Any]:
196
+ """Prepend values to the sequence.
197
+
198
+ Prepends a sequence of values to an observable sequence.
199
+
200
+ Examples:
201
+ Fluent style:
202
+ >>> result = source.start_with(1, 2, 3)
203
+
204
+ Equivalent pipe style:
205
+ >>> from reactivex import operators as ops
206
+ >>> result = source.pipe(ops.start_with(1, 2, 3))
207
+
208
+ Args:
209
+ *args: Values to prepend to the observable sequence.
210
+
211
+ Returns:
212
+ The source sequence prepended with the specified values.
213
+
214
+ See Also:
215
+ - :func:`start_with <reactivex.operators.start_with>`
216
+ """
217
+ from reactivex import operators as ops
218
+
219
+ return self._as_observable().pipe(ops.start_with(*args))
220
+
221
+ def fork_join(self, *others: Observable[Any]) -> Observable[tuple[Any, ...]]:
222
+ """Wait for all observables to complete and combine last values.
223
+
224
+ Wait for observables to complete and then combine last values
225
+ they emitted into a tuple. Whenever any of those observables
226
+ completes without emitting any value, result sequence will
227
+ complete at that moment as well.
228
+
229
+ Examples:
230
+ Fluent style:
231
+ >>> result = source.fork_join(observable2, observable3)
232
+
233
+ Equivalent pipe style:
234
+ >>> from reactivex import operators as ops
235
+ >>> result = source.pipe(ops.fork_join(observable2, observable3))
236
+
237
+ Args:
238
+ *others: Other observable sequences to combine with.
239
+
240
+ Returns:
241
+ An observable sequence containing a tuple with the last elements
242
+ from all sequences.
243
+
244
+ See Also:
245
+ - :func:`fork_join <reactivex.operators.fork_join>`
246
+ - :meth:`zip`
247
+ - :meth:`combine_latest`
248
+ """
249
+ from reactivex import operators as ops
250
+
251
+ return self._as_observable().pipe(ops.fork_join(*others))
252
+
253
+ def switch_latest(self) -> Observable[Any]:
254
+ """Switch to the most recent inner observable.
255
+
256
+ Transforms an observable sequence of observable sequences into an
257
+ observable sequence producing values only from the most recent
258
+ observable sequence.
259
+
260
+ Examples:
261
+ Fluent style:
262
+ >>> result = source_of_observables.switch_latest()
263
+
264
+ Equivalent pipe style:
265
+ >>> from reactivex import operators as ops
266
+ >>> result = source.pipe(ops.switch_latest())
267
+
268
+ Returns:
269
+ The observable sequence that at any point in time produces the
270
+ elements of the most recent inner observable sequence that has
271
+ been received.
272
+
273
+ See Also:
274
+ - :func:`switch_latest <reactivex.operators.switch_latest>`
275
+ - :meth:`switch_map`
276
+ - :meth:`merge`
277
+ """
278
+ # Cast is safe: switch_latest is meant to be called on Observable
279
+ # of Observables. The fluent API allows chaining this on nested
280
+ # observable sequences. The cast preserves type safety for the
281
+ # intended use case where _T is an Observable or Future.
282
+
283
+ from reactivex import operators as ops
284
+
285
+ source: Observable[Observable[Any] | Future[Any]] = cast(
286
+ "Observable[Observable[Any] | Future[Any]]", self._as_observable()
287
+ )
288
+ return ops.switch_latest()(source)
289
+
290
+ def amb(self, right_source: Observable[_T]) -> Observable[_T]:
291
+ """Propagate the observable that reacts first.
292
+
293
+ Propagates the observable sequence that reacts first.
294
+
295
+ Examples:
296
+ Fluent style:
297
+ >>> result = source1.amb(source2)
298
+
299
+ Equivalent pipe style:
300
+ >>> from reactivex import operators as ops
301
+ >>> result = source1.pipe(ops.amb(source2))
302
+
303
+ Args:
304
+ right_source: Second observable sequence.
305
+
306
+ Returns:
307
+ An observable sequence that surfaces any of the given sequences,
308
+ whichever reacted first.
309
+
310
+ See Also:
311
+ - :func:`amb <reactivex.operators.amb>`
312
+ """
313
+ from reactivex import operators as ops
314
+
315
+ return self._as_observable().pipe(ops.amb(right_source))
316
+
317
+ def merge_all(self) -> Observable[Any]:
318
+ """Merge all inner observables.
319
+
320
+ Merges an observable sequence of observable sequences into an observable
321
+ sequence.
322
+
323
+ Examples:
324
+ Fluent style:
325
+ >>> result = source_of_sources.merge_all()
326
+
327
+ Equivalent pipe style:
328
+ >>> from reactivex import operators as ops
329
+ >>> result = source_of_sources.pipe(ops.merge_all())
330
+
331
+ Returns:
332
+ An observable sequence that merges the elements of the inner sequences.
333
+
334
+ See Also:
335
+ - :func:`merge_all <reactivex.operators.merge_all>`
336
+ - :meth:`merge`
337
+ - :meth:`concat_all`
338
+ """
339
+ # Cast is safe: merge_all is meant to be called on Observable of Observables.
340
+ # The fluent API allows chaining this on nested observable sequences where
341
+ # _T is Observable[_T2]. We return Observable[Any] as the inner type cannot
342
+ # be statically inferred from _T without higher-kinded types.
343
+ from reactivex import operators as ops
344
+
345
+ op: Callable[[Observable[Any]], Observable[Any]] = cast(
346
+ "Callable[[Observable[Any]], Observable[Any]]", ops.merge_all()
347
+ )
348
+ return self._as_observable().pipe(op)
349
+
350
+ def zip_with_iterable(self, second: Iterable[_T2]) -> Observable[tuple[_T, _T2]]:
351
+ """Zip with iterable.
352
+
353
+ Merges the specified observable sequence and iterable into one observable
354
+ sequence by creating a tuple whenever both sequences have produced an element
355
+ at a corresponding index.
356
+
357
+ Examples:
358
+ Fluent style:
359
+ >>> result = source.zip_with_iterable([1, 2, 3])
360
+
361
+ Equivalent pipe style:
362
+ >>> from reactivex import operators as ops
363
+ >>> result = source.pipe(ops.zip_with_iterable([1, 2, 3]))
364
+
365
+ Args:
366
+ second: Iterable to zip with the source observable.
367
+
368
+ Returns:
369
+ An observable sequence containing the result of combining elements of the
370
+ sources as a tuple.
371
+
372
+ See Also:
373
+ - :func:`zip_with_iterable <reactivex.operators.zip_with_iterable>`
374
+ - :meth:`zip`
375
+ """
376
+ from reactivex import operators as ops
377
+
378
+ return self._as_observable().pipe(ops.zip_with_iterable(second))
379
+
380
+ def join(
381
+ self,
382
+ right: Observable[_T2],
383
+ left_duration_mapper: Callable[[_T], Observable[Any]],
384
+ right_duration_mapper: Callable[[_T2], Observable[Any]],
385
+ ) -> Observable[tuple[_T, _T2]]:
386
+ """Join based on overlapping durations.
387
+
388
+ Correlates the elements of two sequences based on overlapping durations.
389
+
390
+ Examples:
391
+ Fluent style:
392
+ >>> result = left.join(
393
+ ... right,
394
+ ... lambda x: rx.timer(0.5),
395
+ ... lambda x: rx.timer(0.5)
396
+ ... )
397
+
398
+ Equivalent pipe style:
399
+ >>> from reactivex import operators as ops
400
+ >>> result = left.pipe(
401
+ ... ops.join(
402
+ ... right,
403
+ ... lambda x: rx.timer(0.5),
404
+ ... lambda x: rx.timer(0.5)
405
+ ... )
406
+ ... )
407
+
408
+ Args:
409
+ right: The right observable sequence to join elements for.
410
+ left_duration_mapper: A function to select the duration (expressed as an
411
+ observable sequence) of each element of the left observable sequence,
412
+ used to determine overlap.
413
+ right_duration_mapper: A function to select the duration (expressed as an
414
+ observable sequence) of each element of the right observable sequence,
415
+ used to determine overlap.
416
+
417
+ Returns:
418
+ An observable sequence that contains elements combined into a tuple from
419
+ source elements that have an overlapping duration.
420
+
421
+ See Also:
422
+ - :func:`join <reactivex.operators.join>`
423
+ - :meth:`group_join`
424
+ """
425
+ from reactivex import operators as ops
426
+
427
+ return self._as_observable().pipe(
428
+ ops.join(right, left_duration_mapper, right_duration_mapper)
429
+ )
430
+
431
+ def group_join(
432
+ self,
433
+ right: Observable[_T2],
434
+ left_duration_mapper: Callable[[_T], Observable[Any]],
435
+ right_duration_mapper: Callable[[_T2], Observable[Any]],
436
+ ) -> Observable[tuple[_T, Observable[_T2]]]:
437
+ """Group join based on overlapping durations.
438
+
439
+ Correlates the elements of two sequences based on overlapping durations, and
440
+ groups the results.
441
+
442
+ Examples:
443
+ Fluent style:
444
+ >>> result = left.group_join(
445
+ ... right,
446
+ ... lambda x: rx.timer(0.5),
447
+ ... lambda x: rx.timer(0.5)
448
+ ... )
449
+
450
+ Equivalent pipe style:
451
+ >>> from reactivex import operators as ops
452
+ >>> result = left.pipe(
453
+ ... ops.group_join(
454
+ ... right,
455
+ ... lambda x: rx.timer(0.5),
456
+ ... lambda x: rx.timer(0.5)
457
+ ... )
458
+ ... )
459
+
460
+ Args:
461
+ right: The right observable sequence to join elements for.
462
+ left_duration_mapper: A function to select the duration (expressed as an
463
+ observable sequence) of each element of the left observable sequence,
464
+ used to determine overlap.
465
+ right_duration_mapper: A function to select the duration (expressed as an
466
+ observable sequence) of each element of the right observable sequence,
467
+ used to determine overlap.
468
+
469
+ Returns:
470
+ An observable sequence that contains elements combined into a tuple from
471
+ source elements that have an overlapping duration.
472
+
473
+ See Also:
474
+ - :func:`group_join <reactivex.operators.group_join>`
475
+ - :meth:`join`
476
+ """
477
+ from reactivex import operators as ops
478
+
479
+ return self._as_observable().pipe(
480
+ ops.group_join(right, left_duration_mapper, right_duration_mapper)
481
+ )