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
@@ -0,0 +1,135 @@
1
+ """Conditional operators mixin for Observable."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast, overload
7
+
8
+ if TYPE_CHECKING:
9
+ from reactivex.observable import Observable
10
+
11
+
12
+ _T = TypeVar("_T", covariant=True)
13
+ _A = TypeVar("_A")
14
+
15
+
16
+ class ConditionalMixin(Generic[_T]):
17
+ """Mixin providing conditional operators for Observable.
18
+
19
+ This mixin adds operators that conditionally process or emit elements
20
+ based on various conditions.
21
+ """
22
+
23
+ def _as_observable(self) -> Observable[_T]:
24
+ """Cast mixin instance to Observable preserving type parameter.
25
+
26
+ This is safe because this mixin is only ever used as part of the Observable
27
+ class through multiple inheritance. At runtime, `self` in mixin methods will
28
+ always be an Observable[_T] instance. The type checker cannot infer this
29
+ because it analyzes mixins in isolation.
30
+
31
+ Returns:
32
+ The instance cast to Observable[_T] for type-safe method access.
33
+ """
34
+ return cast("Observable[_T]", self)
35
+
36
+ @overload
37
+ def default_if_empty(self, default_value: _A) -> Observable[_T | _A]: ...
38
+
39
+ @overload
40
+ def default_if_empty(self) -> Observable[_T | None]: ...
41
+
42
+ def default_if_empty(self, default_value: Any = None) -> Observable[Any]:
43
+ """Return default value if observable is empty.
44
+
45
+ Returns the elements of the specified sequence or the specified value in
46
+ a singleton sequence if the sequence is empty.
47
+
48
+ Examples:
49
+ Fluent style:
50
+ >>> result = source.default_if_empty(42)
51
+ >>> result = source.default_if_empty() # Defaults to None
52
+
53
+ Equivalent pipe style:
54
+ >>> from reactivex import operators as ops
55
+ >>> result = source.pipe(ops.default_if_empty(42))
56
+
57
+ Args:
58
+ default_value: The value to return if the sequence is empty.
59
+
60
+ Returns:
61
+ An observable sequence that contains the specified default value if
62
+ the source is empty; otherwise, the elements of the source.
63
+
64
+ See Also:
65
+ - :func:`default_if_empty <reactivex.operators.default_if_empty>`
66
+ """
67
+ from reactivex import operators as ops
68
+
69
+ return self._as_observable().pipe(ops.default_if_empty(default_value))
70
+
71
+ def find(
72
+ self, predicate: Callable[[_T, int, Observable[_T]], bool]
73
+ ) -> Observable[_T | None]:
74
+ """Find first element matching predicate.
75
+
76
+ Searches for an element that matches the conditions defined by the
77
+ specified predicate, and returns the first occurrence within the entire
78
+ Observable sequence.
79
+
80
+ Examples:
81
+ Fluent style:
82
+ >>> result = source.find(lambda x, i, obs: x > 3)
83
+
84
+ Equivalent pipe style:
85
+ >>> from reactivex import operators as ops
86
+ >>> result = source.pipe(ops.find(lambda x, i, obs: x > 3))
87
+
88
+ Args:
89
+ predicate: The predicate that defines the conditions of the element to
90
+ search for. Takes (value, index, source).
91
+
92
+ Returns:
93
+ An observable sequence with the first element that matches the conditions
94
+ defined by the specified predicate, if found; otherwise, None.
95
+
96
+ See Also:
97
+ - :func:`find <reactivex.operators.find>`
98
+ - :meth:`find_index`
99
+ """
100
+ from reactivex import operators as ops
101
+
102
+ return self._as_observable().pipe(ops.find(predicate))
103
+
104
+ def find_index(
105
+ self, predicate: Callable[[_T, int, Observable[_T]], bool]
106
+ ) -> Observable[int | None]:
107
+ """Find index of first element matching predicate.
108
+
109
+ Searches for an element that matches the conditions defined by the specified
110
+ predicate, and returns an Observable sequence with the zero-based index of
111
+ the first occurrence within the entire Observable sequence.
112
+
113
+ Examples:
114
+ Fluent style:
115
+ >>> result = source.find_index(lambda x, i, obs: x > 3)
116
+
117
+ Equivalent pipe style:
118
+ >>> from reactivex import operators as ops
119
+ >>> result = source.pipe(ops.find_index(lambda x, i, obs: x > 3))
120
+
121
+ Args:
122
+ predicate: The predicate that defines the conditions of the element to
123
+ search for. Takes (value, index, source).
124
+
125
+ Returns:
126
+ An observable sequence with the zero-based index of the first element
127
+ that matches the conditions; if not found, returns -1.
128
+
129
+ See Also:
130
+ - :func:`find_index <reactivex.operators.find_index>`
131
+ - :meth:`find`
132
+ """
133
+ from reactivex import operators as ops
134
+
135
+ return self._as_observable().pipe(ops.find_index(predicate))
@@ -0,0 +1,130 @@
1
+ """Error handling operators mixin for Observable."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from collections.abc import Callable
6
+ from typing import TYPE_CHECKING, Generic, TypeVar, cast
7
+
8
+ if TYPE_CHECKING:
9
+ from reactivex.observable import Observable
10
+
11
+
12
+ _T = TypeVar("_T", covariant=True)
13
+
14
+
15
+ class ErrorHandlingMixin(Generic[_T]):
16
+ """Mixin providing error handling operators for Observable.
17
+
18
+ This mixin adds operators that handle errors, retries, and fallback behavior
19
+ when observables encounter exceptions.
20
+ """
21
+
22
+ def _as_observable(self) -> Observable[_T]:
23
+ """Cast mixin instance to Observable preserving type parameter.
24
+
25
+ This is safe because this mixin is only ever used as part of the Observable
26
+ class through multiple inheritance. At runtime, `self` in mixin methods will
27
+ always be an Observable[_T] instance. The type checker cannot infer this
28
+ because it analyzes mixins in isolation.
29
+
30
+ Returns:
31
+ The instance cast to Observable[_T] for type-safe method access.
32
+ """
33
+ return cast("Observable[_T]", self)
34
+
35
+ def catch(
36
+ self,
37
+ handler: Observable[_T] | Callable[[Exception, Observable[_T]], Observable[_T]],
38
+ ) -> Observable[_T]:
39
+ """Handle errors by switching to another observable.
40
+
41
+ Continues an observable sequence that is terminated by an exception with
42
+ the next observable sequence.
43
+
44
+ Examples:
45
+ Fluent style:
46
+ >>> result = source.catch(fallback_observable)
47
+ >>> result = source.catch(lambda ex, src: handle_error(ex))
48
+
49
+ Equivalent pipe style:
50
+ >>> from reactivex import operators as ops
51
+ >>> result = source.pipe(ops.catch(fallback_observable))
52
+
53
+ Args:
54
+ handler: Exception handler function or a second observable sequence
55
+ used to produce results when an error occurs.
56
+
57
+ Returns:
58
+ An observable sequence containing the source sequence's elements,
59
+ followed by the elements of the handler sequence in case an exception
60
+ occurred.
61
+
62
+ See Also:
63
+ - :func:`catch <reactivex.operators.catch>`
64
+ - :meth:`retry`
65
+ - :meth:`on_error_resume_next`
66
+ """
67
+ from reactivex import operators as ops
68
+
69
+ return self._as_observable().pipe(ops.catch(handler))
70
+
71
+ def retry(self, retry_count: int | None = None) -> Observable[_T]:
72
+ """Retry on error.
73
+
74
+ Repeats the source observable sequence the specified number of times or
75
+ until it successfully terminates.
76
+
77
+ Examples:
78
+ Fluent style:
79
+ >>> result = source.retry(3)
80
+ >>> result = source.retry() # Retry indefinitely
81
+
82
+ Equivalent pipe style:
83
+ >>> from reactivex import operators as ops
84
+ >>> result = source.pipe(ops.retry(3))
85
+
86
+ Args:
87
+ retry_count: Number of times to retry. If not specified, retries
88
+ indefinitely.
89
+
90
+ Returns:
91
+ An observable sequence producing the elements of the given sequence
92
+ repeatedly until it terminates successfully.
93
+
94
+ See Also:
95
+ - :func:`retry <reactivex.operators.retry>`
96
+ - :meth:`catch`
97
+ """
98
+ from reactivex import operators as ops
99
+
100
+ return self._as_observable().pipe(ops.retry(retry_count))
101
+
102
+ def on_error_resume_next(self, second: Observable[_T]) -> Observable[_T]:
103
+ """Continue with another observable on error or completion.
104
+
105
+ Continues an observable sequence that is terminated normally or by an
106
+ exception with the next observable sequence.
107
+
108
+ Examples:
109
+ Fluent style:
110
+ >>> result = source.on_error_resume_next(fallback)
111
+
112
+ Equivalent pipe style:
113
+ >>> from reactivex import operators as ops
114
+ >>> result = source.pipe(ops.on_error_resume_next(fallback))
115
+
116
+ Args:
117
+ second: Second observable sequence used to produce results after the
118
+ first sequence terminates.
119
+
120
+ Returns:
121
+ An observable sequence that concatenates the first and second sequence,
122
+ even if the first sequence terminates exceptionally.
123
+
124
+ See Also:
125
+ - :func:`on_error_resume_next <reactivex.operators.on_error_resume_next>`
126
+ - :meth:`catch`
127
+ """
128
+ from reactivex import operators as ops
129
+
130
+ return self._as_observable().pipe(ops.on_error_resume_next(second))