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/_map.py
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
from typing import
|
|
1
|
+
from typing import TypeVar, cast
|
|
2
2
|
|
|
3
|
-
from reactivex import Observable, abc,
|
|
3
|
+
from reactivex import Observable, abc, 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 identity
|
|
7
7
|
from reactivex.internal.utils import infinite
|
|
8
8
|
from reactivex.typing import Mapper, MapperIndexed
|
|
@@ -11,58 +11,73 @@ _T1 = TypeVar("_T1")
|
|
|
11
11
|
_T2 = TypeVar("_T2")
|
|
12
12
|
|
|
13
13
|
|
|
14
|
+
@curry_flip
|
|
14
15
|
def map_(
|
|
15
|
-
|
|
16
|
-
|
|
16
|
+
source: Observable[_T1],
|
|
17
|
+
mapper: Mapper[_T1, _T2] | None = None,
|
|
18
|
+
) -> Observable[_T2]:
|
|
19
|
+
"""Project each element of an observable sequence into a new form.
|
|
20
|
+
|
|
21
|
+
Example:
|
|
22
|
+
>>> result = source.pipe(map(lambda x: x * 2))
|
|
23
|
+
>>> result = map(lambda x: x * 2)(source)
|
|
24
|
+
|
|
25
|
+
Args:
|
|
26
|
+
source: The observable source to transform.
|
|
27
|
+
mapper: A transform function to apply to each element.
|
|
28
|
+
|
|
29
|
+
Returns:
|
|
30
|
+
Returns an observable sequence whose elements are the
|
|
31
|
+
result of invoking the transform function on each element
|
|
32
|
+
of the source.
|
|
33
|
+
"""
|
|
17
34
|
_mapper = mapper or cast(Mapper[_T1, _T2], identity)
|
|
18
35
|
|
|
19
|
-
def
|
|
20
|
-
|
|
36
|
+
def subscribe(
|
|
37
|
+
obv: abc.ObserverBase[_T2], scheduler: abc.SchedulerBase | None = None
|
|
38
|
+
) -> abc.DisposableBase:
|
|
39
|
+
def on_next(value: _T1) -> None:
|
|
40
|
+
try:
|
|
41
|
+
result = _mapper(value)
|
|
42
|
+
except Exception as err: # pylint: disable=broad-except
|
|
43
|
+
obv.on_error(err)
|
|
44
|
+
else:
|
|
45
|
+
obv.on_next(result)
|
|
21
46
|
|
|
22
|
-
|
|
23
|
-
|
|
47
|
+
return source.subscribe(
|
|
48
|
+
on_next, obv.on_error, obv.on_completed, scheduler=scheduler
|
|
49
|
+
)
|
|
24
50
|
|
|
25
|
-
|
|
26
|
-
>>> map(source)
|
|
51
|
+
return Observable(subscribe)
|
|
27
52
|
|
|
28
|
-
Args:
|
|
29
|
-
source: The observable source to transform.
|
|
30
53
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
obv: abc.ObserverBase[_T2], scheduler: Optional[abc.SchedulerBase] = None
|
|
39
|
-
) -> abc.DisposableBase:
|
|
40
|
-
def on_next(value: _T1) -> None:
|
|
41
|
-
try:
|
|
42
|
-
result = _mapper(value)
|
|
43
|
-
except Exception as err: # pylint: disable=broad-except
|
|
44
|
-
obv.on_error(err)
|
|
45
|
-
else:
|
|
46
|
-
obv.on_next(result)
|
|
47
|
-
|
|
48
|
-
return source.subscribe(
|
|
49
|
-
on_next, obv.on_error, obv.on_completed, scheduler=scheduler
|
|
50
|
-
)
|
|
54
|
+
@curry_flip
|
|
55
|
+
def map_indexed_(
|
|
56
|
+
source: Observable[_T1],
|
|
57
|
+
mapper_indexed: MapperIndexed[_T1, _T2] | None = None,
|
|
58
|
+
) -> Observable[_T2]:
|
|
59
|
+
"""Project each element of an observable sequence into a new form by
|
|
60
|
+
incorporating the element's index.
|
|
51
61
|
|
|
52
|
-
|
|
62
|
+
Example:
|
|
63
|
+
>>> result = source.pipe(map_indexed(lambda x, i: (x, i)))
|
|
64
|
+
>>> result = map_indexed(lambda x, i: (x, i))(source)
|
|
53
65
|
|
|
54
|
-
|
|
66
|
+
Args:
|
|
67
|
+
source: The observable source to transform.
|
|
68
|
+
mapper_indexed: A transform function to apply to each element with its index.
|
|
55
69
|
|
|
70
|
+
Returns:
|
|
71
|
+
An observable sequence whose elements are the result of invoking
|
|
72
|
+
the transform function on each element with its index.
|
|
73
|
+
"""
|
|
56
74
|
|
|
57
|
-
def map_indexed_(
|
|
58
|
-
mapper_indexed: Optional[MapperIndexed[_T1, _T2]] = None,
|
|
59
|
-
) -> Callable[[Observable[_T1]], Observable[_T2]]:
|
|
60
75
|
def _identity(value: _T1, _: int) -> _T2:
|
|
61
76
|
return cast(_T2, value)
|
|
62
77
|
|
|
63
78
|
_mapper_indexed = mapper_indexed or cast(typing.MapperIndexed[_T1, _T2], _identity)
|
|
64
79
|
|
|
65
|
-
return
|
|
80
|
+
return source.pipe(
|
|
66
81
|
ops.zip_with_iterable(infinite()),
|
|
67
82
|
ops.starmap_indexed(_mapper_indexed), # type: ignore
|
|
68
83
|
)
|
|
@@ -1,48 +1,47 @@
|
|
|
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
|
from reactivex.notification import Notification, OnCompleted, OnError, OnNext
|
|
5
6
|
|
|
6
7
|
_T = TypeVar("_T")
|
|
7
8
|
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
10
|
+
@curry_flip
|
|
11
|
+
def materialize_(source: Observable[_T]) -> Observable[Notification[_T]]:
|
|
12
|
+
"""Materializes the implicit notifications of an observable
|
|
13
|
+
sequence as explicit notification values.
|
|
12
14
|
|
|
13
|
-
|
|
14
|
-
|
|
15
|
+
Examples:
|
|
16
|
+
>>> res = source.pipe(materialize())
|
|
17
|
+
>>> res = materialize()(source)
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
19
|
+
Args:
|
|
20
|
+
source: Source observable to materialize.
|
|
18
21
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
22
|
+
Returns:
|
|
23
|
+
An observable sequence containing the materialized
|
|
24
|
+
notification values from the source sequence.
|
|
25
|
+
"""
|
|
23
26
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
27
|
+
def subscribe(
|
|
28
|
+
observer: abc.ObserverBase[Notification[_T]],
|
|
29
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
30
|
+
):
|
|
31
|
+
def on_next(value: _T) -> None:
|
|
32
|
+
observer.on_next(OnNext(value))
|
|
30
33
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
+
def on_error(error: Exception) -> None:
|
|
35
|
+
observer.on_next(OnError(error))
|
|
36
|
+
observer.on_completed()
|
|
34
37
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
+
def on_completed() -> None:
|
|
39
|
+
observer.on_next(OnCompleted())
|
|
40
|
+
observer.on_completed()
|
|
38
41
|
|
|
39
|
-
|
|
40
|
-
on_next, on_error, on_completed, scheduler=scheduler
|
|
41
|
-
)
|
|
42
|
+
return source.subscribe(on_next, on_error, on_completed, scheduler=scheduler)
|
|
42
43
|
|
|
43
|
-
|
|
44
|
+
return Observable(subscribe)
|
|
44
45
|
|
|
45
|
-
return materialize
|
|
46
46
|
|
|
47
|
-
|
|
48
|
-
__all__ = ["materialize"]
|
|
47
|
+
__all__ = ["materialize_"]
|
reactivex/operators/_max.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import TypeVar, cast
|
|
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
|
from reactivex.internal.basic import identity
|
|
6
8
|
from reactivex.typing import Comparer
|
|
7
9
|
|
|
@@ -10,25 +12,30 @@ from ._min import first_only
|
|
|
10
12
|
_T = TypeVar("_T")
|
|
11
13
|
|
|
12
14
|
|
|
15
|
+
@curry_flip
|
|
13
16
|
def max_(
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
+
source: Observable[_T],
|
|
18
|
+
comparer: Comparer[_T] | None = None,
|
|
19
|
+
) -> Observable[_T]:
|
|
20
|
+
"""Returns the maximum value in an observable sequence.
|
|
21
|
+
|
|
22
|
+
Returns the maximum value in an observable sequence according to
|
|
17
23
|
the specified comparer.
|
|
18
24
|
|
|
19
25
|
Examples:
|
|
20
|
-
>>>
|
|
21
|
-
>>>
|
|
26
|
+
>>> result = source.pipe(max())
|
|
27
|
+
>>> result = max()(source)
|
|
28
|
+
>>> result = source.pipe(max(lambda x, y: x.value - y.value))
|
|
22
29
|
|
|
23
30
|
Args:
|
|
24
|
-
|
|
31
|
+
source: The source observable.
|
|
32
|
+
comparer: Optional comparer used to compare elements.
|
|
25
33
|
|
|
26
34
|
Returns:
|
|
27
|
-
An
|
|
28
|
-
an observable sequence containing a single element with the
|
|
35
|
+
An observable sequence containing a single element with the
|
|
29
36
|
maximum element in the source sequence.
|
|
30
37
|
"""
|
|
31
|
-
return
|
|
38
|
+
return source.pipe(
|
|
32
39
|
ops.max_by(cast(Callable[[_T], _T], identity), comparer),
|
|
33
40
|
ops.map(first_only),
|
|
34
41
|
)
|
reactivex/operators/_maxby.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import TypeVar
|
|
2
3
|
|
|
3
4
|
from reactivex import Observable, typing
|
|
4
5
|
from reactivex.internal.basic import default_sub_comparer
|
|
@@ -11,12 +12,11 @@ _TKey = TypeVar("_TKey")
|
|
|
11
12
|
|
|
12
13
|
def max_by_(
|
|
13
14
|
key_mapper: typing.Mapper[_T, _TKey],
|
|
14
|
-
comparer:
|
|
15
|
-
) -> Callable[[Observable[_T]], Observable[
|
|
16
|
-
|
|
15
|
+
comparer: typing.SubComparer[_TKey] | None = None,
|
|
16
|
+
) -> Callable[[Observable[_T]], Observable[list[_T]]]:
|
|
17
17
|
cmp = comparer or default_sub_comparer
|
|
18
18
|
|
|
19
|
-
def max_by(source: Observable[_T]) -> Observable[
|
|
19
|
+
def max_by(source: Observable[_T]) -> Observable[list[_T]]:
|
|
20
20
|
"""Partially applied max_by operator.
|
|
21
21
|
|
|
22
22
|
Returns the elements in an observable sequence with the maximum
|
reactivex/operators/_merge.py
CHANGED
|
@@ -1,153 +1,156 @@
|
|
|
1
1
|
from asyncio import Future
|
|
2
|
-
from typing import
|
|
2
|
+
from typing import TypeVar, Union
|
|
3
3
|
|
|
4
4
|
import reactivex
|
|
5
5
|
from reactivex import Observable, abc, from_future, typing
|
|
6
6
|
from reactivex.disposable import CompositeDisposable, SingleAssignmentDisposable
|
|
7
|
-
from reactivex.internal import synchronized
|
|
7
|
+
from reactivex.internal import curry_flip, synchronized
|
|
8
8
|
|
|
9
9
|
_T = TypeVar("_T")
|
|
10
10
|
|
|
11
11
|
|
|
12
|
+
@curry_flip
|
|
12
13
|
def merge_(
|
|
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
|
-
subscribe(s)
|
|
55
|
-
else:
|
|
56
|
-
active_count[0] -= 1
|
|
57
|
-
if is_stopped[0] and active_count[0] == 0:
|
|
58
|
-
observer.on_completed()
|
|
59
|
-
|
|
60
|
-
on_next = synchronized(source.lock)(observer.on_next)
|
|
61
|
-
on_error = synchronized(source.lock)(observer.on_error)
|
|
62
|
-
subscription.disposable = xs.subscribe(
|
|
63
|
-
on_next, on_error, on_completed, scheduler=scheduler
|
|
64
|
-
)
|
|
65
|
-
|
|
66
|
-
def on_next(inner_source: Observable[_T]) -> None:
|
|
67
|
-
assert max_concurrent
|
|
68
|
-
if active_count[0] < max_concurrent:
|
|
69
|
-
active_count[0] += 1
|
|
70
|
-
subscribe(inner_source)
|
|
71
|
-
else:
|
|
72
|
-
queue.append(inner_source)
|
|
73
|
-
|
|
14
|
+
source: Observable[Observable[_T]],
|
|
15
|
+
*sources: Observable[_T],
|
|
16
|
+
max_concurrent: int | None = None,
|
|
17
|
+
) -> Observable[_T]:
|
|
18
|
+
"""Merges an observable sequence of observable sequences into
|
|
19
|
+
an observable sequence, limiting the number of concurrent
|
|
20
|
+
subscriptions to inner sequences. Or merges two observable
|
|
21
|
+
sequences into a single observable sequence.
|
|
22
|
+
|
|
23
|
+
Examples:
|
|
24
|
+
>>> res = source.pipe(merge(max_concurrent=2))
|
|
25
|
+
>>> res = merge()(source)
|
|
26
|
+
|
|
27
|
+
Args:
|
|
28
|
+
source: Source observable.
|
|
29
|
+
*sources: Additional observables to merge.
|
|
30
|
+
max_concurrent: Maximum number of concurrent subscriptions.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
The observable sequence that merges the elements of the
|
|
34
|
+
inner sequences.
|
|
35
|
+
"""
|
|
36
|
+
|
|
37
|
+
if max_concurrent is None:
|
|
38
|
+
sources_ = tuple([source]) + sources
|
|
39
|
+
return reactivex.merge(*sources_)
|
|
40
|
+
|
|
41
|
+
def subscribe(
|
|
42
|
+
observer: abc.ObserverBase[_T],
|
|
43
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
44
|
+
):
|
|
45
|
+
active_count = [0]
|
|
46
|
+
group = CompositeDisposable()
|
|
47
|
+
is_stopped = [False]
|
|
48
|
+
queue: list[Observable[_T]] = []
|
|
49
|
+
|
|
50
|
+
def subscribe(xs: Observable[_T]):
|
|
51
|
+
subscription = SingleAssignmentDisposable()
|
|
52
|
+
group.add(subscription)
|
|
53
|
+
|
|
54
|
+
@synchronized(source.lock)
|
|
74
55
|
def on_completed():
|
|
75
|
-
|
|
76
|
-
if
|
|
77
|
-
|
|
56
|
+
group.remove(subscription)
|
|
57
|
+
if queue:
|
|
58
|
+
s = queue.pop(0)
|
|
59
|
+
subscribe(s)
|
|
60
|
+
else:
|
|
61
|
+
active_count[0] -= 1
|
|
62
|
+
if is_stopped[0] and active_count[0] == 0:
|
|
63
|
+
observer.on_completed()
|
|
78
64
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
65
|
+
on_next = synchronized(source.lock)(observer.on_next)
|
|
66
|
+
on_error = synchronized(source.lock)(observer.on_error)
|
|
67
|
+
subscription.disposable = xs.subscribe(
|
|
68
|
+
on_next, on_error, on_completed, scheduler=scheduler
|
|
83
69
|
)
|
|
84
|
-
return group
|
|
85
|
-
|
|
86
|
-
return Observable(subscribe)
|
|
87
|
-
|
|
88
|
-
return merge
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def merge_all_() -> Callable[[Observable[Observable[_T]]], Observable[_T]]:
|
|
92
|
-
def merge_all(source: Observable[Observable[_T]]) -> Observable[_T]:
|
|
93
|
-
"""Partially applied merge_all operator.
|
|
94
|
-
|
|
95
|
-
Merges an observable sequence of observable sequences into an
|
|
96
|
-
observable sequence.
|
|
97
|
-
|
|
98
|
-
Args:
|
|
99
|
-
source: Source observable to merge.
|
|
100
70
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
):
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
71
|
+
def on_next(inner_source: Observable[_T]) -> None:
|
|
72
|
+
assert max_concurrent
|
|
73
|
+
if active_count[0] < max_concurrent:
|
|
74
|
+
active_count[0] += 1
|
|
75
|
+
subscribe(inner_source)
|
|
76
|
+
else:
|
|
77
|
+
queue.append(inner_source)
|
|
78
|
+
|
|
79
|
+
def on_completed():
|
|
80
|
+
is_stopped[0] = True
|
|
81
|
+
if active_count[0] == 0:
|
|
82
|
+
observer.on_completed()
|
|
83
|
+
|
|
84
|
+
group.add(
|
|
85
|
+
source.subscribe(
|
|
86
|
+
on_next, observer.on_error, on_completed, scheduler=scheduler
|
|
87
|
+
)
|
|
88
|
+
)
|
|
89
|
+
return group
|
|
90
|
+
|
|
91
|
+
return Observable(subscribe)
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@curry_flip
|
|
95
|
+
def merge_all_(source: Observable[Observable[_T]]) -> Observable[_T]:
|
|
96
|
+
"""Merges an observable sequence of observable sequences into an
|
|
97
|
+
observable sequence.
|
|
98
|
+
|
|
99
|
+
Examples:
|
|
100
|
+
>>> res = source.pipe(merge_all())
|
|
101
|
+
>>> res = merge_all()(source)
|
|
102
|
+
|
|
103
|
+
Args:
|
|
104
|
+
source: Source observable to merge.
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
The observable sequence that merges the elements of the inner
|
|
108
|
+
sequences.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
def subscribe(
|
|
112
|
+
observer: abc.ObserverBase[_T],
|
|
113
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
114
|
+
):
|
|
115
|
+
group = CompositeDisposable()
|
|
116
|
+
is_stopped = [False]
|
|
117
|
+
m = SingleAssignmentDisposable()
|
|
118
|
+
group.add(m)
|
|
119
|
+
|
|
120
|
+
def on_next(inner_source: Union[Observable[_T], "Future[_T]"]):
|
|
121
|
+
inner_subscription = SingleAssignmentDisposable()
|
|
122
|
+
group.add(inner_subscription)
|
|
123
|
+
|
|
124
|
+
inner_source = (
|
|
125
|
+
from_future(inner_source)
|
|
126
|
+
if isinstance(inner_source, Future)
|
|
127
|
+
else inner_source
|
|
128
|
+
)
|
|
137
129
|
|
|
130
|
+
@synchronized(source.lock)
|
|
138
131
|
def on_completed():
|
|
139
|
-
|
|
140
|
-
if len(group) == 1:
|
|
132
|
+
group.remove(inner_subscription)
|
|
133
|
+
if is_stopped[0] and len(group) == 1:
|
|
141
134
|
observer.on_completed()
|
|
142
135
|
|
|
143
|
-
|
|
144
|
-
|
|
136
|
+
on_next: typing.OnNext[_T] = synchronized(source.lock)(observer.on_next)
|
|
137
|
+
on_error = synchronized(source.lock)(observer.on_error)
|
|
138
|
+
subscription = inner_source.subscribe(
|
|
139
|
+
on_next, on_error, on_completed, scheduler=scheduler
|
|
145
140
|
)
|
|
146
|
-
|
|
141
|
+
inner_subscription.disposable = subscription
|
|
142
|
+
|
|
143
|
+
def on_completed():
|
|
144
|
+
is_stopped[0] = True
|
|
145
|
+
if len(group) == 1:
|
|
146
|
+
observer.on_completed()
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
m.disposable = source.subscribe(
|
|
149
|
+
on_next, observer.on_error, on_completed, scheduler=scheduler
|
|
150
|
+
)
|
|
151
|
+
return group
|
|
149
152
|
|
|
150
|
-
return
|
|
153
|
+
return Observable(subscribe)
|
|
151
154
|
|
|
152
155
|
|
|
153
156
|
__all__ = ["merge_", "merge_all_"]
|
reactivex/operators/_min.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import TypeVar, cast
|
|
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
|
from reactivex.internal.basic import identity
|
|
6
8
|
from reactivex.internal.exceptions import SequenceContainsNoElementsError
|
|
7
9
|
from reactivex.typing import Comparer
|
|
@@ -9,33 +11,37 @@ from reactivex.typing import Comparer
|
|
|
9
11
|
_T = TypeVar("_T")
|
|
10
12
|
|
|
11
13
|
|
|
12
|
-
def first_only(x:
|
|
14
|
+
def first_only(x: list[_T]) -> _T:
|
|
13
15
|
if not x:
|
|
14
16
|
raise SequenceContainsNoElementsError()
|
|
15
17
|
|
|
16
18
|
return x[0]
|
|
17
19
|
|
|
18
20
|
|
|
21
|
+
@curry_flip
|
|
19
22
|
def min_(
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
+
source: Observable[_T],
|
|
24
|
+
comparer: Comparer[_T] | None = None,
|
|
25
|
+
) -> Observable[_T]:
|
|
26
|
+
"""Returns the minimum element in an observable sequence.
|
|
23
27
|
|
|
24
28
|
Returns the minimum element in an observable sequence according to
|
|
25
29
|
the optional comparer else a default greater than less than check.
|
|
26
30
|
|
|
27
31
|
Examples:
|
|
28
|
-
>>>
|
|
29
|
-
>>>
|
|
32
|
+
>>> result = source.pipe(min())
|
|
33
|
+
>>> result = min()(source)
|
|
34
|
+
>>> result = source.pipe(min(lambda x, y: x.value - y.value))
|
|
30
35
|
|
|
31
36
|
Args:
|
|
32
|
-
|
|
37
|
+
source: The source observable.
|
|
38
|
+
comparer: Optional comparer used to compare elements.
|
|
33
39
|
|
|
34
40
|
Returns:
|
|
35
41
|
An observable sequence containing a single element
|
|
36
42
|
with the minimum element in the source sequence.
|
|
37
43
|
"""
|
|
38
|
-
return
|
|
44
|
+
return source.pipe(
|
|
39
45
|
ops.min_by(cast(Callable[[_T], _T], identity), comparer),
|
|
40
46
|
ops.map(first_only),
|
|
41
47
|
)
|
reactivex/operators/_minby.py
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from
|
|
1
|
+
from collections.abc import Callable
|
|
2
|
+
from typing import TypeVar, cast
|
|
2
3
|
|
|
3
4
|
from reactivex import Observable, abc, typing
|
|
4
5
|
from reactivex.internal.basic import default_sub_comparer
|
|
@@ -11,14 +12,14 @@ def extrema_by(
|
|
|
11
12
|
source: Observable[_T],
|
|
12
13
|
key_mapper: typing.Mapper[_T, _TKey],
|
|
13
14
|
comparer: typing.SubComparer[_TKey],
|
|
14
|
-
) -> Observable[
|
|
15
|
+
) -> Observable[list[_T]]:
|
|
15
16
|
def subscribe(
|
|
16
|
-
observer: abc.ObserverBase[
|
|
17
|
-
scheduler:
|
|
17
|
+
observer: abc.ObserverBase[list[_T]],
|
|
18
|
+
scheduler: abc.SchedulerBase | None = None,
|
|
18
19
|
) -> abc.DisposableBase:
|
|
19
20
|
has_value = False
|
|
20
21
|
last_key: _TKey = cast(_TKey, None)
|
|
21
|
-
items:
|
|
22
|
+
items: list[_T] = []
|
|
22
23
|
|
|
23
24
|
def on_next(x: _T) -> None:
|
|
24
25
|
nonlocal has_value, last_key
|
|
@@ -60,8 +61,8 @@ def extrema_by(
|
|
|
60
61
|
|
|
61
62
|
def min_by_(
|
|
62
63
|
key_mapper: typing.Mapper[_T, _TKey],
|
|
63
|
-
comparer:
|
|
64
|
-
) -> Callable[[Observable[_T]], Observable[
|
|
64
|
+
comparer: typing.SubComparer[_TKey] | None = None,
|
|
65
|
+
) -> Callable[[Observable[_T]], Observable[list[_T]]]:
|
|
65
66
|
"""The `min_by` operator.
|
|
66
67
|
|
|
67
68
|
Returns the elements in an observable sequence with the minimum key
|
|
@@ -82,7 +83,7 @@ def min_by_(
|
|
|
82
83
|
|
|
83
84
|
cmp = comparer or default_sub_comparer
|
|
84
85
|
|
|
85
|
-
def min_by(source: Observable[_T]) -> Observable[
|
|
86
|
+
def min_by(source: Observable[_T]) -> Observable[list[_T]]:
|
|
86
87
|
return extrema_by(source, key_mapper, lambda x, y: -cmp(x, y))
|
|
87
88
|
|
|
88
89
|
return min_by
|