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/_all.py
CHANGED
|
@@ -1,21 +1,38 @@
|
|
|
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
|
|
|
10
|
-
|
|
11
|
-
|
|
11
|
+
@curry_flip
|
|
12
|
+
def all_(source: Observable[_T], predicate: Predicate[_T]) -> Observable[bool]:
|
|
13
|
+
"""Determines whether all elements of an observable sequence satisfy a condition.
|
|
14
|
+
|
|
15
|
+
Examples:
|
|
16
|
+
>>> result = source.pipe(all(lambda x: x > 0))
|
|
17
|
+
>>> result = all(lambda x: x > 0)(source)
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
source: The source observable sequence.
|
|
21
|
+
predicate: A function to test each element for a condition.
|
|
22
|
+
|
|
23
|
+
Returns:
|
|
24
|
+
An observable sequence containing a single element determining
|
|
25
|
+
whether all elements in the source sequence pass the test.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def filter_fn(v: _T):
|
|
12
29
|
return not predicate(v)
|
|
13
30
|
|
|
14
31
|
def mapping(b: bool) -> bool:
|
|
15
32
|
return not b
|
|
16
33
|
|
|
17
|
-
return
|
|
18
|
-
ops.filter(
|
|
34
|
+
return source.pipe(
|
|
35
|
+
ops.filter(filter_fn),
|
|
19
36
|
ops.some(),
|
|
20
37
|
ops.map(mapping),
|
|
21
38
|
)
|
reactivex/operators/_amb.py
CHANGED
|
@@ -1,92 +1,105 @@
|
|
|
1
1
|
from asyncio import Future
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TypeVar, Union
|
|
3
3
|
|
|
4
4
|
from reactivex import Observable, abc, from_future
|
|
5
5
|
from reactivex.disposable import CompositeDisposable, SingleAssignmentDisposable
|
|
6
|
+
from reactivex.internal import curry_flip
|
|
6
7
|
|
|
7
8
|
_T = TypeVar("_T")
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
@curry_flip
|
|
10
12
|
def amb_(
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
left_source: Observable[_T],
|
|
14
|
+
right_source: Union[Observable[_T], "Future[_T]"],
|
|
15
|
+
) -> Observable[_T]:
|
|
16
|
+
"""Propagates the observable sequence that reacts first.
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
>>> result = source.pipe(amb(other_source))
|
|
20
|
+
>>> result = amb(other_source)(source)
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
left_source: The left source observable.
|
|
24
|
+
right_source: The right source observable or future.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
An observable sequence that surfaces either of the given sequences,
|
|
28
|
+
whichever reacted first.
|
|
29
|
+
"""
|
|
14
30
|
if isinstance(right_source, Future):
|
|
15
31
|
obs: Observable[_T] = from_future(right_source)
|
|
16
32
|
else:
|
|
17
33
|
obs = right_source
|
|
18
34
|
|
|
19
|
-
def
|
|
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
|
-
|
|
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
|
-
|
|
86
|
-
|
|
87
|
-
return Observable(subscribe)
|
|
88
|
-
|
|
89
|
-
return amb
|
|
35
|
+
def subscribe(
|
|
36
|
+
observer: abc.ObserverBase[_T],
|
|
37
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
38
|
+
) -> abc.DisposableBase:
|
|
39
|
+
choice: list[str | None] = [None]
|
|
40
|
+
left_choice = "L"
|
|
41
|
+
right_choice = "R"
|
|
42
|
+
left_subscription = SingleAssignmentDisposable()
|
|
43
|
+
right_subscription = SingleAssignmentDisposable()
|
|
44
|
+
|
|
45
|
+
def choice_left():
|
|
46
|
+
if not choice[0]:
|
|
47
|
+
choice[0] = left_choice
|
|
48
|
+
right_subscription.dispose()
|
|
49
|
+
|
|
50
|
+
def choice_right():
|
|
51
|
+
if not choice[0]:
|
|
52
|
+
choice[0] = right_choice
|
|
53
|
+
left_subscription.dispose()
|
|
54
|
+
|
|
55
|
+
def on_next_left(value: _T) -> None:
|
|
56
|
+
with left_source.lock:
|
|
57
|
+
choice_left()
|
|
58
|
+
if choice[0] == left_choice:
|
|
59
|
+
observer.on_next(value)
|
|
60
|
+
|
|
61
|
+
def on_error_left(err: Exception) -> None:
|
|
62
|
+
with left_source.lock:
|
|
63
|
+
choice_left()
|
|
64
|
+
if choice[0] == left_choice:
|
|
65
|
+
observer.on_error(err)
|
|
66
|
+
|
|
67
|
+
def on_completed_left() -> None:
|
|
68
|
+
with left_source.lock:
|
|
69
|
+
choice_left()
|
|
70
|
+
if choice[0] == left_choice:
|
|
71
|
+
observer.on_completed()
|
|
72
|
+
|
|
73
|
+
left_d = left_source.subscribe(
|
|
74
|
+
on_next_left, on_error_left, on_completed_left, scheduler=scheduler
|
|
75
|
+
)
|
|
76
|
+
left_subscription.disposable = left_d
|
|
77
|
+
|
|
78
|
+
def send_right(value: _T) -> None:
|
|
79
|
+
with left_source.lock:
|
|
80
|
+
choice_right()
|
|
81
|
+
if choice[0] == right_choice:
|
|
82
|
+
observer.on_next(value)
|
|
83
|
+
|
|
84
|
+
def on_error_right(err: Exception) -> None:
|
|
85
|
+
with left_source.lock:
|
|
86
|
+
choice_right()
|
|
87
|
+
if choice[0] == right_choice:
|
|
88
|
+
observer.on_error(err)
|
|
89
|
+
|
|
90
|
+
def on_completed_right() -> None:
|
|
91
|
+
with left_source.lock:
|
|
92
|
+
choice_right()
|
|
93
|
+
if choice[0] == right_choice:
|
|
94
|
+
observer.on_completed()
|
|
95
|
+
|
|
96
|
+
right_d = obs.subscribe(
|
|
97
|
+
send_right, on_error_right, on_completed_right, scheduler=scheduler
|
|
98
|
+
)
|
|
99
|
+
right_subscription.disposable = right_d
|
|
100
|
+
return CompositeDisposable(left_subscription, right_subscription)
|
|
101
|
+
|
|
102
|
+
return Observable(subscribe)
|
|
90
103
|
|
|
91
104
|
|
|
92
105
|
__all__ = ["amb_"]
|
|
@@ -1,31 +1,34 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeVar
|
|
2
2
|
|
|
3
3
|
from reactivex import Observable, abc
|
|
4
|
+
from reactivex.internal import curry_flip
|
|
4
5
|
|
|
5
6
|
_T = TypeVar("_T")
|
|
6
7
|
|
|
7
8
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
@curry_flip
|
|
10
|
+
def as_observable_(source: Observable[_T]) -> Observable[_T]:
|
|
11
|
+
"""Hides the identity of an observable sequence.
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
Examples:
|
|
14
|
+
>>> res = source.pipe(as_observable())
|
|
15
|
+
>>> res = as_observable()(source)
|
|
14
16
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
source sequence.
|
|
18
|
-
"""
|
|
17
|
+
Args:
|
|
18
|
+
source: Observable source to hide identity from.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
return source.subscribe(observer, scheduler=scheduler)
|
|
20
|
+
Returns:
|
|
21
|
+
An observable sequence that hides the identity of the
|
|
22
|
+
source sequence.
|
|
23
|
+
"""
|
|
25
24
|
|
|
26
|
-
|
|
25
|
+
def subscribe(
|
|
26
|
+
observer: abc.ObserverBase[_T],
|
|
27
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
28
|
+
) -> abc.DisposableBase:
|
|
29
|
+
return source.subscribe(observer, scheduler=scheduler)
|
|
27
30
|
|
|
28
|
-
return
|
|
31
|
+
return Observable(subscribe)
|
|
29
32
|
|
|
30
33
|
|
|
31
34
|
__all__ = ["as_observable_"]
|
reactivex/operators/_average.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import Any,
|
|
2
|
+
from typing import Any, TypeVar, cast
|
|
3
3
|
|
|
4
4
|
from reactivex import Observable, operators, typing
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
5
6
|
|
|
6
7
|
_T = TypeVar("_T")
|
|
7
8
|
|
|
@@ -12,51 +13,53 @@ class AverageValue:
|
|
|
12
13
|
count: int
|
|
13
14
|
|
|
14
15
|
|
|
16
|
+
@curry_flip
|
|
15
17
|
def average_(
|
|
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
|
-
|
|
58
|
-
|
|
59
|
-
|
|
18
|
+
source: Observable[_T],
|
|
19
|
+
key_mapper: typing.Mapper[_T, float] | None = None,
|
|
20
|
+
) -> Observable[float]:
|
|
21
|
+
"""Computes the average of an observable sequence of values.
|
|
22
|
+
|
|
23
|
+
Computes the average of an observable sequence of values that
|
|
24
|
+
are in the sequence or obtained by invoking a transform
|
|
25
|
+
function on each element of the input sequence if present.
|
|
26
|
+
|
|
27
|
+
Examples:
|
|
28
|
+
>>> result = source.pipe(average())
|
|
29
|
+
>>> result = average()(source)
|
|
30
|
+
>>> result = source.pipe(average(lambda x: x.value))
|
|
31
|
+
|
|
32
|
+
Args:
|
|
33
|
+
source: Source observable to average.
|
|
34
|
+
key_mapper: Optional mapper to extract numeric values.
|
|
35
|
+
|
|
36
|
+
Returns:
|
|
37
|
+
An observable sequence containing a single element with the
|
|
38
|
+
average of the sequence of values.
|
|
39
|
+
"""
|
|
40
|
+
|
|
41
|
+
key_mapper_: typing.Mapper[_T, float] = key_mapper or (
|
|
42
|
+
lambda x: float(cast(Any, x))
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
def accumulator(prev: AverageValue, cur: float) -> AverageValue:
|
|
46
|
+
return AverageValue(sum=prev.sum + cur, count=prev.count + 1)
|
|
47
|
+
|
|
48
|
+
def mapper(s: AverageValue) -> float:
|
|
49
|
+
if s.count == 0:
|
|
50
|
+
raise Exception("The input sequence was empty")
|
|
51
|
+
|
|
52
|
+
return s.sum / float(s.count)
|
|
53
|
+
|
|
54
|
+
seed = AverageValue(sum=0, count=0)
|
|
55
|
+
|
|
56
|
+
ret = source.pipe(
|
|
57
|
+
operators.map(key_mapper_),
|
|
58
|
+
operators.scan(accumulator, seed),
|
|
59
|
+
operators.last(),
|
|
60
|
+
operators.map(mapper),
|
|
61
|
+
)
|
|
62
|
+
return ret
|
|
60
63
|
|
|
61
64
|
|
|
62
65
|
__all__ = ["average_"]
|
reactivex/operators/_buffer.py
CHANGED
|
@@ -1,80 +1,126 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import Any, TypeVar
|
|
2
3
|
|
|
3
|
-
from reactivex import Observable
|
|
4
|
+
from reactivex import Observable
|
|
4
5
|
from reactivex import operators as ops
|
|
6
|
+
from reactivex.internal import curry_flip
|
|
5
7
|
|
|
6
8
|
_T = TypeVar("_T")
|
|
7
9
|
|
|
8
10
|
|
|
11
|
+
@curry_flip
|
|
9
12
|
def buffer_(
|
|
13
|
+
source: Observable[_T],
|
|
10
14
|
boundaries: Observable[Any],
|
|
11
|
-
) ->
|
|
12
|
-
|
|
15
|
+
) -> Observable[list[_T]]:
|
|
16
|
+
"""Buffers elements from the source based on boundary notifications.
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
>>> res = source.pipe(buffer(boundaries))
|
|
20
|
+
>>> res = buffer(boundaries)(source)
|
|
21
|
+
|
|
22
|
+
Args:
|
|
23
|
+
source: Source observable to buffer.
|
|
24
|
+
boundaries: Observable that triggers buffer emissions.
|
|
25
|
+
|
|
26
|
+
Returns:
|
|
27
|
+
Observable of lists of buffered elements.
|
|
28
|
+
"""
|
|
29
|
+
return source.pipe(
|
|
13
30
|
ops.window(boundaries),
|
|
14
31
|
ops.flat_map(ops.to_list()),
|
|
15
32
|
)
|
|
16
33
|
|
|
17
34
|
|
|
35
|
+
@curry_flip
|
|
18
36
|
def buffer_when_(
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
37
|
+
source: Observable[_T],
|
|
38
|
+
closing_mapper: Callable[[], Observable[Any]],
|
|
39
|
+
) -> Observable[list[_T]]:
|
|
40
|
+
"""Buffers elements using a closing mapper function.
|
|
41
|
+
|
|
42
|
+
Examples:
|
|
43
|
+
>>> res = source.pipe(buffer_when(lambda: timer(1.0)))
|
|
44
|
+
>>> res = buffer_when(lambda: timer(1.0))(source)
|
|
45
|
+
|
|
46
|
+
Args:
|
|
47
|
+
source: Source observable to buffer.
|
|
48
|
+
closing_mapper: Function that returns an observable signaling buffer close.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
Observable of lists of buffered elements.
|
|
52
|
+
"""
|
|
53
|
+
return source.pipe(
|
|
22
54
|
ops.window_when(closing_mapper),
|
|
23
55
|
ops.flat_map(ops.to_list()),
|
|
24
56
|
)
|
|
25
57
|
|
|
26
58
|
|
|
59
|
+
@curry_flip
|
|
27
60
|
def buffer_toggle_(
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
61
|
+
source: Observable[_T],
|
|
62
|
+
openings: Observable[Any],
|
|
63
|
+
closing_mapper: Callable[[Any], Observable[Any]],
|
|
64
|
+
) -> Observable[list[_T]]:
|
|
65
|
+
"""Buffers elements using opening/closing observables.
|
|
66
|
+
|
|
67
|
+
Examples:
|
|
68
|
+
>>> res = source.pipe(buffer_toggle(opens, lambda x: timer(x)))
|
|
69
|
+
>>> res = buffer_toggle(opens, lambda x: timer(x))(source)
|
|
70
|
+
|
|
71
|
+
Args:
|
|
72
|
+
source: Source observable to buffer.
|
|
73
|
+
openings: Observable that triggers buffer opening.
|
|
74
|
+
closing_mapper: Function to create closing observable.
|
|
75
|
+
|
|
76
|
+
Returns:
|
|
77
|
+
Observable of lists of buffered elements.
|
|
78
|
+
"""
|
|
79
|
+
return source.pipe(
|
|
31
80
|
ops.window_toggle(openings, closing_mapper),
|
|
32
81
|
ops.flat_map(ops.to_list()),
|
|
33
82
|
)
|
|
34
83
|
|
|
35
84
|
|
|
85
|
+
@curry_flip
|
|
36
86
|
def buffer_with_count_(
|
|
37
|
-
|
|
38
|
-
|
|
87
|
+
source: Observable[_T],
|
|
88
|
+
count: int,
|
|
89
|
+
skip: int | None = None,
|
|
90
|
+
) -> Observable[list[_T]]:
|
|
39
91
|
"""Projects each element of an observable sequence into zero or more
|
|
40
92
|
buffers which are produced based on element count information.
|
|
41
93
|
|
|
42
94
|
Examples:
|
|
43
|
-
>>> res = buffer_with_count(10)
|
|
44
|
-
>>> res = buffer_with_count(10
|
|
95
|
+
>>> res = source.pipe(buffer_with_count(10))
|
|
96
|
+
>>> res = buffer_with_count(10)(source)
|
|
97
|
+
>>> res = source.pipe(buffer_with_count(10, 1))
|
|
45
98
|
|
|
46
99
|
Args:
|
|
100
|
+
source: Source observable to buffer.
|
|
47
101
|
count: Length of each buffer.
|
|
48
102
|
skip: [Optional] Number of elements to skip between
|
|
49
103
|
creation of consecutive buffers. If not provided, defaults to
|
|
50
104
|
the count.
|
|
51
105
|
|
|
52
106
|
Returns:
|
|
53
|
-
|
|
54
|
-
observable sequence of buffers.
|
|
107
|
+
An observable sequence of buffers.
|
|
55
108
|
"""
|
|
109
|
+
skip_ = skip if skip is not None else count
|
|
56
110
|
|
|
57
|
-
def
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
if skip is None:
|
|
61
|
-
skip = count
|
|
62
|
-
|
|
63
|
-
def mapper(value: Observable[_T]) -> Observable[List[_T]]:
|
|
64
|
-
return value.pipe(
|
|
65
|
-
ops.to_list(),
|
|
66
|
-
)
|
|
67
|
-
|
|
68
|
-
def predicate(value: List[_T]) -> bool:
|
|
69
|
-
return len(value) > 0
|
|
70
|
-
|
|
71
|
-
return source.pipe(
|
|
72
|
-
ops.window_with_count(count, skip),
|
|
73
|
-
ops.flat_map(mapper),
|
|
74
|
-
ops.filter(predicate),
|
|
111
|
+
def mapper(value: Observable[_T]) -> Observable[list[_T]]:
|
|
112
|
+
return value.pipe(
|
|
113
|
+
ops.to_list(),
|
|
75
114
|
)
|
|
76
115
|
|
|
77
|
-
|
|
116
|
+
def predicate(value: list[_T]) -> bool:
|
|
117
|
+
return len(value) > 0
|
|
118
|
+
|
|
119
|
+
return source.pipe(
|
|
120
|
+
ops.window_with_count(count, skip_),
|
|
121
|
+
ops.flat_map(mapper),
|
|
122
|
+
ops.filter(predicate),
|
|
123
|
+
)
|
|
78
124
|
|
|
79
125
|
|
|
80
126
|
__all__ = ["buffer_", "buffer_with_count_", "buffer_when_", "buffer_toggle_"]
|
|
@@ -1,23 +1,43 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeVar
|
|
2
2
|
|
|
3
|
-
from reactivex import Observable, abc, compose
|
|
3
|
+
from reactivex import Observable, abc, compose, typing
|
|
4
4
|
from reactivex import operators as ops
|
|
5
|
-
from reactivex import
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
6
6
|
|
|
7
7
|
_T = TypeVar("_T")
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
@curry_flip
|
|
10
11
|
def buffer_with_time_(
|
|
12
|
+
source: Observable[_T],
|
|
11
13
|
timespan: typing.RelativeTime,
|
|
12
|
-
timeshift:
|
|
13
|
-
scheduler:
|
|
14
|
-
) ->
|
|
14
|
+
timeshift: typing.RelativeTime | None = None,
|
|
15
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
16
|
+
) -> Observable[list[_T]]:
|
|
17
|
+
"""Buffers elements based on timing information.
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
>>> source.pipe(buffer_with_time(1.0))
|
|
21
|
+
>>> source.pipe(buffer_with_time(1.0, 0.5))
|
|
22
|
+
>>> buffer_with_time(1.0)(source)
|
|
23
|
+
|
|
24
|
+
Args:
|
|
25
|
+
source: Source observable to buffer.
|
|
26
|
+
timespan: Length of each buffer.
|
|
27
|
+
timeshift: Interval between creation of consecutive buffers.
|
|
28
|
+
scheduler: Scheduler to use for timing.
|
|
29
|
+
|
|
30
|
+
Returns:
|
|
31
|
+
An observable sequence of buffers.
|
|
32
|
+
"""
|
|
15
33
|
if not timeshift:
|
|
16
34
|
timeshift = timespan
|
|
17
35
|
|
|
18
|
-
return
|
|
19
|
-
|
|
20
|
-
|
|
36
|
+
return source.pipe(
|
|
37
|
+
compose(
|
|
38
|
+
ops.window_with_time(timespan, timeshift, scheduler),
|
|
39
|
+
ops.flat_map(ops.to_list()),
|
|
40
|
+
)
|
|
21
41
|
)
|
|
22
42
|
|
|
23
43
|
|
|
@@ -1,20 +1,39 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeVar
|
|
2
2
|
|
|
3
|
-
from reactivex import Observable, abc, compose
|
|
3
|
+
from reactivex import Observable, abc, compose, typing
|
|
4
4
|
from reactivex import operators as ops
|
|
5
|
-
from reactivex import
|
|
5
|
+
from reactivex.internal import curry_flip
|
|
6
6
|
|
|
7
7
|
_T = TypeVar("_T")
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
@curry_flip
|
|
10
11
|
def buffer_with_time_or_count_(
|
|
12
|
+
source: Observable[_T],
|
|
11
13
|
timespan: typing.RelativeTime,
|
|
12
14
|
count: int,
|
|
13
|
-
scheduler:
|
|
14
|
-
) ->
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
15
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
16
|
+
) -> Observable[list[_T]]:
|
|
17
|
+
"""Buffers elements based on timing and count information.
|
|
18
|
+
|
|
19
|
+
Examples:
|
|
20
|
+
>>> source.pipe(buffer_with_time_or_count(1.0, 10))
|
|
21
|
+
>>> buffer_with_time_or_count(1.0, 10)(source)
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
source: Source observable to buffer.
|
|
25
|
+
timespan: Maximum time length of each buffer.
|
|
26
|
+
count: Maximum element count of each buffer.
|
|
27
|
+
scheduler: Scheduler to use for timing.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
An observable sequence of buffers.
|
|
31
|
+
"""
|
|
32
|
+
return source.pipe(
|
|
33
|
+
compose(
|
|
34
|
+
ops.window_with_time_or_count(timespan, count, scheduler),
|
|
35
|
+
ops.flat_map(ops.to_iterable()),
|
|
36
|
+
)
|
|
18
37
|
)
|
|
19
38
|
|
|
20
39
|
|