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,632 @@
|
|
|
1
|
+
"""Transformation 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
|
+
from typing_extensions import TypeVarTuple, Unpack
|
|
9
|
+
|
|
10
|
+
from reactivex import typing
|
|
11
|
+
from reactivex.internal.utils import NotSet
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from reactivex.observable import Observable
|
|
15
|
+
|
|
16
|
+
_T = TypeVar("_T", covariant=True)
|
|
17
|
+
_A = TypeVar("_A")
|
|
18
|
+
_B = TypeVar("_B")
|
|
19
|
+
_Ts = TypeVarTuple("_Ts")
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class TransformationMixin(Generic[_T]):
|
|
23
|
+
"""Mixin providing transformation operators for Observable.
|
|
24
|
+
|
|
25
|
+
This mixin adds operators that transform elements in various ways,
|
|
26
|
+
including mapping, flattening, and accumulation.
|
|
27
|
+
|
|
28
|
+
Generic over _T to preserve the Observable's element type and provide
|
|
29
|
+
full type safety without Any types.
|
|
30
|
+
"""
|
|
31
|
+
|
|
32
|
+
def _as_observable(self) -> Observable[_T]:
|
|
33
|
+
"""Cast mixin instance to Observable preserving type parameter.
|
|
34
|
+
|
|
35
|
+
This is safe because this mixin is only ever used as part of the Observable
|
|
36
|
+
class through multiple inheritance. At runtime, `self` in mixin methods will
|
|
37
|
+
always be an Observable[_T] instance. The type checker cannot infer this
|
|
38
|
+
because it analyzes mixins in isolation.
|
|
39
|
+
|
|
40
|
+
Returns:
|
|
41
|
+
The instance cast to Observable[_T] for type-safe method access.
|
|
42
|
+
"""
|
|
43
|
+
return cast("Observable[_T]", self)
|
|
44
|
+
|
|
45
|
+
def map(self, mapper: typing.Mapper[_T, _B]) -> Observable[_B]:
|
|
46
|
+
"""Map each element to a new value.
|
|
47
|
+
|
|
48
|
+
Projects each element of an observable sequence into a new form by applying
|
|
49
|
+
a transform function to each element.
|
|
50
|
+
|
|
51
|
+
Examples:
|
|
52
|
+
Fluent style:
|
|
53
|
+
>>> result = source.map(lambda x: x * 2)
|
|
54
|
+
>>> result = source.map(str) # Transform int to str
|
|
55
|
+
|
|
56
|
+
Equivalent pipe style:
|
|
57
|
+
>>> from reactivex import operators as ops
|
|
58
|
+
>>> result = source.pipe(ops.map(lambda x: x * 2))
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
mapper: A transform function to apply to each source element.
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
An observable sequence whose elements are the result of invoking
|
|
65
|
+
the transform function on each element of the source.
|
|
66
|
+
|
|
67
|
+
See Also:
|
|
68
|
+
- :func:`map <reactivex.operators.map>`
|
|
69
|
+
- :meth:`map_indexed`
|
|
70
|
+
"""
|
|
71
|
+
from reactivex import operators as ops
|
|
72
|
+
|
|
73
|
+
return self._as_observable().pipe(ops.map(mapper))
|
|
74
|
+
|
|
75
|
+
@overload
|
|
76
|
+
def reduce(self, accumulator: typing.Accumulator[_T, _T]) -> Observable[_T]: ...
|
|
77
|
+
|
|
78
|
+
@overload
|
|
79
|
+
def reduce(
|
|
80
|
+
self, accumulator: typing.Accumulator[_A, _T], seed: _A
|
|
81
|
+
) -> Observable[_A]: ...
|
|
82
|
+
|
|
83
|
+
def reduce(
|
|
84
|
+
self,
|
|
85
|
+
accumulator: typing.Accumulator[_A, _T],
|
|
86
|
+
seed: _A | type[NotSet] = NotSet,
|
|
87
|
+
) -> Observable[_T] | Observable[_A]:
|
|
88
|
+
"""Apply an accumulator function and return the final accumulated result.
|
|
89
|
+
|
|
90
|
+
Applies an accumulator function over an observable sequence, returning the
|
|
91
|
+
result of the aggregation as a single element in the result sequence.
|
|
92
|
+
|
|
93
|
+
Examples:
|
|
94
|
+
Fluent style:
|
|
95
|
+
>>> result = source.reduce(lambda acc, x: acc + x)
|
|
96
|
+
>>> result = source.reduce(lambda acc, x: acc + x, 0)
|
|
97
|
+
>>> # Concatenate strings
|
|
98
|
+
>>> result = source.reduce(lambda acc, x: acc + x, "")
|
|
99
|
+
|
|
100
|
+
Equivalent pipe style:
|
|
101
|
+
>>> from reactivex import operators as ops
|
|
102
|
+
>>> result = source.pipe(ops.reduce(lambda acc, x: acc + x))
|
|
103
|
+
>>> result = source.pipe(ops.reduce(lambda acc, x: acc + x, 0))
|
|
104
|
+
|
|
105
|
+
Args:
|
|
106
|
+
accumulator: An accumulator function to be invoked on each element.
|
|
107
|
+
seed: Optional initial accumulator value.
|
|
108
|
+
|
|
109
|
+
Returns:
|
|
110
|
+
An observable sequence containing a single element with the final
|
|
111
|
+
accumulated value.
|
|
112
|
+
|
|
113
|
+
See Also:
|
|
114
|
+
- :func:`reduce <reactivex.operators.reduce>`
|
|
115
|
+
- :meth:`scan`
|
|
116
|
+
"""
|
|
117
|
+
from reactivex import operators as ops
|
|
118
|
+
|
|
119
|
+
if seed is NotSet:
|
|
120
|
+
return self._as_observable().pipe(ops.reduce(accumulator))
|
|
121
|
+
# After the guard above, seed is guaranteed to be _A (not type[NotSet]).
|
|
122
|
+
# Cast is needed because pyright doesn't narrow union types with `is` checks.
|
|
123
|
+
seed_value = cast(_A, seed)
|
|
124
|
+
return self._as_observable().pipe(ops.reduce(accumulator, seed_value))
|
|
125
|
+
|
|
126
|
+
@overload
|
|
127
|
+
def scan(self, accumulator: typing.Accumulator[_T, _T]) -> Observable[_T]: ...
|
|
128
|
+
|
|
129
|
+
@overload
|
|
130
|
+
def scan(
|
|
131
|
+
self, accumulator: typing.Accumulator[_A, _T], seed: _A
|
|
132
|
+
) -> Observable[_A]: ...
|
|
133
|
+
|
|
134
|
+
def scan(
|
|
135
|
+
self,
|
|
136
|
+
accumulator: typing.Accumulator[_A, _T],
|
|
137
|
+
seed: _A | type[NotSet] = NotSet,
|
|
138
|
+
) -> Observable[_T] | Observable[_A]:
|
|
139
|
+
"""Apply an accumulator function and return each intermediate result.
|
|
140
|
+
|
|
141
|
+
Applies an accumulator function over an observable sequence and returns
|
|
142
|
+
each intermediate result. Similar to reduce, but emits the current
|
|
143
|
+
accumulation after each element.
|
|
144
|
+
|
|
145
|
+
Examples:
|
|
146
|
+
Fluent style:
|
|
147
|
+
>>> result = source.scan(lambda acc, x: acc + x)
|
|
148
|
+
>>> result = source.scan(lambda acc, x: acc + x, 0)
|
|
149
|
+
>>> result = source.scan(lambda acc, x: acc + [x], []) # Collect into list
|
|
150
|
+
|
|
151
|
+
Equivalent pipe style:
|
|
152
|
+
>>> from reactivex import operators as ops
|
|
153
|
+
>>> result = source.pipe(ops.scan(lambda acc, x: acc + x))
|
|
154
|
+
>>> result = source.pipe(ops.scan(lambda acc, x: acc + x, 0))
|
|
155
|
+
|
|
156
|
+
Args:
|
|
157
|
+
accumulator: An accumulator function to be invoked on each element.
|
|
158
|
+
seed: Optional initial accumulator value.
|
|
159
|
+
|
|
160
|
+
Returns:
|
|
161
|
+
An observable sequence containing the accumulated values.
|
|
162
|
+
|
|
163
|
+
See Also:
|
|
164
|
+
- :func:`scan <reactivex.operators.scan>`
|
|
165
|
+
- :meth:`reduce`
|
|
166
|
+
"""
|
|
167
|
+
from reactivex import operators as ops
|
|
168
|
+
|
|
169
|
+
return self._as_observable().pipe(ops.scan(accumulator, seed))
|
|
170
|
+
|
|
171
|
+
@overload
|
|
172
|
+
def flat_map(self, mapper: typing.Mapper[_T, Observable[_B]]) -> Observable[_B]: ...
|
|
173
|
+
|
|
174
|
+
@overload
|
|
175
|
+
def flat_map(self, mapper: None = None) -> Observable[object]: ...
|
|
176
|
+
|
|
177
|
+
def flat_map(
|
|
178
|
+
self,
|
|
179
|
+
mapper: typing.Mapper[_T, Observable[_B]] | None = None,
|
|
180
|
+
) -> Observable[_B]:
|
|
181
|
+
"""Transform elements into observables and flatten (also known as merge_map).
|
|
182
|
+
|
|
183
|
+
Projects each element of an observable sequence to an observable sequence
|
|
184
|
+
and merges the resulting observable sequences into one observable sequence.
|
|
185
|
+
|
|
186
|
+
Examples:
|
|
187
|
+
Fluent style:
|
|
188
|
+
>>> result = source.flat_map(lambda x: rx.of(x, x * 2))
|
|
189
|
+
>>> result = rx.of(rx.of(1, 2), rx.of(3, 4)).flat_map() # Flatten
|
|
190
|
+
|
|
191
|
+
Equivalent pipe style:
|
|
192
|
+
>>> from reactivex import operators as ops
|
|
193
|
+
>>> result = source.pipe(ops.flat_map(lambda x: rx.of(x, x * 2)))
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
mapper: A transform function to apply to each element, or None to
|
|
197
|
+
flatten nested observables.
|
|
198
|
+
|
|
199
|
+
Returns:
|
|
200
|
+
An observable sequence whose elements are the result of invoking the
|
|
201
|
+
one-to-many transform function on each element of the input sequence
|
|
202
|
+
and merging all the resulting sequences.
|
|
203
|
+
|
|
204
|
+
See Also:
|
|
205
|
+
- :func:`flat_map <reactivex.operators.flat_map>`
|
|
206
|
+
- :meth:`concat_map`
|
|
207
|
+
- :meth:`switch_map`
|
|
208
|
+
"""
|
|
209
|
+
from reactivex import operators as ops
|
|
210
|
+
|
|
211
|
+
return self._as_observable().pipe(ops.flat_map(mapper))
|
|
212
|
+
|
|
213
|
+
def concat_map(self, project: typing.Mapper[_T, Observable[_B]]) -> Observable[_B]:
|
|
214
|
+
"""Transform and concatenate observables in order.
|
|
215
|
+
|
|
216
|
+
Projects each source value to an observable which is merged in the output
|
|
217
|
+
observable, in a serialized fashion waiting for each one to complete before
|
|
218
|
+
merging the next.
|
|
219
|
+
|
|
220
|
+
Examples:
|
|
221
|
+
Fluent style:
|
|
222
|
+
>>> result = source.concat_map(lambda x: rx.of(x, x * 2))
|
|
223
|
+
>>> result = source.concat_map(lambda x: delayed_observable(x))
|
|
224
|
+
|
|
225
|
+
Equivalent pipe style:
|
|
226
|
+
>>> from reactivex import operators as ops
|
|
227
|
+
>>> result = source.pipe(ops.concat_map(lambda x: rx.of(x, x * 2)))
|
|
228
|
+
|
|
229
|
+
Args:
|
|
230
|
+
project: A transform function to apply to each element.
|
|
231
|
+
|
|
232
|
+
Returns:
|
|
233
|
+
An observable sequence whose elements are the result of invoking the
|
|
234
|
+
transform function on each element and concatenating all the sequences.
|
|
235
|
+
|
|
236
|
+
See Also:
|
|
237
|
+
- :func:`concat_map <reactivex.operators.concat_map>`
|
|
238
|
+
- :meth:`flat_map`
|
|
239
|
+
- :meth:`switch_map`
|
|
240
|
+
"""
|
|
241
|
+
from reactivex import operators as ops
|
|
242
|
+
|
|
243
|
+
return self._as_observable().pipe(ops.concat_map(project))
|
|
244
|
+
|
|
245
|
+
def switch_map(self, project: typing.Mapper[_T, Observable[_B]]) -> Observable[_B]:
|
|
246
|
+
"""Transform and switch to the latest observable.
|
|
247
|
+
|
|
248
|
+
Projects each source value to an observable which is merged in the output
|
|
249
|
+
observable, emitting values only from the most recently projected observable.
|
|
250
|
+
|
|
251
|
+
Examples:
|
|
252
|
+
Fluent style:
|
|
253
|
+
>>> result = source.switch_map(lambda x: rx.of(x, x * 2))
|
|
254
|
+
>>> result = source.switch_map(lambda x: delayed_observable(x))
|
|
255
|
+
|
|
256
|
+
Equivalent pipe style:
|
|
257
|
+
>>> from reactivex import operators as ops
|
|
258
|
+
>>> result = source.pipe(ops.switch_map(lambda x: rx.of(x, x * 2)))
|
|
259
|
+
|
|
260
|
+
Args:
|
|
261
|
+
project: A transform function to apply to each element.
|
|
262
|
+
|
|
263
|
+
Returns:
|
|
264
|
+
An observable sequence whose elements are the result of invoking the
|
|
265
|
+
transform function on each element and merging only the most recent
|
|
266
|
+
inner observable sequence.
|
|
267
|
+
|
|
268
|
+
See Also:
|
|
269
|
+
- :func:`switch_map <reactivex.operators.switch_map>`
|
|
270
|
+
- :meth:`flat_map`
|
|
271
|
+
- :meth:`concat_map`
|
|
272
|
+
"""
|
|
273
|
+
from reactivex import operators as ops
|
|
274
|
+
|
|
275
|
+
return self._as_observable().pipe(ops.switch_map(project))
|
|
276
|
+
|
|
277
|
+
def map_indexed(
|
|
278
|
+
self, mapper_indexed: typing.MapperIndexed[_T, _B] | None = None
|
|
279
|
+
) -> Observable[_B]:
|
|
280
|
+
"""Map each element to a new value with its index.
|
|
281
|
+
|
|
282
|
+
Projects each element of an observable sequence into a new form by
|
|
283
|
+
incorporating the element's index.
|
|
284
|
+
|
|
285
|
+
Examples:
|
|
286
|
+
Fluent style:
|
|
287
|
+
>>> result = source.map_indexed(lambda x, i: f"{i}: {x}")
|
|
288
|
+
>>> result = source.map_indexed(lambda x, i: x * i)
|
|
289
|
+
|
|
290
|
+
Equivalent pipe style:
|
|
291
|
+
>>> from reactivex import operators as ops
|
|
292
|
+
>>> result = source.pipe(ops.map_indexed(lambda x, i: f"{i}: {x}"))
|
|
293
|
+
|
|
294
|
+
Args:
|
|
295
|
+
mapper_indexed: A transform function to apply to each element and
|
|
296
|
+
its index. The function receives (value, index) and returns the
|
|
297
|
+
transformed value.
|
|
298
|
+
|
|
299
|
+
Returns:
|
|
300
|
+
An observable sequence whose elements are the result of invoking
|
|
301
|
+
the indexed transform function on each element of the source.
|
|
302
|
+
|
|
303
|
+
See Also:
|
|
304
|
+
- :func:`map_indexed <reactivex.operators.map_indexed>`
|
|
305
|
+
- :meth:`map`
|
|
306
|
+
"""
|
|
307
|
+
from reactivex import operators as ops
|
|
308
|
+
|
|
309
|
+
return self._as_observable().pipe(ops.map_indexed(mapper_indexed))
|
|
310
|
+
|
|
311
|
+
def flat_map_indexed(
|
|
312
|
+
self, mapper_indexed: typing.MapperIndexed[_T, Observable[_B]] | None = None
|
|
313
|
+
) -> Observable[_B]:
|
|
314
|
+
"""Transform elements into observables and flatten, with index.
|
|
315
|
+
|
|
316
|
+
Projects each element of an observable sequence to an observable sequence
|
|
317
|
+
by incorporating the element's index, and merges the resulting observable
|
|
318
|
+
sequences into one observable sequence.
|
|
319
|
+
|
|
320
|
+
Examples:
|
|
321
|
+
Fluent style:
|
|
322
|
+
>>> result = source.flat_map_indexed(lambda x, i: rx.of(x, i))
|
|
323
|
+
>>> result = source.flat_map_indexed(lambda x, i: fetch_data(x, i))
|
|
324
|
+
|
|
325
|
+
Equivalent pipe style:
|
|
326
|
+
>>> from reactivex import operators as ops
|
|
327
|
+
>>> result = source.pipe(ops.flat_map_indexed(lambda x, i: rx.of(x, i)))
|
|
328
|
+
|
|
329
|
+
Args:
|
|
330
|
+
mapper_indexed: A transform function to apply to each element and its
|
|
331
|
+
index. The function receives (value, index) and returns an Observable.
|
|
332
|
+
|
|
333
|
+
Returns:
|
|
334
|
+
An observable sequence whose elements are the result of invoking the
|
|
335
|
+
indexed transform function on each element and merging all sequences.
|
|
336
|
+
|
|
337
|
+
See Also:
|
|
338
|
+
- :func:`flat_map_indexed <reactivex.operators.flat_map_indexed>`
|
|
339
|
+
- :meth:`flat_map`
|
|
340
|
+
- :meth:`map_indexed`
|
|
341
|
+
"""
|
|
342
|
+
from reactivex import operators as ops
|
|
343
|
+
|
|
344
|
+
return self._as_observable().pipe(ops.flat_map_indexed(mapper_indexed))
|
|
345
|
+
|
|
346
|
+
def flat_map_latest(
|
|
347
|
+
self, mapper: typing.Mapper[_T, Observable[_B]]
|
|
348
|
+
) -> Observable[_B]:
|
|
349
|
+
"""Transform and flatten, canceling previous inner observables.
|
|
350
|
+
|
|
351
|
+
Projects each element to an observable, merges the resulting observables,
|
|
352
|
+
and emits only from the most recently projected observable.
|
|
353
|
+
|
|
354
|
+
Examples:
|
|
355
|
+
Fluent style:
|
|
356
|
+
>>> result = source.flat_map_latest(lambda x: fetch_data(x))
|
|
357
|
+
|
|
358
|
+
Equivalent pipe style:
|
|
359
|
+
>>> from reactivex import operators as ops
|
|
360
|
+
>>> result = source.pipe(ops.flat_map_latest(lambda x: fetch_data(x)))
|
|
361
|
+
|
|
362
|
+
Args:
|
|
363
|
+
mapper: A transform function to apply to each element.
|
|
364
|
+
|
|
365
|
+
Returns:
|
|
366
|
+
An observable sequence containing the merged results from the
|
|
367
|
+
most recent inner observable.
|
|
368
|
+
|
|
369
|
+
See Also:
|
|
370
|
+
- :func:`flat_map_latest <reactivex.operators.flat_map_latest>`
|
|
371
|
+
- :meth:`flat_map`
|
|
372
|
+
- :meth:`switch_map`
|
|
373
|
+
"""
|
|
374
|
+
from reactivex import operators as ops
|
|
375
|
+
|
|
376
|
+
return self._as_observable().pipe(ops.flat_map_latest(mapper))
|
|
377
|
+
|
|
378
|
+
def switch_map_indexed(
|
|
379
|
+
self, mapper_indexed: typing.MapperIndexed[_T, Observable[_B]]
|
|
380
|
+
) -> Observable[_B]:
|
|
381
|
+
"""Transform and switch to latest observable, with index.
|
|
382
|
+
|
|
383
|
+
Projects each element to an observable by incorporating the element's index,
|
|
384
|
+
and emits values only from the most recently projected observable.
|
|
385
|
+
|
|
386
|
+
Examples:
|
|
387
|
+
Fluent style:
|
|
388
|
+
>>> result = source.switch_map_indexed(lambda x, i: fetch_data(x, i))
|
|
389
|
+
|
|
390
|
+
Equivalent pipe style:
|
|
391
|
+
>>> from reactivex import operators as ops
|
|
392
|
+
>>> result = source.pipe(
|
|
393
|
+
... ops.switch_map_indexed(lambda x, i: fetch_data(x, i))
|
|
394
|
+
... )
|
|
395
|
+
|
|
396
|
+
Args:
|
|
397
|
+
mapper_indexed: A transform function to apply to each element and its index.
|
|
398
|
+
|
|
399
|
+
Returns:
|
|
400
|
+
An observable sequence whose elements are the result of invoking the
|
|
401
|
+
indexed transform function and switching to the most recent sequence.
|
|
402
|
+
|
|
403
|
+
See Also:
|
|
404
|
+
- :func:`switch_map_indexed <reactivex.operators.switch_map_indexed>`
|
|
405
|
+
- :meth:`switch_map`
|
|
406
|
+
- :meth:`flat_map_indexed`
|
|
407
|
+
"""
|
|
408
|
+
from reactivex import operators as ops
|
|
409
|
+
|
|
410
|
+
return self._as_observable().pipe(ops.switch_map_indexed(mapper_indexed))
|
|
411
|
+
|
|
412
|
+
@overload
|
|
413
|
+
def starmap(self: TransformationMixin[_T]) -> Observable[_T]:
|
|
414
|
+
"""Identity overload when no mapper provided."""
|
|
415
|
+
...
|
|
416
|
+
|
|
417
|
+
@overload
|
|
418
|
+
def starmap(
|
|
419
|
+
self: TransformationMixin[tuple[Unpack[_Ts]]],
|
|
420
|
+
mapper: Callable[[Unpack[_Ts]], _B],
|
|
421
|
+
) -> Observable[_B]:
|
|
422
|
+
"""Typed overload with variadic generics."""
|
|
423
|
+
...
|
|
424
|
+
|
|
425
|
+
def starmap(self, mapper: Any = None) -> Observable[Any]:
|
|
426
|
+
"""Unpack arguments from tuples and apply to mapper function.
|
|
427
|
+
|
|
428
|
+
Projects each element of an observable sequence of tuples into a new form
|
|
429
|
+
by unpacking the tuple as arguments to a function.
|
|
430
|
+
|
|
431
|
+
Examples:
|
|
432
|
+
Fluent style:
|
|
433
|
+
>>> result = rx.of((1, 2), (3, 4)).starmap(lambda x, y: x + y)
|
|
434
|
+
>>> result = rx.of(("a", 1), ("b", 2)).starmap(lambda s, n: s * n)
|
|
435
|
+
|
|
436
|
+
Equivalent pipe style:
|
|
437
|
+
>>> from reactivex import operators as ops
|
|
438
|
+
>>> result = source.pipe(ops.starmap(lambda x, y: x + y))
|
|
439
|
+
|
|
440
|
+
Args:
|
|
441
|
+
mapper: A transform function that receives unpacked tuple elements.
|
|
442
|
+
If not provided, returns the tuple unchanged.
|
|
443
|
+
|
|
444
|
+
Returns:
|
|
445
|
+
An observable sequence whose elements are the result of invoking
|
|
446
|
+
the transform function with unpacked tuple arguments.
|
|
447
|
+
|
|
448
|
+
See Also:
|
|
449
|
+
- :func:`starmap <reactivex.operators.starmap>`
|
|
450
|
+
- :meth:`map`
|
|
451
|
+
"""
|
|
452
|
+
from reactivex import operators as ops
|
|
453
|
+
|
|
454
|
+
# Cast is safe: The overloads above provide type safety for callers.
|
|
455
|
+
# The implementation uses Any because variadic generics can't be
|
|
456
|
+
# perfectly expressed in the implementation signature.
|
|
457
|
+
source = cast("Observable[Any]", self._as_observable())
|
|
458
|
+
return source.pipe(ops.starmap(mapper))
|
|
459
|
+
|
|
460
|
+
@overload
|
|
461
|
+
def starmap_indexed(
|
|
462
|
+
self: TransformationMixin[tuple[Unpack[_Ts]]],
|
|
463
|
+
mapper_indexed: Callable[[Unpack[_Ts], int], _B],
|
|
464
|
+
) -> Observable[_B]: ...
|
|
465
|
+
|
|
466
|
+
@overload
|
|
467
|
+
def starmap_indexed(self, mapper_indexed: None = None) -> Observable[Any]: ...
|
|
468
|
+
|
|
469
|
+
def starmap_indexed(self, mapper_indexed: Any = None) -> Observable[Any]:
|
|
470
|
+
"""Unpack tuple arguments and apply to indexed mapper function.
|
|
471
|
+
|
|
472
|
+
Projects each element of an observable sequence of tuples into a new form
|
|
473
|
+
by unpacking the tuple as arguments to a function, with index.
|
|
474
|
+
|
|
475
|
+
Examples:
|
|
476
|
+
Fluent style:
|
|
477
|
+
>>> result = rx.of((1, 2), (3, 4)).starmap_indexed(
|
|
478
|
+
... lambda x, y, i: (x + y) * i
|
|
479
|
+
... )
|
|
480
|
+
|
|
481
|
+
Equivalent pipe style:
|
|
482
|
+
>>> from reactivex import operators as ops
|
|
483
|
+
>>> result = source.pipe(ops.starmap_indexed(lambda x, y, i: (x + y) * i))
|
|
484
|
+
|
|
485
|
+
Args:
|
|
486
|
+
mapper_indexed: A transform function that receives unpacked tuple
|
|
487
|
+
elements and the index.
|
|
488
|
+
|
|
489
|
+
Returns:
|
|
490
|
+
An observable sequence whose elements are the result of invoking
|
|
491
|
+
the indexed transform function with unpacked tuple arguments.
|
|
492
|
+
|
|
493
|
+
See Also:
|
|
494
|
+
- :func:`starmap_indexed <reactivex.operators.starmap_indexed>`
|
|
495
|
+
- :meth:`starmap`
|
|
496
|
+
- :meth:`map_indexed`
|
|
497
|
+
"""
|
|
498
|
+
from reactivex import operators as ops
|
|
499
|
+
|
|
500
|
+
# Cast is safe: The overload above provides type safety for callers.
|
|
501
|
+
# The implementation uses Any because variadic generics can't be
|
|
502
|
+
# perfectly expressed in the implementation signature.
|
|
503
|
+
source = cast("Observable[Any]", self._as_observable())
|
|
504
|
+
return source.pipe(ops.starmap_indexed(mapper_indexed))
|
|
505
|
+
|
|
506
|
+
def pluck(self, key: str) -> Observable[Any]:
|
|
507
|
+
"""Extract a property from each element.
|
|
508
|
+
|
|
509
|
+
Returns an observable sequence of values corresponding to a property
|
|
510
|
+
with the given name from all elements in the source sequence.
|
|
511
|
+
|
|
512
|
+
Examples:
|
|
513
|
+
Fluent style:
|
|
514
|
+
>>> result = source.pluck("name")
|
|
515
|
+
>>> result = rx.of({"x": 1}, {"x": 2}).pluck("x")
|
|
516
|
+
|
|
517
|
+
Equivalent pipe style:
|
|
518
|
+
>>> from reactivex import operators as ops
|
|
519
|
+
>>> result = source.pipe(ops.pluck("name"))
|
|
520
|
+
|
|
521
|
+
Args:
|
|
522
|
+
key: The property name to extract.
|
|
523
|
+
|
|
524
|
+
Returns:
|
|
525
|
+
An observable sequence of property values.
|
|
526
|
+
|
|
527
|
+
See Also:
|
|
528
|
+
- :func:`pluck <reactivex.operators.pluck>`
|
|
529
|
+
- :meth:`pluck_attr`
|
|
530
|
+
- :meth:`map`
|
|
531
|
+
"""
|
|
532
|
+
from reactivex import operators as ops
|
|
533
|
+
|
|
534
|
+
# Cast is safe: pluck expects Observable[dict[str, Any]] but
|
|
535
|
+
# we have Observable[_T]. The fluent API allows calling this
|
|
536
|
+
# on sequences of dictionaries.
|
|
537
|
+
source: Observable[Any] = cast("Observable[Any]", self._as_observable())
|
|
538
|
+
return ops.pluck(key)(source)
|
|
539
|
+
|
|
540
|
+
def pluck_attr(self, attr: str) -> Observable[Any]:
|
|
541
|
+
"""Extract an attribute from each element.
|
|
542
|
+
|
|
543
|
+
Returns an observable sequence of values corresponding to an attribute
|
|
544
|
+
with the given name from all elements in the source sequence.
|
|
545
|
+
|
|
546
|
+
Examples:
|
|
547
|
+
Fluent style:
|
|
548
|
+
>>> result = source.pluck_attr("name")
|
|
549
|
+
>>> result = source.pluck_attr("value")
|
|
550
|
+
|
|
551
|
+
Equivalent pipe style:
|
|
552
|
+
>>> from reactivex import operators as ops
|
|
553
|
+
>>> result = source.pipe(ops.pluck_attr("name"))
|
|
554
|
+
|
|
555
|
+
Args:
|
|
556
|
+
attr: The attribute name to extract.
|
|
557
|
+
|
|
558
|
+
Returns:
|
|
559
|
+
An observable sequence of attribute values.
|
|
560
|
+
|
|
561
|
+
See Also:
|
|
562
|
+
- :func:`pluck_attr <reactivex.operators.pluck_attr>`
|
|
563
|
+
- :meth:`pluck`
|
|
564
|
+
- :meth:`map`
|
|
565
|
+
"""
|
|
566
|
+
from reactivex import operators as ops
|
|
567
|
+
|
|
568
|
+
return self._as_observable().pipe(ops.pluck_attr(attr))
|
|
569
|
+
|
|
570
|
+
def expand(self, mapper: typing.Mapper[_T, Observable[_T]]) -> Observable[_T]:
|
|
571
|
+
"""Recursively expand observable sequences.
|
|
572
|
+
|
|
573
|
+
Recursively projects each source value to an observable which is merged
|
|
574
|
+
in the output observable.
|
|
575
|
+
|
|
576
|
+
Examples:
|
|
577
|
+
Fluent style:
|
|
578
|
+
>>> result = rx.of(1).expand(
|
|
579
|
+
... lambda x: rx.of(x + 1) if x < 10 else rx.empty()
|
|
580
|
+
... )
|
|
581
|
+
|
|
582
|
+
Equivalent pipe style:
|
|
583
|
+
>>> from reactivex import operators as ops
|
|
584
|
+
>>> result = source.pipe(
|
|
585
|
+
... ops.expand(lambda x: rx.of(x + 1) if x < 10 else rx.empty())
|
|
586
|
+
... )
|
|
587
|
+
|
|
588
|
+
Args:
|
|
589
|
+
mapper: A transform function to apply to each element, returning an
|
|
590
|
+
observable sequence.
|
|
591
|
+
|
|
592
|
+
Returns:
|
|
593
|
+
An observable sequence containing all values from the source and
|
|
594
|
+
recursively expanded observables.
|
|
595
|
+
|
|
596
|
+
See Also:
|
|
597
|
+
- :func:`expand <reactivex.operators.expand>`
|
|
598
|
+
- :meth:`flat_map`
|
|
599
|
+
"""
|
|
600
|
+
from reactivex import operators as ops
|
|
601
|
+
|
|
602
|
+
return self._as_observable().pipe(ops.expand(mapper))
|
|
603
|
+
|
|
604
|
+
def exclusive(self) -> Observable[_T]:
|
|
605
|
+
"""Projects and merges observables exclusively.
|
|
606
|
+
|
|
607
|
+
Projects each element of the source observable to an observable,
|
|
608
|
+
emitting only from the first inner observable until it completes.
|
|
609
|
+
|
|
610
|
+
Examples:
|
|
611
|
+
Fluent style:
|
|
612
|
+
>>> result = source_of_observables.exclusive()
|
|
613
|
+
|
|
614
|
+
Equivalent pipe style:
|
|
615
|
+
>>> from reactivex import operators as ops
|
|
616
|
+
>>> result = source.pipe(ops.exclusive())
|
|
617
|
+
|
|
618
|
+
Returns:
|
|
619
|
+
An observable sequence containing elements from the first inner
|
|
620
|
+
observable until completion, then the next, and so on.
|
|
621
|
+
|
|
622
|
+
See Also:
|
|
623
|
+
- :func:`exclusive <reactivex.operators.exclusive>`
|
|
624
|
+
- :meth:`concat_map`
|
|
625
|
+
"""
|
|
626
|
+
from reactivex import operators as ops
|
|
627
|
+
|
|
628
|
+
# Cast is safe: exclusive expects Observable[Observable[T]] but
|
|
629
|
+
# we have Observable[_T]. The fluent API allows calling this on
|
|
630
|
+
# sequences of observables.
|
|
631
|
+
source: Observable[Any] = cast("Observable[Any]", self._as_observable())
|
|
632
|
+
return cast("Observable[_T]", ops.exclusive()(source))
|