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
reactivex/operators/_catch.py
CHANGED
|
@@ -1,9 +1,11 @@
|
|
|
1
1
|
from asyncio import Future
|
|
2
|
-
from
|
|
2
|
+
from collections.abc import Callable
|
|
3
|
+
from typing import TypeVar, Union
|
|
3
4
|
|
|
4
5
|
import reactivex
|
|
5
6
|
from reactivex import Observable, abc
|
|
6
7
|
from reactivex.disposable import SerialDisposable, SingleAssignmentDisposable
|
|
8
|
+
from reactivex.internal import curry_flip
|
|
7
9
|
|
|
8
10
|
_T = TypeVar("_T")
|
|
9
11
|
|
|
@@ -13,7 +15,7 @@ def catch_handler(
|
|
|
13
15
|
handler: Callable[[Exception, Observable[_T]], Union[Observable[_T], "Future[_T]"]],
|
|
14
16
|
) -> Observable[_T]:
|
|
15
17
|
def subscribe(
|
|
16
|
-
observer: abc.ObserverBase[_T], scheduler:
|
|
18
|
+
observer: abc.ObserverBase[_T], scheduler: abc.SchedulerBase | None = None
|
|
17
19
|
) -> abc.DisposableBase:
|
|
18
20
|
d1 = SingleAssignmentDisposable()
|
|
19
21
|
subscription = SerialDisposable()
|
|
@@ -42,37 +44,36 @@ def catch_handler(
|
|
|
42
44
|
return Observable(subscribe)
|
|
43
45
|
|
|
44
46
|
|
|
47
|
+
@curry_flip
|
|
45
48
|
def catch_(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
return catch
|
|
49
|
+
source: Observable[_T],
|
|
50
|
+
handler: Observable[_T] | Callable[[Exception, Observable[_T]], Observable[_T]],
|
|
51
|
+
) -> Observable[_T]:
|
|
52
|
+
"""Continues an observable sequence that is terminated by an
|
|
53
|
+
exception with the next observable sequence.
|
|
54
|
+
|
|
55
|
+
Examples:
|
|
56
|
+
>>> res = source.pipe(catch(ys))
|
|
57
|
+
>>> res = catch(ys)(source)
|
|
58
|
+
>>> res = source.pipe(catch(lambda ex, src: ys(ex)))
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
source: The source observable sequence.
|
|
62
|
+
handler: Second observable sequence used to produce
|
|
63
|
+
results when an error occurred in the first sequence, or an
|
|
64
|
+
exception handler function that returns an observable sequence
|
|
65
|
+
given the error and source observable that occurred in the
|
|
66
|
+
first sequence.
|
|
67
|
+
|
|
68
|
+
Returns:
|
|
69
|
+
An observable sequence containing the first sequence's
|
|
70
|
+
elements, followed by the elements of the handler sequence
|
|
71
|
+
in case an exception occurred.
|
|
72
|
+
"""
|
|
73
|
+
if callable(handler):
|
|
74
|
+
return catch_handler(source, handler)
|
|
75
|
+
else:
|
|
76
|
+
return reactivex.catch(source, handler)
|
|
76
77
|
|
|
77
78
|
|
|
78
79
|
__all__ = ["catch_"]
|
|
@@ -1,30 +1,38 @@
|
|
|
1
|
-
from typing import Any,
|
|
1
|
+
from typing import Any, cast
|
|
2
2
|
|
|
3
3
|
import reactivex
|
|
4
4
|
from reactivex import Observable
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
5
6
|
|
|
6
7
|
|
|
8
|
+
@curry_flip
|
|
7
9
|
def combine_latest_(
|
|
10
|
+
source: Observable[Any],
|
|
8
11
|
*others: Observable[Any],
|
|
9
|
-
) ->
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
12
|
+
) -> Observable[tuple[Any, ...]]:
|
|
13
|
+
"""Merges the specified observable sequences into one
|
|
14
|
+
observable sequence by creating a tuple whenever any
|
|
15
|
+
of the observable sequences produces an element.
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
>>> result = source.pipe(combine_latest(other1, other2))
|
|
19
|
+
>>> result = combine_latest(other1, other2)(source)
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
source: The source observable sequence.
|
|
23
|
+
others: Additional observable sequences to combine.
|
|
24
|
+
|
|
25
|
+
Returns:
|
|
26
|
+
An observable sequence containing the result of combining
|
|
27
|
+
elements of the sources into a tuple.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
sources: tuple[Observable[Any], ...] = (source, *others)
|
|
31
|
+
|
|
32
|
+
ret: Observable[tuple[Any, ...]] = cast(
|
|
33
|
+
Observable[tuple[Any, ...]], reactivex.combine_latest(*sources)
|
|
34
|
+
)
|
|
35
|
+
return ret
|
|
28
36
|
|
|
29
37
|
|
|
30
38
|
__all__ = ["combine_latest_"]
|
reactivex/operators/_concat.py
CHANGED
|
@@ -1,26 +1,29 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeVar
|
|
2
2
|
|
|
3
3
|
import reactivex
|
|
4
4
|
from reactivex import Observable
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
5
6
|
|
|
6
7
|
_T = TypeVar("_T")
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
@curry_flip
|
|
11
|
+
def concat_(source: Observable[_T], *sources: Observable[_T]) -> Observable[_T]:
|
|
12
|
+
"""Concatenates all the observable sequences.
|
|
12
13
|
|
|
13
|
-
|
|
14
|
-
|
|
14
|
+
Examples:
|
|
15
|
+
>>> result = source.pipe(concat(xs, ys, zs))
|
|
16
|
+
>>> result = concat(xs, ys, zs)(source)
|
|
15
17
|
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
each given sequence, in sequential order.
|
|
20
|
-
"""
|
|
21
|
-
return reactivex.concat(source, *sources)
|
|
18
|
+
Args:
|
|
19
|
+
source: The source observable sequence.
|
|
20
|
+
sources: Additional observable sequences to concatenate.
|
|
22
21
|
|
|
23
|
-
|
|
22
|
+
Returns:
|
|
23
|
+
An observable sequence that contains the elements of
|
|
24
|
+
each given sequence, in sequential order.
|
|
25
|
+
"""
|
|
26
|
+
return reactivex.concat(source, *sources)
|
|
24
27
|
|
|
25
28
|
|
|
26
29
|
__all__ = ["concat_"]
|
reactivex/operators/_contains.py
CHANGED
|
@@ -1,22 +1,41 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeVar
|
|
2
2
|
|
|
3
|
-
from reactivex import Observable,
|
|
3
|
+
from reactivex import Observable, typing
|
|
4
4
|
from reactivex import operators as ops
|
|
5
|
-
from reactivex import
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
6
6
|
from reactivex.internal.basic import default_comparer
|
|
7
7
|
|
|
8
8
|
_T = TypeVar("_T")
|
|
9
9
|
|
|
10
10
|
|
|
11
|
+
@curry_flip
|
|
11
12
|
def contains_(
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
source: Observable[_T],
|
|
14
|
+
value: _T,
|
|
15
|
+
comparer: typing.Comparer[_T] | None = None,
|
|
16
|
+
) -> Observable[bool]:
|
|
17
|
+
"""Determines whether an observable sequence contains a specified element.
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
>>> result = source.pipe(contains(42))
|
|
21
|
+
>>> result = contains(42)(source)
|
|
22
|
+
>>> result = source.pipe(contains(42, custom_comparer))
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
source: The source observable sequence.
|
|
26
|
+
value: The value to locate in the source sequence.
|
|
27
|
+
comparer: Optional equality comparer to compare elements.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
An observable sequence containing a single element determining
|
|
31
|
+
whether the source sequence contains the specified value.
|
|
32
|
+
"""
|
|
14
33
|
comparer_ = comparer or default_comparer
|
|
15
34
|
|
|
16
35
|
def predicate(v: _T) -> bool:
|
|
17
36
|
return comparer_(v, value)
|
|
18
37
|
|
|
19
|
-
return
|
|
38
|
+
return source.pipe(
|
|
20
39
|
ops.filter(predicate),
|
|
21
40
|
ops.some(),
|
|
22
41
|
)
|
reactivex/operators/_count.py
CHANGED
|
@@ -1,18 +1,35 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeVar
|
|
2
2
|
|
|
3
|
-
from reactivex import Observable
|
|
3
|
+
from reactivex import Observable
|
|
4
4
|
from reactivex import operators as ops
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
5
6
|
from reactivex.typing import Predicate
|
|
6
7
|
|
|
7
8
|
_T = TypeVar("_T")
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
@curry_flip
|
|
10
12
|
def count_(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
source: Observable[_T],
|
|
14
|
+
predicate: Predicate[_T] | None = None,
|
|
15
|
+
) -> Observable[int]:
|
|
16
|
+
"""Returns an observable sequence containing a single element with the
|
|
17
|
+
number of elements in the source sequence.
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
>>> result = source.pipe(count())
|
|
21
|
+
>>> result = count()(source)
|
|
22
|
+
>>> result = source.pipe(count(lambda x: x > 5))
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
source: The source observable.
|
|
26
|
+
predicate: Optional predicate to filter elements before counting.
|
|
27
|
+
|
|
28
|
+
Returns:
|
|
29
|
+
An observable sequence containing a single element with the count.
|
|
30
|
+
"""
|
|
14
31
|
if predicate:
|
|
15
|
-
return
|
|
32
|
+
return source.pipe(
|
|
16
33
|
ops.filter(predicate),
|
|
17
34
|
ops.count(),
|
|
18
35
|
)
|
|
@@ -20,8 +37,7 @@ def count_(
|
|
|
20
37
|
def reducer(n: int, _: _T) -> int:
|
|
21
38
|
return n + 1
|
|
22
39
|
|
|
23
|
-
|
|
24
|
-
return counter
|
|
40
|
+
return source.pipe(ops.reduce(reducer, seed=0))
|
|
25
41
|
|
|
26
42
|
|
|
27
43
|
__all__ = ["count_"]
|
reactivex/operators/_debounce.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import Any, TypeVar, cast
|
|
2
3
|
|
|
3
4
|
from reactivex import Observable, abc, typing
|
|
4
5
|
from reactivex.disposable import (
|
|
@@ -6,169 +7,171 @@ from reactivex.disposable import (
|
|
|
6
7
|
SerialDisposable,
|
|
7
8
|
SingleAssignmentDisposable,
|
|
8
9
|
)
|
|
10
|
+
from reactivex.internal import curry_flip
|
|
9
11
|
from reactivex.scheduler import TimeoutScheduler
|
|
10
12
|
|
|
11
13
|
_T = TypeVar("_T")
|
|
12
14
|
|
|
13
15
|
|
|
16
|
+
@curry_flip
|
|
14
17
|
def debounce_(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def on_error(exception: Exception) -> None:
|
|
58
|
-
cancelable.dispose()
|
|
59
|
-
observer.on_error(exception)
|
|
18
|
+
source: Observable[_T],
|
|
19
|
+
duetime: typing.RelativeTime,
|
|
20
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
21
|
+
) -> Observable[_T]:
|
|
22
|
+
"""Ignores values from an observable sequence which are followed by
|
|
23
|
+
another value before duetime.
|
|
24
|
+
|
|
25
|
+
Examples:
|
|
26
|
+
>>> res = source.pipe(debounce(0.5))
|
|
27
|
+
>>> res = debounce(0.5)(source)
|
|
28
|
+
|
|
29
|
+
Args:
|
|
30
|
+
source: Source observable to debounce.
|
|
31
|
+
duetime: Duration to wait before emitting.
|
|
32
|
+
scheduler: Scheduler to use.
|
|
33
|
+
|
|
34
|
+
Returns:
|
|
35
|
+
The debounced observable sequence.
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
def subscribe(
|
|
39
|
+
observer: abc.ObserverBase[_T],
|
|
40
|
+
scheduler_: abc.SchedulerBase | None = None,
|
|
41
|
+
) -> abc.DisposableBase:
|
|
42
|
+
_scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
|
|
43
|
+
cancelable = SerialDisposable()
|
|
44
|
+
has_value = [False]
|
|
45
|
+
value: list[_T] = [cast(_T, None)]
|
|
46
|
+
_id: list[int] = [0]
|
|
47
|
+
|
|
48
|
+
def on_next(x: _T) -> None:
|
|
49
|
+
has_value[0] = True
|
|
50
|
+
value[0] = x
|
|
51
|
+
_id[0] += 1
|
|
52
|
+
current_id = _id[0]
|
|
53
|
+
d = SingleAssignmentDisposable()
|
|
54
|
+
cancelable.disposable = d
|
|
55
|
+
|
|
56
|
+
def action(scheduler: abc.SchedulerBase, state: Any = None) -> None:
|
|
57
|
+
if has_value[0] and _id[0] == current_id:
|
|
58
|
+
observer.on_next(value[0])
|
|
60
59
|
has_value[0] = False
|
|
61
|
-
_id[0] += 1
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
cancelable.dispose()
|
|
65
|
-
if has_value[0]:
|
|
66
|
-
observer.on_next(value[0])
|
|
61
|
+
d.disposable = _scheduler.schedule_relative(duetime, action)
|
|
67
62
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
63
|
+
def on_error(exception: Exception) -> None:
|
|
64
|
+
cancelable.dispose()
|
|
65
|
+
observer.on_error(exception)
|
|
66
|
+
has_value[0] = False
|
|
67
|
+
_id[0] += 1
|
|
71
68
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
def on_completed() -> None:
|
|
70
|
+
cancelable.dispose()
|
|
71
|
+
if has_value[0]:
|
|
72
|
+
observer.on_next(value[0])
|
|
73
|
+
|
|
74
|
+
observer.on_completed()
|
|
75
|
+
has_value[0] = False
|
|
76
|
+
_id[0] += 1
|
|
76
77
|
|
|
77
|
-
|
|
78
|
+
subscription = source.subscribe(
|
|
79
|
+
on_next, on_error, on_completed, scheduler=scheduler_
|
|
80
|
+
)
|
|
81
|
+
return CompositeDisposable(subscription, cancelable)
|
|
78
82
|
|
|
79
|
-
return
|
|
83
|
+
return Observable(subscribe)
|
|
80
84
|
|
|
81
85
|
|
|
86
|
+
@curry_flip
|
|
82
87
|
def throttle_with_mapper_(
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
observer.on_error(e)
|
|
118
|
-
return
|
|
119
|
-
|
|
120
|
-
has_value = True
|
|
121
|
-
value = x
|
|
122
|
-
_id[0] += 1
|
|
123
|
-
current_id = _id[0]
|
|
124
|
-
d = SingleAssignmentDisposable()
|
|
125
|
-
cancelable.disposable = d
|
|
126
|
-
|
|
127
|
-
def on_next(x: Any) -> None:
|
|
128
|
-
nonlocal has_value
|
|
129
|
-
if has_value and _id[0] == current_id:
|
|
130
|
-
observer.on_next(value)
|
|
131
|
-
|
|
132
|
-
has_value = False
|
|
133
|
-
d.dispose()
|
|
134
|
-
|
|
135
|
-
def on_completed() -> None:
|
|
136
|
-
nonlocal has_value
|
|
137
|
-
if has_value and _id[0] == current_id:
|
|
138
|
-
observer.on_next(value)
|
|
139
|
-
|
|
140
|
-
has_value = False
|
|
141
|
-
d.dispose()
|
|
142
|
-
|
|
143
|
-
d.disposable = throttle.subscribe(
|
|
144
|
-
on_next, observer.on_error, on_completed, scheduler=scheduler
|
|
145
|
-
)
|
|
146
|
-
|
|
147
|
-
def on_error(e: Exception) -> None:
|
|
148
|
-
nonlocal has_value
|
|
149
|
-
cancelable.dispose()
|
|
88
|
+
source: Observable[_T],
|
|
89
|
+
throttle_duration_mapper: Callable[[Any], Observable[Any]],
|
|
90
|
+
) -> Observable[_T]:
|
|
91
|
+
"""Ignores values from an observable sequence which are followed by
|
|
92
|
+
another value within a computed throttle duration.
|
|
93
|
+
|
|
94
|
+
Examples:
|
|
95
|
+
>>> res = source.pipe(throttle_with_mapper(lambda x: timer(x)))
|
|
96
|
+
>>> res = throttle_with_mapper(lambda x: timer(x))(source)
|
|
97
|
+
|
|
98
|
+
Args:
|
|
99
|
+
source: The observable source to throttle.
|
|
100
|
+
throttle_duration_mapper: Function to compute throttle duration.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
The throttled observable sequence.
|
|
104
|
+
"""
|
|
105
|
+
|
|
106
|
+
def subscribe(
|
|
107
|
+
observer: abc.ObserverBase[_T],
|
|
108
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
109
|
+
) -> abc.DisposableBase:
|
|
110
|
+
cancelable = SerialDisposable()
|
|
111
|
+
has_value: bool = False
|
|
112
|
+
value: _T = cast(_T, None)
|
|
113
|
+
_id = [0]
|
|
114
|
+
|
|
115
|
+
def on_next(x: _T) -> None:
|
|
116
|
+
nonlocal value, has_value
|
|
117
|
+
|
|
118
|
+
throttle = None
|
|
119
|
+
try:
|
|
120
|
+
throttle = throttle_duration_mapper(x)
|
|
121
|
+
except Exception as e: # pylint: disable=broad-except
|
|
150
122
|
observer.on_error(e)
|
|
123
|
+
return
|
|
124
|
+
|
|
125
|
+
has_value = True
|
|
126
|
+
value = x
|
|
127
|
+
_id[0] += 1
|
|
128
|
+
current_id = _id[0]
|
|
129
|
+
d = SingleAssignmentDisposable()
|
|
130
|
+
cancelable.disposable = d
|
|
131
|
+
|
|
132
|
+
def on_next(x: Any) -> None:
|
|
133
|
+
nonlocal has_value
|
|
134
|
+
if has_value and _id[0] == current_id:
|
|
135
|
+
observer.on_next(value)
|
|
136
|
+
|
|
151
137
|
has_value = False
|
|
152
|
-
|
|
138
|
+
d.dispose()
|
|
153
139
|
|
|
154
140
|
def on_completed() -> None:
|
|
155
141
|
nonlocal has_value
|
|
156
|
-
|
|
157
|
-
if has_value:
|
|
142
|
+
if has_value and _id[0] == current_id:
|
|
158
143
|
observer.on_next(value)
|
|
159
144
|
|
|
160
|
-
observer.on_completed()
|
|
161
145
|
has_value = False
|
|
162
|
-
|
|
146
|
+
d.dispose()
|
|
163
147
|
|
|
164
|
-
|
|
165
|
-
on_next, on_error, on_completed, scheduler=scheduler
|
|
148
|
+
d.disposable = throttle.subscribe(
|
|
149
|
+
on_next, observer.on_error, on_completed, scheduler=scheduler
|
|
166
150
|
)
|
|
167
|
-
return CompositeDisposable(subscription, cancelable)
|
|
168
|
-
|
|
169
|
-
return Observable(subscribe)
|
|
170
151
|
|
|
171
|
-
|
|
152
|
+
def on_error(e: Exception) -> None:
|
|
153
|
+
nonlocal has_value
|
|
154
|
+
cancelable.dispose()
|
|
155
|
+
observer.on_error(e)
|
|
156
|
+
has_value = False
|
|
157
|
+
_id[0] += 1
|
|
158
|
+
|
|
159
|
+
def on_completed() -> None:
|
|
160
|
+
nonlocal has_value
|
|
161
|
+
cancelable.dispose()
|
|
162
|
+
if has_value:
|
|
163
|
+
observer.on_next(value)
|
|
164
|
+
|
|
165
|
+
observer.on_completed()
|
|
166
|
+
has_value = False
|
|
167
|
+
_id[0] += 1
|
|
168
|
+
|
|
169
|
+
subscription = source.subscribe(
|
|
170
|
+
on_next, on_error, on_completed, scheduler=scheduler
|
|
171
|
+
)
|
|
172
|
+
return CompositeDisposable(subscription, cancelable)
|
|
173
|
+
|
|
174
|
+
return Observable(subscribe)
|
|
172
175
|
|
|
173
176
|
|
|
174
177
|
__all__ = ["debounce_", "throttle_with_mapper_"]
|