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
|
@@ -1,53 +1,58 @@
|
|
|
1
|
-
from typing import Any,
|
|
1
|
+
from typing import Any, TypeVar
|
|
2
2
|
|
|
3
3
|
from reactivex import Observable, abc, typing
|
|
4
4
|
from reactivex.disposable import CompositeDisposable
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
5
6
|
from reactivex.scheduler import TimeoutScheduler
|
|
6
7
|
|
|
7
8
|
_T = TypeVar("_T")
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
@curry_flip
|
|
10
12
|
def take_with_time_(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
13
|
+
source: Observable[_T],
|
|
14
|
+
duration: typing.RelativeTime,
|
|
15
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
16
|
+
) -> Observable[_T]:
|
|
17
|
+
"""Takes elements for the specified duration from the start of
|
|
18
|
+
the observable source sequence.
|
|
19
|
+
|
|
20
|
+
Examples:
|
|
21
|
+
>>> source.pipe(take_with_time(5.0))
|
|
22
|
+
>>> take_with_time(5.0)(source)
|
|
23
|
+
|
|
24
|
+
This operator accumulates a queue with a length enough to store
|
|
25
|
+
elements received during the initial duration window. As more
|
|
26
|
+
elements are received, elements older than the specified
|
|
27
|
+
duration are taken from the queue and produced on the result
|
|
28
|
+
sequence. This causes elements to be delayed with duration.
|
|
29
|
+
|
|
30
|
+
Args:
|
|
31
|
+
source: Source observable to take elements from.
|
|
32
|
+
duration: Duration for taking elements from the start of
|
|
33
|
+
the sequence.
|
|
34
|
+
scheduler: Scheduler to use for timing.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
An observable sequence with the elements taken during the
|
|
38
|
+
specified duration from the start of the source sequence.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
def subscribe(
|
|
42
|
+
observer: abc.ObserverBase[_T],
|
|
43
|
+
scheduler_: abc.SchedulerBase | None = None,
|
|
44
|
+
) -> abc.DisposableBase:
|
|
45
|
+
_scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
|
|
46
|
+
|
|
47
|
+
def action(scheduler: abc.SchedulerBase, state: Any = None):
|
|
48
|
+
observer.on_completed()
|
|
49
|
+
|
|
50
|
+
disp = _scheduler.schedule_relative(duration, action)
|
|
51
|
+
return CompositeDisposable(
|
|
52
|
+
disp, source.subscribe(observer, scheduler=scheduler_)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
return Observable(subscribe)
|
|
51
56
|
|
|
52
57
|
|
|
53
58
|
__all__ = ["take_with_time_"]
|
|
@@ -1,57 +1,64 @@
|
|
|
1
1
|
from datetime import datetime
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TypeVar
|
|
3
3
|
|
|
4
4
|
from reactivex import Observable, abc, typing
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
5
6
|
from reactivex.scheduler import TimeoutScheduler
|
|
6
7
|
|
|
7
8
|
_T = TypeVar("_T")
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
@curry_flip
|
|
10
12
|
def throttle_first_(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
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
|
-
|
|
13
|
+
source: Observable[_T],
|
|
14
|
+
window_duration: typing.RelativeTime,
|
|
15
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
16
|
+
) -> Observable[_T]:
|
|
17
|
+
"""Returns an observable that emits only the first item emitted
|
|
18
|
+
by the source Observable during sequential time windows of a
|
|
19
|
+
specified duration.
|
|
20
|
+
|
|
21
|
+
Examples:
|
|
22
|
+
>>> result = source.pipe(throttle_first(1.0))
|
|
23
|
+
>>> result = throttle_first(1.0)(source)
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
source: Source observable to throttle.
|
|
27
|
+
window_duration: Duration of windows during which to throttle.
|
|
28
|
+
scheduler: Optional scheduler to use for timing.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
An Observable that performs the throttle operation.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def subscribe(
|
|
35
|
+
observer: abc.ObserverBase[_T],
|
|
36
|
+
scheduler_: abc.SchedulerBase | None = None,
|
|
37
|
+
) -> abc.DisposableBase:
|
|
38
|
+
_scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
|
|
39
|
+
|
|
40
|
+
duration = _scheduler.to_timedelta(window_duration or 0.0)
|
|
41
|
+
if duration <= _scheduler.to_timedelta(0):
|
|
42
|
+
raise ValueError("window_duration cannot be less or equal zero.")
|
|
43
|
+
last_on_next: datetime | None = None
|
|
44
|
+
|
|
45
|
+
def on_next(x: _T) -> None:
|
|
46
|
+
nonlocal last_on_next
|
|
47
|
+
emit = False
|
|
48
|
+
now = _scheduler.now
|
|
49
|
+
|
|
50
|
+
with source.lock:
|
|
51
|
+
if not last_on_next or now - last_on_next >= duration:
|
|
52
|
+
last_on_next = now
|
|
53
|
+
emit = True
|
|
54
|
+
if emit:
|
|
55
|
+
observer.on_next(x)
|
|
56
|
+
|
|
57
|
+
return source.subscribe(
|
|
58
|
+
on_next, observer.on_error, observer.on_completed, scheduler=_scheduler
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
return Observable(subscribe)
|
|
55
62
|
|
|
56
63
|
|
|
57
64
|
__all__ = ["throttle_first_"]
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from datetime import timedelta
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Generic, TypeVar
|
|
4
4
|
|
|
5
5
|
from reactivex import Observable, abc
|
|
6
6
|
from reactivex import operators as ops
|
|
7
|
+
from reactivex.internal import curry_flip
|
|
7
8
|
from reactivex.scheduler import TimeoutScheduler
|
|
8
9
|
|
|
9
10
|
_T = TypeVar("_T")
|
|
@@ -15,39 +16,42 @@ class TimeInterval(Generic[_T]):
|
|
|
15
16
|
interval: timedelta
|
|
16
17
|
|
|
17
18
|
|
|
19
|
+
@curry_flip
|
|
18
20
|
def time_interval_(
|
|
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
|
-
|
|
21
|
+
source: Observable[_T],
|
|
22
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
23
|
+
) -> Observable[TimeInterval[_T]]:
|
|
24
|
+
"""Records the time interval between consecutive values in an
|
|
25
|
+
observable sequence.
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
>>> res = source.pipe(time_interval())
|
|
29
|
+
>>> res = time_interval()(source)
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
source: The source observable sequence.
|
|
33
|
+
scheduler: Scheduler to use for timing.
|
|
34
|
+
|
|
35
|
+
Returns:
|
|
36
|
+
An observable sequence with time interval information on
|
|
37
|
+
values.
|
|
38
|
+
"""
|
|
39
|
+
|
|
40
|
+
def subscribe(
|
|
41
|
+
observer: abc.ObserverBase[TimeInterval[_T]],
|
|
42
|
+
scheduler_: abc.SchedulerBase | None = None,
|
|
43
|
+
) -> abc.DisposableBase:
|
|
44
|
+
_scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
|
|
45
|
+
last = _scheduler.now
|
|
46
|
+
|
|
47
|
+
def mapper(value: _T) -> TimeInterval[_T]:
|
|
48
|
+
nonlocal last
|
|
49
|
+
|
|
50
|
+
now = _scheduler.now
|
|
51
|
+
span = now - last
|
|
52
|
+
last = now
|
|
53
|
+
return TimeInterval(value=value, interval=span)
|
|
54
|
+
|
|
55
|
+
return source.pipe(ops.map(mapper)).subscribe(observer, scheduler=_scheduler)
|
|
56
|
+
|
|
57
|
+
return Observable(subscribe)
|
reactivex/operators/_timeout.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
from asyncio import Future
|
|
2
2
|
from datetime import datetime
|
|
3
|
-
from typing import Any,
|
|
3
|
+
from typing import Any, TypeVar, Union
|
|
4
4
|
|
|
5
5
|
from reactivex import Observable, abc, from_future, throw, typing
|
|
6
6
|
from reactivex.disposable import (
|
|
@@ -8,94 +8,96 @@ from reactivex.disposable import (
|
|
|
8
8
|
SerialDisposable,
|
|
9
9
|
SingleAssignmentDisposable,
|
|
10
10
|
)
|
|
11
|
+
from reactivex.internal import curry_flip
|
|
11
12
|
from reactivex.scheduler import TimeoutScheduler
|
|
12
13
|
|
|
13
14
|
_T = TypeVar("_T")
|
|
14
15
|
|
|
15
16
|
|
|
17
|
+
@curry_flip
|
|
16
18
|
def timeout_(
|
|
19
|
+
source: Observable[_T],
|
|
17
20
|
duetime: typing.AbsoluteOrRelativeTime,
|
|
18
|
-
other:
|
|
19
|
-
scheduler:
|
|
20
|
-
) ->
|
|
21
|
-
|
|
21
|
+
other: Union[Observable[_T], "Future[_T]"] | None = None,
|
|
22
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
23
|
+
) -> Observable[_T]:
|
|
24
|
+
"""Returns the source observable sequence or the other observable
|
|
25
|
+
sequence if duetime elapses.
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
>>> source.pipe(timeout(5.0))
|
|
29
|
+
>>> timeout(5.0)(source)
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
source: Source observable to timeout.
|
|
33
|
+
duetime: Timeout duration.
|
|
34
|
+
other: Observable to switch to on timeout.
|
|
35
|
+
scheduler: Scheduler to use for timing.
|
|
36
|
+
|
|
37
|
+
Returns:
|
|
38
|
+
An observable sequence switching to the other sequence in
|
|
39
|
+
case of a timeout.
|
|
40
|
+
"""
|
|
22
41
|
other = other or throw(Exception("Timeout"))
|
|
23
42
|
if isinstance(other, Future):
|
|
24
43
|
obs = from_future(other)
|
|
25
44
|
else:
|
|
26
45
|
obs = other
|
|
27
46
|
|
|
28
|
-
def
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
_id[0] += 1
|
|
86
|
-
observer.on_error(error)
|
|
87
|
-
|
|
88
|
-
def on_completed() -> None:
|
|
89
|
-
on_completed_wins = not switched[0]
|
|
90
|
-
if on_completed_wins:
|
|
91
|
-
_id[0] += 1
|
|
92
|
-
observer.on_completed()
|
|
93
|
-
|
|
94
|
-
original.disposable = source.subscribe(
|
|
95
|
-
on_next, on_error, on_completed, scheduler=scheduler_
|
|
96
|
-
)
|
|
97
|
-
return CompositeDisposable(subscription, timer)
|
|
98
|
-
|
|
99
|
-
return Observable(subscribe)
|
|
100
|
-
|
|
101
|
-
return timeout
|
|
47
|
+
def subscribe(
|
|
48
|
+
observer: abc.ObserverBase[_T],
|
|
49
|
+
scheduler_: abc.SchedulerBase | None = None,
|
|
50
|
+
) -> abc.DisposableBase:
|
|
51
|
+
_scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
|
|
52
|
+
|
|
53
|
+
switched = [False]
|
|
54
|
+
_id = [0]
|
|
55
|
+
|
|
56
|
+
original = SingleAssignmentDisposable()
|
|
57
|
+
subscription = SerialDisposable()
|
|
58
|
+
timer = SerialDisposable()
|
|
59
|
+
subscription.disposable = original
|
|
60
|
+
|
|
61
|
+
def create_timer() -> None:
|
|
62
|
+
my_id = _id[0]
|
|
63
|
+
|
|
64
|
+
def action(scheduler: abc.SchedulerBase, state: Any = None):
|
|
65
|
+
switched[0] = _id[0] == my_id
|
|
66
|
+
timer_wins = switched[0]
|
|
67
|
+
if timer_wins:
|
|
68
|
+
subscription.disposable = obs.subscribe(
|
|
69
|
+
observer, scheduler=scheduler
|
|
70
|
+
)
|
|
71
|
+
|
|
72
|
+
if isinstance(duetime, datetime):
|
|
73
|
+
timer.disposable = _scheduler.schedule_absolute(duetime, action)
|
|
74
|
+
else:
|
|
75
|
+
timer.disposable = _scheduler.schedule_relative(duetime, action)
|
|
76
|
+
|
|
77
|
+
create_timer()
|
|
78
|
+
|
|
79
|
+
def on_next(value: _T) -> None:
|
|
80
|
+
send_wins = not switched[0]
|
|
81
|
+
if send_wins:
|
|
82
|
+
_id[0] += 1
|
|
83
|
+
observer.on_next(value)
|
|
84
|
+
create_timer()
|
|
85
|
+
|
|
86
|
+
def on_error(error: Exception) -> None:
|
|
87
|
+
on_error_wins = not switched[0]
|
|
88
|
+
if on_error_wins:
|
|
89
|
+
_id[0] += 1
|
|
90
|
+
observer.on_error(error)
|
|
91
|
+
|
|
92
|
+
def on_completed() -> None:
|
|
93
|
+
on_completed_wins = not switched[0]
|
|
94
|
+
if on_completed_wins:
|
|
95
|
+
_id[0] += 1
|
|
96
|
+
observer.on_completed()
|
|
97
|
+
|
|
98
|
+
original.disposable = source.subscribe(
|
|
99
|
+
on_next, on_error, on_completed, scheduler=scheduler_
|
|
100
|
+
)
|
|
101
|
+
return CompositeDisposable(subscription, timer)
|
|
102
|
+
|
|
103
|
+
return Observable(subscribe)
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import Any, TypeVar
|
|
2
3
|
|
|
3
4
|
import reactivex
|
|
4
5
|
from reactivex import Observable, abc
|
|
@@ -12,9 +13,9 @@ _T = TypeVar("_T")
|
|
|
12
13
|
|
|
13
14
|
|
|
14
15
|
def timeout_with_mapper_(
|
|
15
|
-
first_timeout:
|
|
16
|
-
timeout_duration_mapper:
|
|
17
|
-
other:
|
|
16
|
+
first_timeout: Observable[_T] | None = None,
|
|
17
|
+
timeout_duration_mapper: Callable[[Any], Observable[Any]] | None = None,
|
|
18
|
+
other: Observable[_T] | None = None,
|
|
18
19
|
) -> Callable[[Observable[_T]], Observable[_T]]:
|
|
19
20
|
"""Returns the source observable sequence, switching to the other
|
|
20
21
|
observable sequence if a timeout is signaled.
|
|
@@ -48,7 +49,7 @@ def timeout_with_mapper_(
|
|
|
48
49
|
def timeout_with_mapper(source: Observable[_T]) -> Observable[_T]:
|
|
49
50
|
def subscribe(
|
|
50
51
|
observer: abc.ObserverBase[_T],
|
|
51
|
-
scheduler:
|
|
52
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
52
53
|
) -> abc.DisposableBase:
|
|
53
54
|
subscription = SerialDisposable()
|
|
54
55
|
timer = SerialDisposable()
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
2
|
from datetime import datetime
|
|
3
|
-
from typing import
|
|
3
|
+
from typing import Generic, TypeVar
|
|
4
4
|
|
|
5
5
|
from reactivex import Observable, abc, defer, operators
|
|
6
|
+
from reactivex.internal import curry_flip
|
|
6
7
|
from reactivex.scheduler import TimeoutScheduler
|
|
7
8
|
|
|
8
9
|
_T = TypeVar("_T")
|
|
@@ -14,36 +15,37 @@ class Timestamp(Generic[_T]):
|
|
|
14
15
|
timestamp: datetime
|
|
15
16
|
|
|
16
17
|
|
|
18
|
+
@curry_flip
|
|
17
19
|
def timestamp_(
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
source: Observable[_T],
|
|
21
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
22
|
+
) -> Observable[Timestamp[_T]]:
|
|
23
|
+
"""Records the timestamp for each value in an observable sequence.
|
|
22
24
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
+
Examples:
|
|
26
|
+
>>> result = source.pipe(timestamp())
|
|
27
|
+
>>> result = timestamp()(source)
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
29
|
+
Produces objects with attributes `value` and `timestamp`, where
|
|
30
|
+
value is the original value.
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
32
|
+
Args:
|
|
33
|
+
source: Observable source to timestamp.
|
|
34
|
+
scheduler: Optional scheduler to use for timestamping.
|
|
31
35
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
36
|
+
Returns:
|
|
37
|
+
An observable sequence with timestamp information on values.
|
|
38
|
+
"""
|
|
35
39
|
|
|
36
|
-
|
|
37
|
-
|
|
40
|
+
def factory(scheduler_: abc.SchedulerBase | None = None):
|
|
41
|
+
_scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
|
|
43
|
+
def mapper(value: _T) -> Timestamp[_T]:
|
|
44
|
+
return Timestamp(value=value, timestamp=_scheduler.now)
|
|
41
45
|
|
|
42
|
-
|
|
46
|
+
return source.pipe(operators.map(mapper))
|
|
43
47
|
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return timestamp
|
|
48
|
+
return defer(factory)
|
|
47
49
|
|
|
48
50
|
|
|
49
51
|
__all__ = ["timestamp_"]
|