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.
- reactivex/__init__.py +35 -39
- reactivex/_version.py +1 -1
- reactivex/abc/disposable.py +3 -4
- reactivex/abc/observable.py +13 -6
- reactivex/abc/observer.py +2 -1
- reactivex/abc/periodicscheduler.py +7 -6
- reactivex/abc/scheduler.py +10 -9
- reactivex/abc/subject.py +5 -5
- reactivex/disposable/compositedisposable.py +4 -4
- reactivex/disposable/disposable.py +1 -2
- reactivex/disposable/multipleassignmentdisposable.py +2 -3
- reactivex/disposable/refcountdisposable.py +1 -2
- reactivex/disposable/serialdisposable.py +4 -5
- reactivex/disposable/singleassignmentdisposable.py +3 -4
- reactivex/internal/__init__.py +2 -0
- reactivex/internal/basic.py +2 -2
- reactivex/internal/concurrency.py +2 -1
- reactivex/internal/curry.py +59 -0
- reactivex/internal/exceptions.py +7 -12
- reactivex/internal/priorityqueue.py +2 -2
- reactivex/internal/utils.py +3 -2
- reactivex/notification.py +22 -21
- reactivex/observable/case.py +5 -6
- reactivex/observable/catch.py +3 -2
- reactivex/observable/combinelatest.py +4 -5
- reactivex/observable/concat.py +3 -2
- reactivex/observable/connectableobservable.py +7 -7
- reactivex/observable/defer.py +4 -3
- reactivex/observable/empty.py +3 -4
- reactivex/observable/forkjoin.py +5 -5
- reactivex/observable/fromcallback.py +4 -3
- reactivex/observable/fromfuture.py +2 -2
- reactivex/observable/fromiterable.py +4 -3
- reactivex/observable/generate.py +2 -2
- reactivex/observable/generatewithrelativetime.py +4 -3
- reactivex/observable/groupedobservable.py +4 -4
- reactivex/observable/ifthen.py +3 -2
- reactivex/observable/interval.py +1 -4
- reactivex/observable/marbles.py +18 -17
- reactivex/observable/mixins/__init__.py +32 -0
- reactivex/observable/mixins/combination.py +481 -0
- reactivex/observable/mixins/conditional.py +135 -0
- reactivex/observable/mixins/error_handling.py +130 -0
- reactivex/observable/mixins/filtering.py +1119 -0
- reactivex/observable/mixins/mathematical.py +277 -0
- reactivex/observable/mixins/multicasting.py +306 -0
- reactivex/observable/mixins/testing.py +193 -0
- reactivex/observable/mixins/time_based.py +209 -0
- reactivex/observable/mixins/transformation.py +632 -0
- reactivex/observable/mixins/utility.py +811 -0
- reactivex/observable/mixins/windowing.py +688 -0
- reactivex/observable/never.py +2 -2
- reactivex/observable/observable.py +72 -25
- reactivex/observable/onerrorresumenext.py +7 -6
- reactivex/observable/range.py +6 -6
- reactivex/observable/repeat.py +2 -2
- reactivex/observable/returnvalue.py +6 -5
- reactivex/observable/start.py +3 -2
- reactivex/observable/startasync.py +2 -1
- reactivex/observable/throw.py +3 -3
- reactivex/observable/timer.py +12 -12
- reactivex/observable/toasync.py +3 -2
- reactivex/observable/using.py +5 -4
- reactivex/observable/withlatestfrom.py +4 -5
- reactivex/observable/zip.py +7 -6
- reactivex/observer/autodetachobserver.py +4 -4
- reactivex/observer/observer.py +5 -4
- reactivex/observer/scheduledobserver.py +2 -2
- reactivex/operators/__init__.py +162 -208
- reactivex/operators/_all.py +23 -6
- reactivex/operators/_amb.py +88 -75
- reactivex/operators/_asobservable.py +20 -17
- reactivex/operators/_average.py +48 -45
- reactivex/operators/_buffer.py +81 -35
- reactivex/operators/_bufferwithtime.py +29 -9
- reactivex/operators/_bufferwithtimeorcount.py +27 -8
- reactivex/operators/_catch.py +33 -32
- reactivex/operators/_combinelatest.py +28 -20
- reactivex/operators/_concat.py +16 -13
- reactivex/operators/_contains.py +25 -6
- reactivex/operators/_count.py +24 -8
- reactivex/operators/_debounce.py +141 -138
- reactivex/operators/_defaultifempty.py +45 -42
- reactivex/operators/_delay.py +24 -23
- reactivex/operators/_delaysubscription.py +23 -21
- reactivex/operators/_delaywithmapper.py +10 -11
- reactivex/operators/_dematerialize.py +25 -21
- reactivex/operators/_distinct.py +50 -46
- reactivex/operators/_distinctuntilchanged.py +60 -57
- reactivex/operators/_do.py +123 -116
- reactivex/operators/_dowhile.py +3 -2
- reactivex/operators/_elementatordefault.py +57 -33
- reactivex/operators/_exclusive.py +59 -53
- reactivex/operators/_expand.py +82 -77
- reactivex/operators/_filter.py +63 -68
- reactivex/operators/_finallyaction.py +3 -2
- reactivex/operators/_find.py +49 -32
- reactivex/operators/_first.py +18 -11
- reactivex/operators/_firstordefault.py +5 -4
- reactivex/operators/_flatmap.py +89 -83
- reactivex/operators/_forkjoin.py +23 -18
- reactivex/operators/_groupby.py +27 -6
- reactivex/operators/_groupbyuntil.py +8 -5
- reactivex/operators/_groupjoin.py +7 -6
- reactivex/operators/_ignoreelements.py +20 -15
- reactivex/operators/_isempty.py +15 -4
- reactivex/operators/_join.py +6 -5
- reactivex/operators/_last.py +36 -31
- reactivex/operators/_lastordefault.py +8 -8
- reactivex/operators/_map.py +54 -39
- reactivex/operators/_materialize.py +30 -31
- reactivex/operators/_max.py +18 -11
- reactivex/operators/_maxby.py +5 -5
- reactivex/operators/_merge.py +132 -129
- reactivex/operators/_min.py +16 -10
- reactivex/operators/_minby.py +9 -8
- reactivex/operators/_multicast.py +9 -9
- reactivex/operators/_observeon.py +35 -31
- reactivex/operators/_onerrorresumenext.py +2 -1
- reactivex/operators/_pairwise.py +38 -34
- reactivex/operators/_partition.py +80 -73
- reactivex/operators/_pluck.py +4 -3
- reactivex/operators/_publish.py +36 -21
- reactivex/operators/_publishvalue.py +8 -7
- reactivex/operators/_reduce.py +16 -12
- reactivex/operators/_repeat.py +33 -30
- reactivex/operators/_replay.py +9 -9
- reactivex/operators/_retry.py +12 -10
- reactivex/operators/_sample.py +31 -27
- reactivex/operators/_scan.py +41 -39
- reactivex/operators/_sequenceequal.py +8 -7
- reactivex/operators/_single.py +20 -13
- reactivex/operators/_singleordefault.py +6 -5
- reactivex/operators/_skip.py +35 -32
- reactivex/operators/_skiplast.py +38 -34
- reactivex/operators/_skiplastwithtime.py +5 -4
- reactivex/operators/_skipuntil.py +40 -35
- reactivex/operators/_skipuntilwithtime.py +4 -3
- reactivex/operators/_skipwhile.py +65 -44
- reactivex/operators/_skipwithtime.py +50 -46
- reactivex/operators/_slice.py +58 -53
- reactivex/operators/_some.py +48 -47
- reactivex/operators/_startswith.py +17 -15
- reactivex/operators/_subscribeon.py +44 -41
- reactivex/operators/_sum.py +23 -6
- reactivex/operators/_switchlatest.py +71 -69
- reactivex/operators/_take.py +37 -33
- reactivex/operators/_takelast.py +37 -36
- reactivex/operators/_takelastbuffer.py +38 -37
- reactivex/operators/_takelastwithtime.py +60 -56
- reactivex/operators/_takeuntil.py +33 -32
- reactivex/operators/_takeuntilwithtime.py +42 -39
- reactivex/operators/_takewhile.py +108 -100
- reactivex/operators/_takewithtime.py +46 -41
- reactivex/operators/_throttlefirst.py +52 -45
- reactivex/operators/_timeinterval.py +40 -36
- reactivex/operators/_timeout.py +81 -79
- reactivex/operators/_timeoutwithmapper.py +6 -5
- reactivex/operators/_timestamp.py +24 -22
- reactivex/operators/_todict.py +51 -43
- reactivex/operators/_tofuture.py +24 -15
- reactivex/operators/_toiterable.py +33 -27
- reactivex/operators/_tomarbles.py +5 -5
- reactivex/operators/_toset.py +29 -19
- reactivex/operators/_whiledo.py +2 -1
- reactivex/operators/_window.py +100 -99
- reactivex/operators/_windowwithcount.py +56 -54
- reactivex/operators/_windowwithtime.py +95 -79
- reactivex/operators/_windowwithtimeorcount.py +85 -69
- reactivex/operators/_withlatestfrom.py +13 -9
- reactivex/operators/_zip.py +67 -63
- reactivex/operators/connectable/_refcount.py +4 -3
- reactivex/pipe.py +2 -1
- reactivex/run.py +8 -4
- reactivex/scheduler/catchscheduler.py +11 -10
- reactivex/scheduler/currentthreadscheduler.py +2 -3
- reactivex/scheduler/eventloop/asyncioscheduler.py +7 -6
- reactivex/scheduler/eventloop/asynciothreadsafescheduler.py +12 -14
- reactivex/scheduler/eventloop/eventletscheduler.py +4 -4
- reactivex/scheduler/eventloop/geventscheduler.py +4 -4
- reactivex/scheduler/eventloop/ioloopscheduler.py +4 -4
- reactivex/scheduler/eventloop/twistedscheduler.py +4 -4
- reactivex/scheduler/eventloopscheduler.py +9 -12
- reactivex/scheduler/historicalscheduler.py +1 -2
- reactivex/scheduler/immediatescheduler.py +5 -4
- reactivex/scheduler/mainloop/gtkscheduler.py +6 -7
- reactivex/scheduler/mainloop/pygamescheduler.py +4 -4
- reactivex/scheduler/mainloop/qtscheduler.py +6 -6
- reactivex/scheduler/mainloop/tkinterscheduler.py +4 -4
- reactivex/scheduler/mainloop/wxscheduler.py +7 -7
- reactivex/scheduler/newthreadscheduler.py +6 -8
- reactivex/scheduler/periodicscheduler.py +4 -4
- reactivex/scheduler/scheduleditem.py +4 -4
- reactivex/scheduler/scheduler.py +5 -5
- reactivex/scheduler/threadpoolscheduler.py +3 -3
- reactivex/scheduler/timeoutscheduler.py +5 -4
- reactivex/scheduler/trampoline.py +1 -2
- reactivex/scheduler/trampolinescheduler.py +5 -6
- reactivex/scheduler/virtualtimescheduler.py +4 -4
- reactivex/subject/asyncsubject.py +2 -2
- reactivex/subject/behaviorsubject.py +2 -2
- reactivex/subject/innersubscription.py +2 -2
- reactivex/subject/replaysubject.py +8 -8
- reactivex/subject/subject.py +4 -4
- reactivex/testing/coldobservable.py +5 -5
- reactivex/testing/hotobservable.py +6 -6
- reactivex/testing/marbles.py +21 -20
- reactivex/testing/mockdisposable.py +1 -3
- reactivex/testing/mockobserver.py +2 -2
- reactivex/testing/reactivetest.py +2 -2
- reactivex/testing/recorded.py +1 -1
- reactivex/testing/subscription.py +3 -3
- reactivex/testing/testscheduler.py +13 -12
- reactivex/typing.py +25 -14
- {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/METADATA +59 -26
- reactivex-5.0.0a2.dist-info/RECORD +236 -0
- {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/WHEEL +1 -1
- reactivex-4.1.0.dist-info/RECORD +0 -223
- {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,277 @@
|
|
|
1
|
+
"""Mathematical operators mixin for Observable."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast, overload
|
|
6
|
+
|
|
7
|
+
from reactivex import typing
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from reactivex.observable import Observable
|
|
11
|
+
|
|
12
|
+
_T = TypeVar("_T", covariant=True)
|
|
13
|
+
_TKey = TypeVar("_TKey")
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class MathematicalMixin(Generic[_T]):
|
|
17
|
+
"""Mixin providing mathematical operators for Observable.
|
|
18
|
+
|
|
19
|
+
This mixin adds operators that perform mathematical operations on sequences,
|
|
20
|
+
including counting, summing, averaging, and finding minimum/maximum values.
|
|
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
|
+
def count(self, predicate: typing.Predicate[_T] | None = None) -> Observable[int]:
|
|
37
|
+
"""Count the number of elements, optionally satisfying a predicate.
|
|
38
|
+
|
|
39
|
+
Returns an observable sequence containing a value that represents how many
|
|
40
|
+
elements in the specified observable sequence satisfy a condition if provided,
|
|
41
|
+
else the count of items.
|
|
42
|
+
|
|
43
|
+
Examples:
|
|
44
|
+
Fluent style:
|
|
45
|
+
>>> result = source.count()
|
|
46
|
+
>>> result = source.count(lambda x: x > 5)
|
|
47
|
+
|
|
48
|
+
Equivalent pipe style:
|
|
49
|
+
>>> from reactivex import operators as ops
|
|
50
|
+
>>> result = source.pipe(ops.count())
|
|
51
|
+
|
|
52
|
+
Args:
|
|
53
|
+
predicate: Optional function to test each source element for a condition.
|
|
54
|
+
|
|
55
|
+
Returns:
|
|
56
|
+
An observable sequence containing a single element with the number
|
|
57
|
+
of elements in the source sequence that satisfy the condition.
|
|
58
|
+
|
|
59
|
+
See Also:
|
|
60
|
+
- :func:`count <reactivex.operators.count>`
|
|
61
|
+
- :meth:`reduce`
|
|
62
|
+
"""
|
|
63
|
+
from reactivex import operators as ops
|
|
64
|
+
|
|
65
|
+
return self._as_observable().pipe(ops.count(predicate))
|
|
66
|
+
|
|
67
|
+
@overload
|
|
68
|
+
def sum(self) -> Observable[float]: ...
|
|
69
|
+
|
|
70
|
+
@overload
|
|
71
|
+
def sum(self, key_mapper: typing.Mapper[_T, float]) -> Observable[float]: ...
|
|
72
|
+
|
|
73
|
+
def sum(
|
|
74
|
+
self, key_mapper: typing.Mapper[Any, float] | None = None
|
|
75
|
+
) -> Observable[float]:
|
|
76
|
+
"""Compute the sum of the sequence.
|
|
77
|
+
|
|
78
|
+
Computes the sum of a sequence of values that are obtained by invoking an
|
|
79
|
+
optional transform function on each element of the input sequence, else if
|
|
80
|
+
not specified computes the sum on each item in the sequence.
|
|
81
|
+
|
|
82
|
+
Examples:
|
|
83
|
+
Fluent style:
|
|
84
|
+
>>> result = rx.of(1, 2, 3, 4, 5).sum()
|
|
85
|
+
>>> result = source.sum(lambda x: x.value)
|
|
86
|
+
|
|
87
|
+
Equivalent pipe style:
|
|
88
|
+
>>> from reactivex import operators as ops
|
|
89
|
+
>>> result = source.pipe(ops.sum())
|
|
90
|
+
|
|
91
|
+
Args:
|
|
92
|
+
key_mapper: Optional transform function to apply to each element.
|
|
93
|
+
|
|
94
|
+
Returns:
|
|
95
|
+
An observable sequence containing a single element with the sum
|
|
96
|
+
of the values in the source sequence.
|
|
97
|
+
|
|
98
|
+
See Also:
|
|
99
|
+
- :func:`sum <reactivex.operators.sum>`
|
|
100
|
+
- :meth:`average`
|
|
101
|
+
- :meth:`reduce`
|
|
102
|
+
"""
|
|
103
|
+
from reactivex import operators as ops
|
|
104
|
+
|
|
105
|
+
if key_mapper is None:
|
|
106
|
+
# Call operator directly with cast when no key_mapper is provided.
|
|
107
|
+
# sum() expects Observable[float] but we have Observable[_T].
|
|
108
|
+
source: Observable[float] = cast("Observable[float]", self._as_observable())
|
|
109
|
+
return ops.sum()(source)
|
|
110
|
+
return self._as_observable().pipe(ops.sum(key_mapper))
|
|
111
|
+
|
|
112
|
+
def average(
|
|
113
|
+
self, key_mapper: typing.Mapper[Any, float] | None = None
|
|
114
|
+
) -> Observable[float]:
|
|
115
|
+
"""Compute the average of the sequence.
|
|
116
|
+
|
|
117
|
+
Computes the average of an observable sequence of values that are
|
|
118
|
+
in the sequence or obtained by invoking a transform function on
|
|
119
|
+
each element if present.
|
|
120
|
+
|
|
121
|
+
Examples:
|
|
122
|
+
Fluent style:
|
|
123
|
+
>>> result = rx.of(1, 2, 3, 4, 5).average()
|
|
124
|
+
>>> result = source.average(lambda x: x.value)
|
|
125
|
+
|
|
126
|
+
Equivalent pipe style:
|
|
127
|
+
>>> from reactivex import operators as ops
|
|
128
|
+
>>> result = source.pipe(ops.average())
|
|
129
|
+
|
|
130
|
+
Args:
|
|
131
|
+
key_mapper: Optional transform function to apply to each element.
|
|
132
|
+
|
|
133
|
+
Returns:
|
|
134
|
+
An observable sequence containing a single element with the average
|
|
135
|
+
of the sequence of values.
|
|
136
|
+
|
|
137
|
+
See Also:
|
|
138
|
+
- :func:`average <reactivex.operators.average>`
|
|
139
|
+
- :meth:`sum`
|
|
140
|
+
"""
|
|
141
|
+
from reactivex import operators as ops
|
|
142
|
+
|
|
143
|
+
return self._as_observable().pipe(ops.average(key_mapper))
|
|
144
|
+
|
|
145
|
+
def min(self, comparer: typing.Comparer[_T] | None = None) -> Observable[_T]:
|
|
146
|
+
"""Find the minimum element.
|
|
147
|
+
|
|
148
|
+
Returns the minimum element in an observable sequence according to the
|
|
149
|
+
optional comparer else a default greater than less than check.
|
|
150
|
+
|
|
151
|
+
Examples:
|
|
152
|
+
Fluent style:
|
|
153
|
+
>>> result = source.min()
|
|
154
|
+
>>> result = source.min(lambda x, y: x.value < y.value)
|
|
155
|
+
|
|
156
|
+
Equivalent pipe style:
|
|
157
|
+
>>> from reactivex import operators as ops
|
|
158
|
+
>>> result = source.pipe(ops.min())
|
|
159
|
+
|
|
160
|
+
Args:
|
|
161
|
+
comparer: Optional comparer function for comparing elements.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
An observable sequence containing a single element with the minimum
|
|
165
|
+
element in the source sequence.
|
|
166
|
+
|
|
167
|
+
See Also:
|
|
168
|
+
- :func:`min <reactivex.operators.min>`
|
|
169
|
+
- :meth:`max`
|
|
170
|
+
- :meth:`min_by`
|
|
171
|
+
"""
|
|
172
|
+
from reactivex import operators as ops
|
|
173
|
+
|
|
174
|
+
return self._as_observable().pipe(ops.min(comparer))
|
|
175
|
+
|
|
176
|
+
def max(self, comparer: typing.Comparer[_T] | None = None) -> Observable[_T]:
|
|
177
|
+
"""Find the maximum element.
|
|
178
|
+
|
|
179
|
+
Returns the maximum value in an observable sequence according to the
|
|
180
|
+
specified comparer or default greater than less than check.
|
|
181
|
+
|
|
182
|
+
Examples:
|
|
183
|
+
Fluent style:
|
|
184
|
+
>>> result = source.max()
|
|
185
|
+
>>> result = source.max(lambda x, y: x.value > y.value)
|
|
186
|
+
|
|
187
|
+
Equivalent pipe style:
|
|
188
|
+
>>> from reactivex import operators as ops
|
|
189
|
+
>>> result = source.pipe(ops.max())
|
|
190
|
+
|
|
191
|
+
Args:
|
|
192
|
+
comparer: Optional comparer function for comparing elements.
|
|
193
|
+
|
|
194
|
+
Returns:
|
|
195
|
+
An observable sequence containing a single element with the maximum
|
|
196
|
+
element in the source sequence.
|
|
197
|
+
|
|
198
|
+
See Also:
|
|
199
|
+
- :func:`max <reactivex.operators.max>`
|
|
200
|
+
- :meth:`min`
|
|
201
|
+
- :meth:`max_by`
|
|
202
|
+
"""
|
|
203
|
+
from reactivex import operators as ops
|
|
204
|
+
|
|
205
|
+
return self._as_observable().pipe(ops.max(comparer))
|
|
206
|
+
|
|
207
|
+
def min_by(
|
|
208
|
+
self,
|
|
209
|
+
key_mapper: typing.Mapper[_T, _TKey],
|
|
210
|
+
comparer: typing.Comparer[_TKey] | None = None,
|
|
211
|
+
) -> Observable[list[_T]]:
|
|
212
|
+
"""Find all elements with the minimum key value.
|
|
213
|
+
|
|
214
|
+
Returns the elements in an observable sequence with the minimum key
|
|
215
|
+
value according to the specified comparer.
|
|
216
|
+
|
|
217
|
+
Examples:
|
|
218
|
+
Fluent style:
|
|
219
|
+
>>> result = source.min_by(lambda x: x.value)
|
|
220
|
+
>>> result = source.min_by(lambda x: x.age, lambda x, y: x < y)
|
|
221
|
+
|
|
222
|
+
Equivalent pipe style:
|
|
223
|
+
>>> from reactivex import operators as ops
|
|
224
|
+
>>> result = source.pipe(ops.min_by(lambda x: x.value))
|
|
225
|
+
|
|
226
|
+
Args:
|
|
227
|
+
key_mapper: A function to extract the key from each element.
|
|
228
|
+
comparer: Optional comparer function for comparing keys.
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
An observable sequence containing a list of zero or more elements
|
|
232
|
+
that have a minimum key value.
|
|
233
|
+
|
|
234
|
+
See Also:
|
|
235
|
+
- :func:`min_by <reactivex.operators.min_by>`
|
|
236
|
+
- :meth:`min`
|
|
237
|
+
- :meth:`max_by`
|
|
238
|
+
"""
|
|
239
|
+
from reactivex import operators as ops
|
|
240
|
+
|
|
241
|
+
return self._as_observable().pipe(ops.min_by(key_mapper, comparer))
|
|
242
|
+
|
|
243
|
+
def max_by(
|
|
244
|
+
self,
|
|
245
|
+
key_mapper: typing.Mapper[_T, _TKey],
|
|
246
|
+
comparer: typing.Comparer[_TKey] | None = None,
|
|
247
|
+
) -> Observable[list[_T]]:
|
|
248
|
+
"""Find all elements with the maximum key value.
|
|
249
|
+
|
|
250
|
+
Returns the elements in an observable sequence with the maximum key
|
|
251
|
+
value according to the specified comparer.
|
|
252
|
+
|
|
253
|
+
Examples:
|
|
254
|
+
Fluent style:
|
|
255
|
+
>>> result = source.max_by(lambda x: x.value)
|
|
256
|
+
>>> result = source.max_by(lambda x: x.age, lambda x, y: x > y)
|
|
257
|
+
|
|
258
|
+
Equivalent pipe style:
|
|
259
|
+
>>> from reactivex import operators as ops
|
|
260
|
+
>>> result = source.pipe(ops.max_by(lambda x: x.value))
|
|
261
|
+
|
|
262
|
+
Args:
|
|
263
|
+
key_mapper: A function to extract the key from each element.
|
|
264
|
+
comparer: Optional comparer function for comparing keys.
|
|
265
|
+
|
|
266
|
+
Returns:
|
|
267
|
+
An observable sequence containing a list of zero or more elements
|
|
268
|
+
that have a maximum key value.
|
|
269
|
+
|
|
270
|
+
See Also:
|
|
271
|
+
- :func:`max_by <reactivex.operators.max_by>`
|
|
272
|
+
- :meth:`max`
|
|
273
|
+
- :meth:`min_by`
|
|
274
|
+
"""
|
|
275
|
+
from reactivex import operators as ops
|
|
276
|
+
|
|
277
|
+
return self._as_observable().pipe(ops.max_by(key_mapper, comparer))
|
|
@@ -0,0 +1,306 @@
|
|
|
1
|
+
"""Multicasting operators mixin for Observable."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from typing import TYPE_CHECKING, Any, Generic, TypeVar, cast, overload
|
|
6
|
+
|
|
7
|
+
from reactivex import abc, typing
|
|
8
|
+
|
|
9
|
+
if TYPE_CHECKING:
|
|
10
|
+
from reactivex.observable import Observable
|
|
11
|
+
from reactivex.observable.connectableobservable import ConnectableObservable
|
|
12
|
+
|
|
13
|
+
_T = TypeVar("_T", covariant=True)
|
|
14
|
+
_R = TypeVar("_R")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MulticastingMixin(Generic[_T]):
|
|
18
|
+
"""Mixin providing multicasting operators for Observable.
|
|
19
|
+
|
|
20
|
+
This mixin adds operators that share a single subscription among
|
|
21
|
+
multiple observers, including publish, replay, and multicast.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
def _as_observable(self) -> Observable[_T]:
|
|
25
|
+
"""Cast mixin instance to Observable preserving type parameter.
|
|
26
|
+
|
|
27
|
+
This is safe because this mixin is only ever used as part of the Observable
|
|
28
|
+
class through multiple inheritance. At runtime, `self` in mixin methods will
|
|
29
|
+
always be an Observable[_T] instance. The type checker cannot infer this
|
|
30
|
+
because it analyzes mixins in isolation.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
The instance cast to Observable[_T] for type-safe method access.
|
|
34
|
+
"""
|
|
35
|
+
return cast("Observable[_T]", self)
|
|
36
|
+
|
|
37
|
+
def share(self) -> Observable[_T]:
|
|
38
|
+
"""Share a single subscription among multiple observers.
|
|
39
|
+
|
|
40
|
+
This is an alias for a composed publish() and ref_count().
|
|
41
|
+
As long as there is at least one subscriber, this observable
|
|
42
|
+
will be subscribed and emitting data. When all subscribers have
|
|
43
|
+
unsubscribed, it will unsubscribe from the source.
|
|
44
|
+
|
|
45
|
+
Examples:
|
|
46
|
+
Fluent style:
|
|
47
|
+
>>> shared = source.share()
|
|
48
|
+
|
|
49
|
+
Equivalent pipe style:
|
|
50
|
+
>>> from reactivex import operators as ops
|
|
51
|
+
>>> shared = source.pipe(ops.share())
|
|
52
|
+
|
|
53
|
+
Returns:
|
|
54
|
+
An observable that shares a single subscription to the
|
|
55
|
+
underlying source.
|
|
56
|
+
|
|
57
|
+
See Also:
|
|
58
|
+
- :func:`share <reactivex.operators.share>`
|
|
59
|
+
- :meth:`publish`
|
|
60
|
+
- :meth:`ref_count`
|
|
61
|
+
"""
|
|
62
|
+
from reactivex import operators as ops
|
|
63
|
+
|
|
64
|
+
return self._as_observable().pipe(ops.share())
|
|
65
|
+
|
|
66
|
+
@overload
|
|
67
|
+
def publish(self) -> ConnectableObservable[_T]: ...
|
|
68
|
+
|
|
69
|
+
@overload
|
|
70
|
+
def publish(
|
|
71
|
+
self, mapper: typing.Mapper[Observable[_T], Observable[_R]]
|
|
72
|
+
) -> Observable[_R]: ...
|
|
73
|
+
|
|
74
|
+
def publish(
|
|
75
|
+
self, mapper: typing.Mapper[Observable[_T], Observable[_R]] | None = None
|
|
76
|
+
) -> Observable[_R] | ConnectableObservable[_T]:
|
|
77
|
+
"""Returns a connectable observable or maps through a selector.
|
|
78
|
+
|
|
79
|
+
Returns an observable sequence that is the result of invoking the
|
|
80
|
+
mapper on a connectable observable sequence that shares a single
|
|
81
|
+
subscription to the underlying sequence.
|
|
82
|
+
|
|
83
|
+
Examples:
|
|
84
|
+
Fluent style:
|
|
85
|
+
>>> connectable = source.publish()
|
|
86
|
+
>>> result = source.publish(lambda x: x.take(5))
|
|
87
|
+
|
|
88
|
+
Equivalent pipe style:
|
|
89
|
+
>>> from reactivex import operators as ops
|
|
90
|
+
>>> connectable = source.pipe(ops.publish())
|
|
91
|
+
|
|
92
|
+
Args:
|
|
93
|
+
mapper: Optional selector function which can use the
|
|
94
|
+
multicasted source sequence.
|
|
95
|
+
|
|
96
|
+
Returns:
|
|
97
|
+
An observable sequence that contains the elements of a
|
|
98
|
+
sequence produced by multicasting the source sequence within
|
|
99
|
+
a mapper function, or a connectable observable if no mapper
|
|
100
|
+
is specified.
|
|
101
|
+
|
|
102
|
+
See Also:
|
|
103
|
+
- :func:`publish <reactivex.operators.publish>`
|
|
104
|
+
- :meth:`share`
|
|
105
|
+
- :meth:`multicast`
|
|
106
|
+
"""
|
|
107
|
+
from reactivex import operators as ops
|
|
108
|
+
|
|
109
|
+
if mapper is None:
|
|
110
|
+
return self._as_observable().pipe(ops.publish())
|
|
111
|
+
return self._as_observable().pipe(ops.publish(mapper))
|
|
112
|
+
|
|
113
|
+
@overload
|
|
114
|
+
def replay(
|
|
115
|
+
self,
|
|
116
|
+
buffer_size: int | None = None,
|
|
117
|
+
window: typing.RelativeTime | None = None,
|
|
118
|
+
*,
|
|
119
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
120
|
+
) -> ConnectableObservable[_T]: ...
|
|
121
|
+
|
|
122
|
+
@overload
|
|
123
|
+
def replay(
|
|
124
|
+
self,
|
|
125
|
+
buffer_size: int | None = None,
|
|
126
|
+
window: typing.RelativeTime | None = None,
|
|
127
|
+
*,
|
|
128
|
+
mapper: typing.Mapper[Observable[_T], Observable[_R]],
|
|
129
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
130
|
+
) -> Observable[_R]: ...
|
|
131
|
+
|
|
132
|
+
def replay(
|
|
133
|
+
self,
|
|
134
|
+
buffer_size: int | None = None,
|
|
135
|
+
window: typing.RelativeTime | None = None,
|
|
136
|
+
*,
|
|
137
|
+
mapper: typing.Mapper[Observable[_T], Observable[_R]] | None = None,
|
|
138
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
139
|
+
) -> Observable[_R] | ConnectableObservable[_T]:
|
|
140
|
+
"""Replay emissions to new subscribers.
|
|
141
|
+
|
|
142
|
+
Returns an observable sequence that is the result of invoking the
|
|
143
|
+
mapper on a connectable observable sequence that shares a single
|
|
144
|
+
subscription to the underlying sequence and starts with an initial
|
|
145
|
+
value. Replays values to new subscribers.
|
|
146
|
+
|
|
147
|
+
Examples:
|
|
148
|
+
Fluent style:
|
|
149
|
+
>>> connectable = source.replay()
|
|
150
|
+
>>> connectable = source.replay(buffer_size=3)
|
|
151
|
+
>>> result = source.replay(mapper=lambda x: x.take(5))
|
|
152
|
+
|
|
153
|
+
Equivalent pipe style:
|
|
154
|
+
>>> from reactivex import operators as ops
|
|
155
|
+
>>> connectable = source.pipe(ops.replay())
|
|
156
|
+
|
|
157
|
+
Args:
|
|
158
|
+
buffer_size: Maximum element count of the replay buffer.
|
|
159
|
+
window: Maximum time length of the replay buffer.
|
|
160
|
+
mapper: Selector function which can use the multicasted source.
|
|
161
|
+
scheduler: Scheduler to use for replay timing.
|
|
162
|
+
|
|
163
|
+
Returns:
|
|
164
|
+
An observable sequence that contains the elements of a
|
|
165
|
+
sequence produced by multicasting the source sequence within
|
|
166
|
+
a mapper function, or a connectable observable if no mapper
|
|
167
|
+
is specified.
|
|
168
|
+
|
|
169
|
+
See Also:
|
|
170
|
+
- :func:`replay <reactivex.operators.replay>`
|
|
171
|
+
- :meth:`publish`
|
|
172
|
+
- :meth:`share`
|
|
173
|
+
"""
|
|
174
|
+
from reactivex import operators as ops
|
|
175
|
+
|
|
176
|
+
if mapper is None:
|
|
177
|
+
return self._as_observable().pipe(
|
|
178
|
+
ops.replay(buffer_size, window, scheduler=scheduler)
|
|
179
|
+
)
|
|
180
|
+
return self._as_observable().pipe(
|
|
181
|
+
ops.replay(buffer_size, window, mapper=mapper, scheduler=scheduler)
|
|
182
|
+
)
|
|
183
|
+
|
|
184
|
+
def multicast(
|
|
185
|
+
self,
|
|
186
|
+
subject: abc.SubjectBase[_T] | None = None,
|
|
187
|
+
) -> Observable[_T]:
|
|
188
|
+
"""Multicast through a subject.
|
|
189
|
+
|
|
190
|
+
Multicasts the source sequence notifications through an
|
|
191
|
+
instantiated subject.
|
|
192
|
+
|
|
193
|
+
Examples:
|
|
194
|
+
Fluent style:
|
|
195
|
+
>>> from reactivex.subject import Subject
|
|
196
|
+
>>> connectable = source.multicast(Subject())
|
|
197
|
+
|
|
198
|
+
Equivalent pipe style:
|
|
199
|
+
>>> from reactivex import operators as ops
|
|
200
|
+
>>> connectable = source.pipe(ops.multicast(Subject()))
|
|
201
|
+
|
|
202
|
+
Args:
|
|
203
|
+
subject: The subject to multicast through. If None, creates
|
|
204
|
+
a new subject.
|
|
205
|
+
|
|
206
|
+
Returns:
|
|
207
|
+
A connectable observable sequence that upon connection causes
|
|
208
|
+
the source sequence to push results into the specified subject.
|
|
209
|
+
|
|
210
|
+
See Also:
|
|
211
|
+
- :func:`multicast <reactivex.operators.multicast>`
|
|
212
|
+
- :meth:`publish`
|
|
213
|
+
- :meth:`share`
|
|
214
|
+
"""
|
|
215
|
+
from reactivex import operators as ops
|
|
216
|
+
|
|
217
|
+
if subject is None:
|
|
218
|
+
return self._as_observable().pipe(ops.multicast())
|
|
219
|
+
return self._as_observable().pipe(ops.multicast(subject))
|
|
220
|
+
|
|
221
|
+
def ref_count(self) -> Observable[_T]:
|
|
222
|
+
"""Manage subscriptions to a connectable observable.
|
|
223
|
+
|
|
224
|
+
Returns an observable sequence that stays connected to the
|
|
225
|
+
source as long as there is at least one subscription to the
|
|
226
|
+
observable sequence.
|
|
227
|
+
|
|
228
|
+
Examples:
|
|
229
|
+
Fluent style:
|
|
230
|
+
>>> result = source.publish().ref_count()
|
|
231
|
+
|
|
232
|
+
Equivalent pipe style:
|
|
233
|
+
>>> from reactivex import operators as ops
|
|
234
|
+
>>> result = source.pipe(ops.publish(), ops.ref_count())
|
|
235
|
+
|
|
236
|
+
Returns:
|
|
237
|
+
An observable sequence that stays connected to the source.
|
|
238
|
+
|
|
239
|
+
See Also:
|
|
240
|
+
- :func:`ref_count <reactivex.operators.ref_count>`
|
|
241
|
+
- :meth:`share`
|
|
242
|
+
- :meth:`publish`
|
|
243
|
+
"""
|
|
244
|
+
from reactivex import operators as ops
|
|
245
|
+
|
|
246
|
+
# Cast is safe: ref_count is meant to be called on ConnectableObservable
|
|
247
|
+
# instances (the result of publish/multicast). The fluent API allows
|
|
248
|
+
# chaining this after publish(). We call the operator directly to avoid
|
|
249
|
+
# type variance issues with pipe's generic parameters.
|
|
250
|
+
source = cast("ConnectableObservable[_T]", self._as_observable())
|
|
251
|
+
return ops.ref_count()(source)
|
|
252
|
+
|
|
253
|
+
@overload
|
|
254
|
+
def publish_value(self, initial_value: Any) -> ConnectableObservable[Any]: ...
|
|
255
|
+
|
|
256
|
+
@overload
|
|
257
|
+
def publish_value(
|
|
258
|
+
self,
|
|
259
|
+
initial_value: Any,
|
|
260
|
+
mapper: typing.Mapper[Observable[Any], Observable[_R]],
|
|
261
|
+
) -> Observable[_R]: ...
|
|
262
|
+
|
|
263
|
+
def publish_value(
|
|
264
|
+
self,
|
|
265
|
+
initial_value: Any,
|
|
266
|
+
mapper: typing.Mapper[Observable[Any], Observable[_R]] | None = None,
|
|
267
|
+
) -> Observable[_R] | ConnectableObservable[Any]:
|
|
268
|
+
"""Multicast with an initial value (BehaviorSubject).
|
|
269
|
+
|
|
270
|
+
Returns an observable sequence that is the result of invoking
|
|
271
|
+
the mapper on a connectable observable sequence that shares a
|
|
272
|
+
single subscription to the underlying sequence and starts with
|
|
273
|
+
initial_value.
|
|
274
|
+
|
|
275
|
+
This is essentially publish with a BehaviorSubject.
|
|
276
|
+
|
|
277
|
+
Examples:
|
|
278
|
+
Fluent style:
|
|
279
|
+
>>> connectable = source.publish_value(0)
|
|
280
|
+
>>> result = source.publish_value(0, lambda x: x.take(5))
|
|
281
|
+
|
|
282
|
+
Equivalent pipe style:
|
|
283
|
+
>>> from reactivex import operators as ops
|
|
284
|
+
>>> connectable = source.pipe(ops.publish_value(0))
|
|
285
|
+
|
|
286
|
+
Args:
|
|
287
|
+
initial_value: Initial value to emit before source emissions.
|
|
288
|
+
mapper: Optional selector function which can use the
|
|
289
|
+
multicasted source sequence.
|
|
290
|
+
|
|
291
|
+
Returns:
|
|
292
|
+
An observable sequence that contains the elements of a
|
|
293
|
+
sequence produced by multicasting the source sequence within
|
|
294
|
+
a mapper function, or a connectable observable if no mapper
|
|
295
|
+
is specified.
|
|
296
|
+
|
|
297
|
+
See Also:
|
|
298
|
+
- :func:`publish_value <reactivex.operators.publish_value>`
|
|
299
|
+
- :meth:`publish`
|
|
300
|
+
- :meth:`replay`
|
|
301
|
+
"""
|
|
302
|
+
from reactivex import operators as ops
|
|
303
|
+
|
|
304
|
+
if mapper is None:
|
|
305
|
+
return self._as_observable().pipe(ops.publish_value(initial_value))
|
|
306
|
+
return self._as_observable().pipe(ops.publish_value(initial_value, mapper))
|