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.
Files changed (219) hide show
  1. reactivex/__init__.py +35 -39
  2. reactivex/_version.py +1 -1
  3. reactivex/abc/disposable.py +3 -4
  4. reactivex/abc/observable.py +13 -6
  5. reactivex/abc/observer.py +2 -1
  6. reactivex/abc/periodicscheduler.py +7 -6
  7. reactivex/abc/scheduler.py +10 -9
  8. reactivex/abc/subject.py +5 -5
  9. reactivex/disposable/compositedisposable.py +4 -4
  10. reactivex/disposable/disposable.py +1 -2
  11. reactivex/disposable/multipleassignmentdisposable.py +2 -3
  12. reactivex/disposable/refcountdisposable.py +1 -2
  13. reactivex/disposable/serialdisposable.py +4 -5
  14. reactivex/disposable/singleassignmentdisposable.py +3 -4
  15. reactivex/internal/__init__.py +2 -0
  16. reactivex/internal/basic.py +2 -2
  17. reactivex/internal/concurrency.py +2 -1
  18. reactivex/internal/curry.py +59 -0
  19. reactivex/internal/exceptions.py +7 -12
  20. reactivex/internal/priorityqueue.py +2 -2
  21. reactivex/internal/utils.py +3 -2
  22. reactivex/notification.py +22 -21
  23. reactivex/observable/case.py +5 -6
  24. reactivex/observable/catch.py +3 -2
  25. reactivex/observable/combinelatest.py +4 -5
  26. reactivex/observable/concat.py +3 -2
  27. reactivex/observable/connectableobservable.py +7 -7
  28. reactivex/observable/defer.py +4 -3
  29. reactivex/observable/empty.py +3 -4
  30. reactivex/observable/forkjoin.py +5 -5
  31. reactivex/observable/fromcallback.py +4 -3
  32. reactivex/observable/fromfuture.py +2 -2
  33. reactivex/observable/fromiterable.py +4 -3
  34. reactivex/observable/generate.py +2 -2
  35. reactivex/observable/generatewithrelativetime.py +4 -3
  36. reactivex/observable/groupedobservable.py +4 -4
  37. reactivex/observable/ifthen.py +3 -2
  38. reactivex/observable/interval.py +1 -4
  39. reactivex/observable/marbles.py +18 -17
  40. reactivex/observable/mixins/__init__.py +32 -0
  41. reactivex/observable/mixins/combination.py +481 -0
  42. reactivex/observable/mixins/conditional.py +135 -0
  43. reactivex/observable/mixins/error_handling.py +130 -0
  44. reactivex/observable/mixins/filtering.py +1119 -0
  45. reactivex/observable/mixins/mathematical.py +277 -0
  46. reactivex/observable/mixins/multicasting.py +306 -0
  47. reactivex/observable/mixins/testing.py +193 -0
  48. reactivex/observable/mixins/time_based.py +209 -0
  49. reactivex/observable/mixins/transformation.py +632 -0
  50. reactivex/observable/mixins/utility.py +811 -0
  51. reactivex/observable/mixins/windowing.py +688 -0
  52. reactivex/observable/never.py +2 -2
  53. reactivex/observable/observable.py +72 -25
  54. reactivex/observable/onerrorresumenext.py +7 -6
  55. reactivex/observable/range.py +6 -6
  56. reactivex/observable/repeat.py +2 -2
  57. reactivex/observable/returnvalue.py +6 -5
  58. reactivex/observable/start.py +3 -2
  59. reactivex/observable/startasync.py +2 -1
  60. reactivex/observable/throw.py +3 -3
  61. reactivex/observable/timer.py +12 -12
  62. reactivex/observable/toasync.py +3 -2
  63. reactivex/observable/using.py +5 -4
  64. reactivex/observable/withlatestfrom.py +4 -5
  65. reactivex/observable/zip.py +7 -6
  66. reactivex/observer/autodetachobserver.py +4 -4
  67. reactivex/observer/observer.py +5 -4
  68. reactivex/observer/scheduledobserver.py +2 -2
  69. reactivex/operators/__init__.py +162 -208
  70. reactivex/operators/_all.py +23 -6
  71. reactivex/operators/_amb.py +88 -75
  72. reactivex/operators/_asobservable.py +20 -17
  73. reactivex/operators/_average.py +48 -45
  74. reactivex/operators/_buffer.py +81 -35
  75. reactivex/operators/_bufferwithtime.py +29 -9
  76. reactivex/operators/_bufferwithtimeorcount.py +27 -8
  77. reactivex/operators/_catch.py +33 -32
  78. reactivex/operators/_combinelatest.py +28 -20
  79. reactivex/operators/_concat.py +16 -13
  80. reactivex/operators/_contains.py +25 -6
  81. reactivex/operators/_count.py +24 -8
  82. reactivex/operators/_debounce.py +141 -138
  83. reactivex/operators/_defaultifempty.py +45 -42
  84. reactivex/operators/_delay.py +24 -23
  85. reactivex/operators/_delaysubscription.py +23 -21
  86. reactivex/operators/_delaywithmapper.py +10 -11
  87. reactivex/operators/_dematerialize.py +25 -21
  88. reactivex/operators/_distinct.py +50 -46
  89. reactivex/operators/_distinctuntilchanged.py +60 -57
  90. reactivex/operators/_do.py +123 -116
  91. reactivex/operators/_dowhile.py +3 -2
  92. reactivex/operators/_elementatordefault.py +57 -33
  93. reactivex/operators/_exclusive.py +59 -53
  94. reactivex/operators/_expand.py +82 -77
  95. reactivex/operators/_filter.py +63 -68
  96. reactivex/operators/_finallyaction.py +3 -2
  97. reactivex/operators/_find.py +49 -32
  98. reactivex/operators/_first.py +18 -11
  99. reactivex/operators/_firstordefault.py +5 -4
  100. reactivex/operators/_flatmap.py +89 -83
  101. reactivex/operators/_forkjoin.py +23 -18
  102. reactivex/operators/_groupby.py +27 -6
  103. reactivex/operators/_groupbyuntil.py +8 -5
  104. reactivex/operators/_groupjoin.py +7 -6
  105. reactivex/operators/_ignoreelements.py +20 -15
  106. reactivex/operators/_isempty.py +15 -4
  107. reactivex/operators/_join.py +6 -5
  108. reactivex/operators/_last.py +36 -31
  109. reactivex/operators/_lastordefault.py +8 -8
  110. reactivex/operators/_map.py +54 -39
  111. reactivex/operators/_materialize.py +30 -31
  112. reactivex/operators/_max.py +18 -11
  113. reactivex/operators/_maxby.py +5 -5
  114. reactivex/operators/_merge.py +132 -129
  115. reactivex/operators/_min.py +16 -10
  116. reactivex/operators/_minby.py +9 -8
  117. reactivex/operators/_multicast.py +9 -9
  118. reactivex/operators/_observeon.py +35 -31
  119. reactivex/operators/_onerrorresumenext.py +2 -1
  120. reactivex/operators/_pairwise.py +38 -34
  121. reactivex/operators/_partition.py +80 -73
  122. reactivex/operators/_pluck.py +4 -3
  123. reactivex/operators/_publish.py +36 -21
  124. reactivex/operators/_publishvalue.py +8 -7
  125. reactivex/operators/_reduce.py +16 -12
  126. reactivex/operators/_repeat.py +33 -30
  127. reactivex/operators/_replay.py +9 -9
  128. reactivex/operators/_retry.py +12 -10
  129. reactivex/operators/_sample.py +31 -27
  130. reactivex/operators/_scan.py +41 -39
  131. reactivex/operators/_sequenceequal.py +8 -7
  132. reactivex/operators/_single.py +20 -13
  133. reactivex/operators/_singleordefault.py +6 -5
  134. reactivex/operators/_skip.py +35 -32
  135. reactivex/operators/_skiplast.py +38 -34
  136. reactivex/operators/_skiplastwithtime.py +5 -4
  137. reactivex/operators/_skipuntil.py +40 -35
  138. reactivex/operators/_skipuntilwithtime.py +4 -3
  139. reactivex/operators/_skipwhile.py +65 -44
  140. reactivex/operators/_skipwithtime.py +50 -46
  141. reactivex/operators/_slice.py +58 -53
  142. reactivex/operators/_some.py +48 -47
  143. reactivex/operators/_startswith.py +17 -15
  144. reactivex/operators/_subscribeon.py +44 -41
  145. reactivex/operators/_sum.py +23 -6
  146. reactivex/operators/_switchlatest.py +71 -69
  147. reactivex/operators/_take.py +37 -33
  148. reactivex/operators/_takelast.py +37 -36
  149. reactivex/operators/_takelastbuffer.py +38 -37
  150. reactivex/operators/_takelastwithtime.py +60 -56
  151. reactivex/operators/_takeuntil.py +33 -32
  152. reactivex/operators/_takeuntilwithtime.py +42 -39
  153. reactivex/operators/_takewhile.py +108 -100
  154. reactivex/operators/_takewithtime.py +46 -41
  155. reactivex/operators/_throttlefirst.py +52 -45
  156. reactivex/operators/_timeinterval.py +40 -36
  157. reactivex/operators/_timeout.py +81 -79
  158. reactivex/operators/_timeoutwithmapper.py +6 -5
  159. reactivex/operators/_timestamp.py +24 -22
  160. reactivex/operators/_todict.py +51 -43
  161. reactivex/operators/_tofuture.py +24 -15
  162. reactivex/operators/_toiterable.py +33 -27
  163. reactivex/operators/_tomarbles.py +5 -5
  164. reactivex/operators/_toset.py +29 -19
  165. reactivex/operators/_whiledo.py +2 -1
  166. reactivex/operators/_window.py +100 -99
  167. reactivex/operators/_windowwithcount.py +56 -54
  168. reactivex/operators/_windowwithtime.py +95 -79
  169. reactivex/operators/_windowwithtimeorcount.py +85 -69
  170. reactivex/operators/_withlatestfrom.py +13 -9
  171. reactivex/operators/_zip.py +67 -63
  172. reactivex/operators/connectable/_refcount.py +4 -3
  173. reactivex/pipe.py +2 -1
  174. reactivex/run.py +8 -4
  175. reactivex/scheduler/catchscheduler.py +11 -10
  176. reactivex/scheduler/currentthreadscheduler.py +2 -3
  177. reactivex/scheduler/eventloop/asyncioscheduler.py +7 -6
  178. reactivex/scheduler/eventloop/asynciothreadsafescheduler.py +12 -14
  179. reactivex/scheduler/eventloop/eventletscheduler.py +4 -4
  180. reactivex/scheduler/eventloop/geventscheduler.py +4 -4
  181. reactivex/scheduler/eventloop/ioloopscheduler.py +4 -4
  182. reactivex/scheduler/eventloop/twistedscheduler.py +4 -4
  183. reactivex/scheduler/eventloopscheduler.py +9 -12
  184. reactivex/scheduler/historicalscheduler.py +1 -2
  185. reactivex/scheduler/immediatescheduler.py +5 -4
  186. reactivex/scheduler/mainloop/gtkscheduler.py +6 -7
  187. reactivex/scheduler/mainloop/pygamescheduler.py +4 -4
  188. reactivex/scheduler/mainloop/qtscheduler.py +6 -6
  189. reactivex/scheduler/mainloop/tkinterscheduler.py +4 -4
  190. reactivex/scheduler/mainloop/wxscheduler.py +7 -7
  191. reactivex/scheduler/newthreadscheduler.py +6 -8
  192. reactivex/scheduler/periodicscheduler.py +4 -4
  193. reactivex/scheduler/scheduleditem.py +4 -4
  194. reactivex/scheduler/scheduler.py +5 -5
  195. reactivex/scheduler/threadpoolscheduler.py +3 -3
  196. reactivex/scheduler/timeoutscheduler.py +5 -4
  197. reactivex/scheduler/trampoline.py +1 -2
  198. reactivex/scheduler/trampolinescheduler.py +5 -6
  199. reactivex/scheduler/virtualtimescheduler.py +4 -4
  200. reactivex/subject/asyncsubject.py +2 -2
  201. reactivex/subject/behaviorsubject.py +2 -2
  202. reactivex/subject/innersubscription.py +2 -2
  203. reactivex/subject/replaysubject.py +8 -8
  204. reactivex/subject/subject.py +4 -4
  205. reactivex/testing/coldobservable.py +5 -5
  206. reactivex/testing/hotobservable.py +6 -6
  207. reactivex/testing/marbles.py +21 -20
  208. reactivex/testing/mockdisposable.py +1 -3
  209. reactivex/testing/mockobserver.py +2 -2
  210. reactivex/testing/reactivetest.py +2 -2
  211. reactivex/testing/recorded.py +1 -1
  212. reactivex/testing/subscription.py +3 -3
  213. reactivex/testing/testscheduler.py +13 -12
  214. reactivex/typing.py +25 -14
  215. {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/METADATA +59 -26
  216. reactivex-5.0.0a2.dist-info/RECORD +236 -0
  217. {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/WHEEL +1 -1
  218. reactivex-4.1.0.dist-info/RECORD +0 -223
  219. {reactivex-4.1.0.dist-info → reactivex-5.0.0a2.dist-info}/licenses/LICENSE +0 -0
@@ -1,8 +1,8 @@
1
- from typing import Callable, Optional, TypeVar, cast
1
+ from typing import TypeVar, cast
2
2
 
3
- from reactivex import Observable, abc, compose
3
+ from reactivex import Observable, abc, typing
4
4
  from reactivex import operators as ops
5
- from reactivex import typing
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
- mapper: Optional[Mapper[_T1, _T2]] = None,
16
- ) -> Callable[[Observable[_T1]], Observable[_T2]]:
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 map(source: Observable[_T1]) -> Observable[_T2]:
20
- """Partially applied map operator.
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
- Project each element of an observable sequence into a new form
23
- by incorporating the element's index.
47
+ return source.subscribe(
48
+ on_next, obv.on_error, obv.on_completed, scheduler=scheduler
49
+ )
24
50
 
25
- Example:
26
- >>> map(source)
51
+ return Observable(subscribe)
27
52
 
28
- Args:
29
- source: The observable source to transform.
30
53
 
31
- Returns:
32
- Returns an observable sequence whose elements are the
33
- result of invoking the transform function on each element
34
- of the source.
35
- """
36
-
37
- def subscribe(
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
- return Observable(subscribe)
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
- return map
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 compose(
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 Callable, Optional, TypeVar
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
- def materialize() -> Callable[[Observable[_T]], Observable[Notification[_T]]]:
10
- def materialize(source: Observable[_T]) -> Observable[Notification[_T]]:
11
- """Partially applied materialize operator.
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
- Materializes the implicit notifications of an observable
14
- sequence as explicit notification values.
15
+ Examples:
16
+ >>> res = source.pipe(materialize())
17
+ >>> res = materialize()(source)
15
18
 
16
- Args:
17
- source: Source observable to materialize.
19
+ Args:
20
+ source: Source observable to materialize.
18
21
 
19
- Returns:
20
- An observable sequence containing the materialized
21
- notification values from the source sequence.
22
- """
22
+ Returns:
23
+ An observable sequence containing the materialized
24
+ notification values from the source sequence.
25
+ """
23
26
 
24
- def subscribe(
25
- observer: abc.ObserverBase[Notification[_T]],
26
- scheduler: Optional[abc.SchedulerBase] = None,
27
- ):
28
- def on_next(value: _T) -> None:
29
- observer.on_next(OnNext(value))
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
- def on_error(error: Exception) -> None:
32
- observer.on_next(OnError(error))
33
- observer.on_completed()
34
+ def on_error(error: Exception) -> None:
35
+ observer.on_next(OnError(error))
36
+ observer.on_completed()
34
37
 
35
- def on_completed() -> None:
36
- observer.on_next(OnCompleted())
37
- observer.on_completed()
38
+ def on_completed() -> None:
39
+ observer.on_next(OnCompleted())
40
+ observer.on_completed()
38
41
 
39
- return source.subscribe(
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
- return Observable(subscribe)
44
+ return Observable(subscribe)
44
45
 
45
- return materialize
46
46
 
47
-
48
- __all__ = ["materialize"]
47
+ __all__ = ["materialize_"]
@@ -1,7 +1,9 @@
1
- from typing import Callable, Optional, TypeVar, cast
1
+ from collections.abc import Callable
2
+ from typing import TypeVar, cast
2
3
 
3
- from reactivex import Observable, compose
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
- comparer: Optional[Comparer[_T]] = None,
15
- ) -> Callable[[Observable[_T]], Observable[_T]]:
16
- """Returns the maximum value in an observable sequence according to
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
- >>> op = max()
21
- >>> op = max(lambda x, y: x.value - y.value)
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
- comparer: [Optional] Comparer used to compare elements.
31
+ source: The source observable.
32
+ comparer: Optional comparer used to compare elements.
25
33
 
26
34
  Returns:
27
- An operator function that takes an observable source and returns
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 compose(
38
+ return source.pipe(
32
39
  ops.max_by(cast(Callable[[_T], _T], identity), comparer),
33
40
  ops.map(first_only),
34
41
  )
@@ -1,4 +1,5 @@
1
- from typing import Callable, List, Optional, TypeVar
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: Optional[typing.SubComparer[_TKey]] = None,
15
- ) -> Callable[[Observable[_T]], Observable[List[_T]]]:
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[List[_T]]:
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
@@ -1,153 +1,156 @@
1
1
  from asyncio import Future
2
- from typing import Callable, List, Optional, TypeVar, Union
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
- *sources: Observable[_T], max_concurrent: Optional[int] = None
14
- ) -> Callable[[Observable[Observable[_T]]], Observable[_T]]:
15
- def merge(source: Observable[Observable[_T]]) -> Observable[_T]:
16
- """Merges an observable sequence of observable sequences into
17
- an observable sequence, limiting the number of concurrent
18
- subscriptions to inner sequences. Or merges two observable
19
- sequences into a single observable sequence.
20
-
21
- Examples:
22
- >>> res = merge(sources)
23
-
24
- Args:
25
- source: Source observable.
26
-
27
- Returns:
28
- The observable sequence that merges the elements of the
29
- inner sequences.
30
- """
31
-
32
- if max_concurrent is None:
33
- sources_ = tuple([source]) + sources
34
- return reactivex.merge(*sources_)
35
-
36
- def subscribe(
37
- observer: abc.ObserverBase[_T],
38
- scheduler: Optional[abc.SchedulerBase] = None,
39
- ):
40
- active_count = [0]
41
- group = CompositeDisposable()
42
- is_stopped = [False]
43
- queue: List[Observable[_T]] = []
44
-
45
- def subscribe(xs: Observable[_T]):
46
- subscription = SingleAssignmentDisposable()
47
- group.add(subscription)
48
-
49
- @synchronized(source.lock)
50
- def on_completed():
51
- group.remove(subscription)
52
- if queue:
53
- s = queue.pop(0)
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
- is_stopped[0] = True
76
- if active_count[0] == 0:
77
- observer.on_completed()
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
- group.add(
80
- source.subscribe(
81
- on_next, observer.on_error, on_completed, scheduler=scheduler
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
- Returns:
102
- The observable sequence that merges the elements of the inner
103
- sequences.
104
- """
105
-
106
- def subscribe(
107
- observer: abc.ObserverBase[_T],
108
- scheduler: Optional[abc.SchedulerBase] = None,
109
- ):
110
- group = CompositeDisposable()
111
- is_stopped = [False]
112
- m = SingleAssignmentDisposable()
113
- group.add(m)
114
-
115
- def on_next(inner_source: Union[Observable[_T], "Future[_T]"]):
116
- inner_subscription = SingleAssignmentDisposable()
117
- group.add(inner_subscription)
118
-
119
- inner_source = (
120
- from_future(inner_source)
121
- if isinstance(inner_source, Future)
122
- else inner_source
123
- )
124
-
125
- @synchronized(source.lock)
126
- def on_completed():
127
- group.remove(inner_subscription)
128
- if is_stopped[0] and len(group) == 1:
129
- observer.on_completed()
130
-
131
- on_next: typing.OnNext[_T] = synchronized(source.lock)(observer.on_next)
132
- on_error = synchronized(source.lock)(observer.on_error)
133
- subscription = inner_source.subscribe(
134
- on_next, on_error, on_completed, scheduler=scheduler
135
- )
136
- inner_subscription.disposable = subscription
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
- is_stopped[0] = True
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
- m.disposable = source.subscribe(
144
- on_next, observer.on_error, on_completed, scheduler=scheduler
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
- return group
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
- return Observable(subscribe)
148
+ m.disposable = source.subscribe(
149
+ on_next, observer.on_error, on_completed, scheduler=scheduler
150
+ )
151
+ return group
149
152
 
150
- return merge_all
153
+ return Observable(subscribe)
151
154
 
152
155
 
153
156
  __all__ = ["merge_", "merge_all_"]
@@ -1,7 +1,9 @@
1
- from typing import Callable, List, Optional, TypeVar, cast
1
+ from collections.abc import Callable
2
+ from typing import TypeVar, cast
2
3
 
3
- from reactivex import Observable, compose
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: List[_T]) -> _T:
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
- comparer: Optional[Comparer[_T]] = None,
21
- ) -> Callable[[Observable[_T]], Observable[_T]]:
22
- """The `min` operator.
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
- >>> res = source.min()
29
- >>> res = source.min(lambda x, y: x.value - y.value)
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
- comparer: [Optional] Comparer used to compare elements.
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 compose(
44
+ return source.pipe(
39
45
  ops.min_by(cast(Callable[[_T], _T], identity), comparer),
40
46
  ops.map(first_only),
41
47
  )
@@ -1,4 +1,5 @@
1
- from typing import Callable, List, Optional, TypeVar, cast
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[List[_T]]:
15
+ ) -> Observable[list[_T]]:
15
16
  def subscribe(
16
- observer: abc.ObserverBase[List[_T]],
17
- scheduler: Optional[abc.SchedulerBase] = None,
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: List[_T] = []
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: Optional[typing.SubComparer[_TKey]] = None,
64
- ) -> Callable[[Observable[_T]], Observable[List[_T]]]:
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[List[_T]]:
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