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,9 @@
1
1
  from asyncio import Future
2
- from typing import Any, Callable, Optional, TypeVar, Union, cast
2
+ from typing import Any, TypeVar, Union, cast
3
3
 
4
4
  from reactivex import Observable, from_, from_future
5
5
  from reactivex import operators as ops
6
+ from reactivex.internal import curry_flip
6
7
  from reactivex.internal.basic import identity
7
8
  from reactivex.typing import Mapper, MapperIndexed
8
9
 
@@ -12,19 +13,21 @@ _T2 = TypeVar("_T2")
12
13
 
13
14
  def _flat_map_internal(
14
15
  source: Observable[_T1],
15
- mapper: Optional[Mapper[_T1, Any]] = None,
16
- mapper_indexed: Optional[MapperIndexed[_T1, Any]] = None,
16
+ mapper: Mapper[_T1, Any] | None = None,
17
+ mapper_indexed: MapperIndexed[_T1, Any] | None = None,
17
18
  ) -> Observable[Any]:
18
19
  def projection(x: _T1, i: int) -> Observable[Any]:
19
20
  mapper_result: Any = (
20
21
  mapper(x)
21
22
  if mapper
22
- else mapper_indexed(x, i) if mapper_indexed else identity
23
+ else mapper_indexed(x, i)
24
+ if mapper_indexed
25
+ else identity
23
26
  )
24
27
  if isinstance(mapper_result, Future):
25
28
  result: Observable[Any] = from_future(cast("Future[Any]", mapper_result))
26
29
  elif isinstance(mapper_result, Observable):
27
- result = mapper_result
30
+ result = cast(Observable[Any], mapper_result)
28
31
  else:
29
32
  result = from_(mapper_result)
30
33
  return result
@@ -35,95 +38,98 @@ def _flat_map_internal(
35
38
  )
36
39
 
37
40
 
41
+ @curry_flip
38
42
  def flat_map_(
39
- mapper: Optional[Mapper[_T1, Observable[_T2]]] = None
40
- ) -> Callable[[Observable[_T1]], Observable[_T2]]:
41
- def flat_map(source: Observable[_T1]) -> Observable[_T2]:
42
- """One of the Following:
43
- Projects each element of an observable sequence to an observable
44
- sequence and merges the resulting observable sequences into one
45
- observable sequence.
46
-
47
- Example:
48
- >>> flat_map(source)
49
-
50
- Args:
51
- source: Source observable to flat map.
52
-
53
- Returns:
54
- An operator function that takes a source observable and returns
55
- an observable sequence whose elements are the result of invoking
56
- the one-to-many transform function on each element of the
57
- input sequence .
58
- """
59
-
60
- if callable(mapper):
61
- ret = _flat_map_internal(source, mapper=mapper)
62
- else:
63
- ret = _flat_map_internal(source, mapper=lambda _: mapper)
43
+ source: Observable[_T1],
44
+ mapper: Mapper[_T1, Observable[_T2]] | None = None,
45
+ ) -> Observable[_T2]:
46
+ """Projects each element of an observable sequence to an observable
47
+ sequence and merges the resulting observable sequences into one
48
+ observable sequence.
49
+
50
+ Examples:
51
+ >>> source.pipe(flat_map(lambda x: of(x * 2)))
52
+ >>> flat_map(lambda x: of(x * 2))(source)
53
+
54
+ Args:
55
+ source: Source observable to flat map.
56
+ mapper: Transform function to apply to each element.
64
57
 
65
- return ret
58
+ Returns:
59
+ An observable sequence whose elements are the result of invoking
60
+ the one-to-many transform function on each element of the
61
+ input sequence.
62
+ """
66
63
 
67
- return flat_map
64
+ if callable(mapper):
65
+ ret = _flat_map_internal(source, mapper=mapper)
66
+ else:
67
+ ret = _flat_map_internal(source, mapper=lambda _: mapper)
68
68
 
69
+ return ret
69
70
 
71
+
72
+ @curry_flip
70
73
  def flat_map_indexed_(
71
- mapper_indexed: Optional[Any] = None,
72
- ) -> Callable[[Observable[Any]], Observable[Any]]:
73
- def flat_map_indexed(source: Observable[Any]) -> Observable[Any]:
74
- """One of the Following:
75
- Projects each element of an observable sequence to an observable
76
- sequence and merges the resulting observable sequences into one
77
- observable sequence.
78
-
79
- Example:
80
- >>> flat_map_indexed(source)
81
-
82
- Args:
83
- source: Source observable to flat map.
84
-
85
- Returns:
86
- An observable sequence whose elements are the result of invoking
87
- the one-to-many transform function on each element of the input
88
- sequence.
89
- """
90
-
91
- if callable(mapper_indexed):
92
- ret = _flat_map_internal(source, mapper_indexed=mapper_indexed)
93
- else:
94
- ret = _flat_map_internal(source, mapper=lambda _: mapper_indexed)
95
- return ret
74
+ source: Observable[Any],
75
+ mapper_indexed: Any | None = None,
76
+ ) -> Observable[Any]:
77
+ """Projects each element of an observable sequence to an observable
78
+ sequence and merges the resulting observable sequences into one
79
+ observable sequence.
96
80
 
97
- return flat_map_indexed
81
+ Examples:
82
+ >>> source.pipe(flat_map_indexed(lambda x, i: of(x * i)))
83
+ >>> flat_map_indexed(lambda x, i: of(x * i))(source)
98
84
 
85
+ Args:
86
+ source: Source observable to flat map.
87
+ mapper_indexed: Transform function with index to apply to each element.
99
88
 
89
+ Returns:
90
+ An observable sequence whose elements are the result of invoking
91
+ the one-to-many transform function on each element of the input
92
+ sequence.
93
+ """
94
+
95
+ if callable(mapper_indexed):
96
+ ret = _flat_map_internal(source, mapper_indexed=mapper_indexed)
97
+ else:
98
+ ret = _flat_map_internal(source, mapper=lambda _: mapper_indexed)
99
+ return ret
100
+
101
+
102
+ @curry_flip
100
103
  def flat_map_latest_(
101
- mapper: Mapper[_T1, Union[Observable[_T2], "Future[_T2]"]]
102
- ) -> Callable[[Observable[_T1]], Observable[_T2]]:
103
- def flat_map_latest(source: Observable[_T1]) -> Observable[_T2]:
104
- """Projects each element of an observable sequence into a new
105
- sequence of observable sequences by incorporating the element's
106
- index and then transforms an observable sequence of observable
107
- sequences into an observable sequence producing values only
108
- from the most recent observable sequence.
109
-
110
- Args:
111
- source: Source observable to flat map latest.
112
-
113
- Returns:
114
- An observable sequence whose elements are the result of
115
- invoking the transform function on each element of source
116
- producing an observable of Observable sequences and that at
117
- any point in time produces the elements of the most recent
118
- inner observable sequence that has been received.
119
- """
120
-
121
- return source.pipe(
122
- ops.map(mapper),
123
- ops.switch_latest(),
124
- )
104
+ source: Observable[_T1],
105
+ mapper: Mapper[_T1, Union[Observable[_T2], "Future[_T2]"]],
106
+ ) -> Observable[_T2]:
107
+ """Projects each element of an observable sequence into a new
108
+ sequence of observable sequences by incorporating the element's
109
+ index and then transforms an observable sequence of observable
110
+ sequences into an observable sequence producing values only
111
+ from the most recent observable sequence.
112
+
113
+ Examples:
114
+ >>> source.pipe(flat_map_latest(lambda x: of(x * 2)))
115
+ >>> flat_map_latest(lambda x: of(x * 2))(source)
116
+
117
+ Args:
118
+ source: Source observable to flat map latest.
119
+ mapper: Transform function to apply to each element.
120
+
121
+ Returns:
122
+ An observable sequence whose elements are the result of
123
+ invoking the transform function on each element of source
124
+ producing an observable of Observable sequences and that at
125
+ any point in time produces the elements of the most recent
126
+ inner observable sequence that has been received.
127
+ """
125
128
 
126
- return flat_map_latest
129
+ return source.pipe(
130
+ ops.map(mapper),
131
+ ops.switch_latest(),
132
+ )
127
133
 
128
134
 
129
135
  __all__ = ["flat_map_", "flat_map_latest_", "flat_map_indexed_"]
@@ -1,28 +1,33 @@
1
- from typing import Any, Callable, Tuple
1
+ from typing import Any, cast
2
2
 
3
3
  import reactivex
4
4
  from reactivex import Observable
5
+ from reactivex.internal import curry_flip
5
6
 
6
7
 
8
+ @curry_flip
7
9
  def fork_join_(
10
+ source: Observable[Any],
8
11
  *args: Observable[Any],
9
- ) -> Callable[[Observable[Any]], Observable[Tuple[Any, ...]]]:
10
- def fork_join(source: Observable[Any]) -> Observable[Tuple[Any, ...]]:
11
- """Wait for observables to complete and then combine last values
12
- they emitted into a tuple. Whenever any of that observables
13
- completes without emitting any value, result sequence will
14
- complete at that moment as well.
15
-
16
- Examples:
17
- >>> obs = fork_join(source)
18
-
19
- Returns:
20
- An observable sequence containing the result of combining
21
- last element from each source in given sequence.
22
- """
23
- return reactivex.fork_join(source, *args)
24
-
25
- return fork_join
12
+ ) -> Observable[tuple[Any, ...]]:
13
+ """Wait for observables to complete and then combine last values
14
+ they emitted into a tuple. Whenever any of that observables
15
+ completes without emitting any value, result sequence will
16
+ complete at that moment as well.
17
+
18
+ Examples:
19
+ >>> source.pipe(fork_join(obs1, obs2))
20
+ >>> fork_join(obs1, obs2)(source)
21
+
22
+ Args:
23
+ source: Source observable.
24
+ *args: Additional observables to fork_join with.
25
+
26
+ Returns:
27
+ An observable sequence containing the result of combining
28
+ last element from each source in given sequence.
29
+ """
30
+ return cast(Observable[tuple[Any, ...]], reactivex.fork_join(source, *args))
26
31
 
27
32
 
28
33
  __all__ = ["fork_join_"]
@@ -1,6 +1,8 @@
1
- from typing import Any, Callable, Optional, TypeVar
1
+ from collections.abc import Callable
2
+ from typing import Any, TypeVar
2
3
 
3
4
  from reactivex import GroupedObservable, Observable, typing
5
+ from reactivex.internal import curry_flip
4
6
  from reactivex.subject import Subject
5
7
 
6
8
  _T = TypeVar("_T")
@@ -10,11 +12,30 @@ _TValue = TypeVar("_TValue")
10
12
  # pylint: disable=import-outside-toplevel
11
13
 
12
14
 
15
+ @curry_flip
13
16
  def group_by_(
17
+ source: Observable[_T],
14
18
  key_mapper: typing.Mapper[_T, _TKey],
15
- element_mapper: Optional[typing.Mapper[_T, _TValue]] = None,
16
- subject_mapper: Optional[Callable[[], Subject[_TValue]]] = None,
17
- ) -> Callable[[Observable[_T]], Observable[GroupedObservable[_TKey, _TValue]]]:
19
+ element_mapper: typing.Mapper[_T, _TValue] | None = None,
20
+ subject_mapper: Callable[[], Subject[_TValue]] | None = None,
21
+ ) -> Observable[GroupedObservable[_TKey, _TValue]]:
22
+ """Groups the elements of an observable sequence according to a
23
+ specified key mapper function.
24
+
25
+ Examples:
26
+ >>> res = source.pipe(group_by(lambda x: x.id))
27
+ >>> res = group_by(lambda x: x.id)(source)
28
+
29
+ Args:
30
+ source: Source observable to group.
31
+ key_mapper: A function to extract the key for each element.
32
+ element_mapper: Optional function to map elements to values.
33
+ subject_mapper: Optional function that returns a subject used to initiate
34
+ a grouped observable.
35
+
36
+ Returns:
37
+ An observable sequence of grouped observables.
38
+ """
18
39
  from reactivex import operators as ops
19
40
 
20
41
  def duration_mapper(_: GroupedObservable[Any, Any]) -> Observable[Any]:
@@ -22,8 +43,8 @@ def group_by_(
22
43
 
23
44
  return reactivex.never()
24
45
 
25
- return ops.group_by_until(
26
- key_mapper, element_mapper, duration_mapper, subject_mapper
46
+ return source.pipe(
47
+ ops.group_by_until(key_mapper, element_mapper, duration_mapper, subject_mapper)
27
48
  )
28
49
 
29
50
 
@@ -1,5 +1,6 @@
1
1
  from collections import OrderedDict
2
- from typing import Any, Callable, Optional, TypeVar, cast
2
+ from collections.abc import Callable
3
+ from typing import Any, TypeVar, cast
3
4
 
4
5
  from reactivex import GroupedObservable, Observable, abc
5
6
  from reactivex import operators as ops
@@ -19,9 +20,9 @@ _TValue = TypeVar("_TValue")
19
20
 
20
21
  def group_by_until_(
21
22
  key_mapper: Mapper[_T, _TKey],
22
- element_mapper: Optional[Mapper[_T, _TValue]],
23
+ element_mapper: Mapper[_T, _TValue] | None,
23
24
  duration_mapper: Callable[[GroupedObservable[_TKey, _TValue]], Observable[Any]],
24
- subject_mapper: Optional[Callable[[], Subject[_TValue]]] = None,
25
+ subject_mapper: Callable[[], Subject[_TValue]] | None = None,
25
26
  ) -> Callable[[Observable[_T]], Observable[GroupedObservable[_TKey, _TValue]]]:
26
27
  """Groups the elements of an observable sequence according to a
27
28
  specified key mapper function. A duration mapper function is used
@@ -57,7 +58,9 @@ def group_by_until_(
57
58
 
58
59
  element_mapper_ = element_mapper or cast(Mapper[_T, _TValue], identity)
59
60
 
60
- default_subject_mapper: Callable[[], Subject[_TValue]] = lambda: Subject()
61
+ def default_subject_mapper() -> Subject[_TValue]:
62
+ return Subject()
63
+
61
64
  subject_mapper_ = subject_mapper or default_subject_mapper
62
65
 
63
66
  def group_by_until(
@@ -65,7 +68,7 @@ def group_by_until_(
65
68
  ) -> Observable[GroupedObservable[_TKey, _TValue]]:
66
69
  def subscribe(
67
70
  observer: abc.ObserverBase[GroupedObservable[_TKey, _TValue]],
68
- scheduler: Optional[abc.SchedulerBase] = None,
71
+ scheduler: abc.SchedulerBase | None = None,
69
72
  ) -> abc.DisposableBase:
70
73
  writers: OrderedDict[_TKey, Subject[_TValue]] = OrderedDict()
71
74
  group_disposable = CompositeDisposable()
@@ -1,6 +1,7 @@
1
1
  import logging
2
2
  from collections import OrderedDict
3
- from typing import Any, Callable, Optional, Tuple, TypeVar
3
+ from collections.abc import Callable
4
+ from typing import Any, TypeVar
4
5
 
5
6
  from reactivex import Observable, abc
6
7
  from reactivex import operators as ops
@@ -22,7 +23,7 @@ def group_join_(
22
23
  right: Observable[_TRight],
23
24
  left_duration_mapper: Callable[[_TLeft], Observable[Any]],
24
25
  right_duration_mapper: Callable[[_TRight], Observable[Any]],
25
- ) -> Callable[[Observable[_TLeft]], Observable[Tuple[_TLeft, Observable[_TRight]]]]:
26
+ ) -> Callable[[Observable[_TLeft]], Observable[tuple[_TLeft, Observable[_TRight]]]]:
26
27
  """Correlates the elements of two sequences based on overlapping
27
28
  durations, and groups the results.
28
29
 
@@ -45,10 +46,10 @@ def group_join_(
45
46
 
46
47
  def group_join(
47
48
  left: Observable[_TLeft],
48
- ) -> Observable[Tuple[_TLeft, Observable[_TRight]]]:
49
+ ) -> Observable[tuple[_TLeft, Observable[_TRight]]]:
49
50
  def subscribe(
50
- observer: abc.ObserverBase[Tuple[_TLeft, Observable[_TRight]]],
51
- scheduler: Optional[abc.SchedulerBase] = None,
51
+ observer: abc.ObserverBase[tuple[_TLeft, Observable[_TRight]]],
52
+ scheduler: abc.SchedulerBase | None = None,
52
53
  ) -> abc.DisposableBase:
53
54
  group = CompositeDisposable()
54
55
  rcd = RefCountDisposable(group)
@@ -68,7 +69,7 @@ def group_join_(
68
69
  try:
69
70
  result = (value, add_ref(subject, rcd))
70
71
  except Exception as e:
71
- log.error("*** Exception: %s" % e)
72
+ log.error(f"*** Exception: {e}")
72
73
  for left_value in left_map.values():
73
74
  left_value.on_error(e)
74
75
 
@@ -1,32 +1,37 @@
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 noop
4
+ from reactivex.internal import curry_flip, noop
5
5
 
6
6
  _T = TypeVar("_T")
7
7
 
8
8
 
9
- def ignore_elements_() -> Callable[[Observable[_T]], Observable[_T]]:
9
+ @curry_flip
10
+ def ignore_elements_(source: Observable[_T]) -> Observable[_T]:
10
11
  """Ignores all elements in an observable sequence leaving only the
11
12
  termination messages.
12
13
 
14
+ Examples:
15
+ >>> res = source.pipe(ignore_elements())
16
+ >>> res = ignore_elements()(source)
17
+
18
+ Args:
19
+ source: The source observable sequence.
20
+
13
21
  Returns:
14
- An empty observable {Observable} sequence that signals
22
+ An empty observable sequence that signals
15
23
  termination, successful or exceptional, of the source sequence.
16
24
  """
17
25
 
18
- def ignore_elements(source: Observable[_T]) -> Observable[_T]:
19
- def subscribe(
20
- observer: abc.ObserverBase[_T],
21
- scheduler: Optional[abc.SchedulerBase] = None,
22
- ) -> abc.DisposableBase:
23
- return source.subscribe(
24
- noop, observer.on_error, observer.on_completed, scheduler=scheduler
25
- )
26
-
27
- return Observable(subscribe)
26
+ def subscribe(
27
+ observer: abc.ObserverBase[_T],
28
+ scheduler: abc.SchedulerBase | None = None,
29
+ ) -> abc.DisposableBase:
30
+ return source.subscribe(
31
+ noop, observer.on_error, observer.on_completed, scheduler=scheduler
32
+ )
28
33
 
29
- return ignore_elements
34
+ return Observable(subscribe)
30
35
 
31
36
 
32
37
  __all__ = ["ignore_elements_"]
@@ -1,12 +1,23 @@
1
- from typing import Any, Callable
1
+ from typing import TypeVar
2
2
 
3
- from reactivex import Observable, compose
3
+ from reactivex import Observable
4
4
  from reactivex import operators as ops
5
+ from reactivex.internal import curry_flip
5
6
 
7
+ _T = TypeVar("_T")
6
8
 
7
- def is_empty_() -> Callable[[Observable[Any]], Observable[bool]]:
9
+
10
+ @curry_flip
11
+ def is_empty_(source: Observable[_T]) -> Observable[bool]:
8
12
  """Determines whether an observable sequence is empty.
9
13
 
14
+ Examples:
15
+ >>> res = source.pipe(is_empty())
16
+ >>> res = is_empty()(source)
17
+
18
+ Args:
19
+ source: The source observable sequence.
20
+
10
21
  Returns:
11
22
  An observable sequence containing a single element
12
23
  determining whether the source sequence is empty.
@@ -15,7 +26,7 @@ def is_empty_() -> Callable[[Observable[Any]], Observable[bool]]:
15
26
  def mapper(b: bool) -> bool:
16
27
  return not b
17
28
 
18
- return compose(
29
+ return source.pipe(
19
30
  ops.some(),
20
31
  ops.map(mapper),
21
32
  )
@@ -1,5 +1,6 @@
1
1
  from collections import OrderedDict
2
- from typing import Any, Callable, Optional, Tuple, TypeVar
2
+ from collections.abc import Callable
3
+ from typing import Any, TypeVar
3
4
 
4
5
  from reactivex import Observable, abc
5
6
  from reactivex.disposable import CompositeDisposable, SingleAssignmentDisposable
@@ -14,8 +15,8 @@ def join_(
14
15
  right: Observable[_T2],
15
16
  left_duration_mapper: Callable[[Any], Observable[Any]],
16
17
  right_duration_mapper: Callable[[Any], Observable[Any]],
17
- ) -> Callable[[Observable[_T1]], Observable[Tuple[_T1, _T2]]]:
18
- def join(source: Observable[_T1]) -> Observable[Tuple[_T1, _T2]]:
18
+ ) -> Callable[[Observable[_T1]], Observable[tuple[_T1, _T2]]]:
19
+ def join(source: Observable[_T1]) -> Observable[tuple[_T1, _T2]]:
19
20
  """Correlates the elements of two sequences based on
20
21
  overlapping durations.
21
22
 
@@ -31,8 +32,8 @@ def join_(
31
32
  left = source
32
33
 
33
34
  def subscribe(
34
- observer: abc.ObserverBase[Tuple[_T1, _T2]],
35
- scheduler: Optional[abc.SchedulerBase] = None,
35
+ observer: abc.ObserverBase[tuple[_T1, _T2]],
36
+ scheduler: abc.SchedulerBase | None = None,
36
37
  ) -> abc.DisposableBase:
37
38
  group = CompositeDisposable()
38
39
  left_done = False
@@ -1,6 +1,7 @@
1
- from typing import Any, Callable, Optional, TypeVar
1
+ from typing import TypeVar
2
2
 
3
3
  from reactivex import Observable, operators
4
+ from reactivex.internal import curry_flip
4
5
  from reactivex.typing import Predicate
5
6
 
6
7
  from ._lastordefault import last_or_default_async
@@ -8,37 +9,41 @@ from ._lastordefault import last_or_default_async
8
9
  _T = TypeVar("_T")
9
10
 
10
11
 
12
+ @curry_flip
11
13
  def last_(
12
- predicate: Optional[Predicate[_T]] = None,
13
- ) -> Callable[[Observable[_T]], Observable[Any]]:
14
- def last(source: Observable[_T]) -> Observable[Any]:
15
- """Partially applied last operator.
16
-
17
- Returns the last element of an observable sequence that
18
- satisfies the condition in the predicate if specified, else
19
- the last element.
20
-
21
- Examples:
22
- >>> res = last(source)
23
-
24
- Args:
25
- source: Source observable to get last item from.
26
-
27
- Returns:
28
- An observable sequence containing the last element in the
29
- observable sequence that satisfies the condition in the
30
- predicate.
31
- """
32
-
33
- if predicate:
34
- return source.pipe(
35
- operators.filter(predicate),
36
- operators.last(),
37
- )
38
-
39
- return last_or_default_async(source, False)
40
-
41
- return last
14
+ source: Observable[_T],
15
+ predicate: Predicate[_T] | None = None,
16
+ ) -> Observable[_T]:
17
+ """Returns the last element of an observable sequence that
18
+ satisfies the condition in the predicate if specified, else
19
+ the last element.
20
+
21
+ Examples:
22
+ >>> res = source.pipe(last())
23
+ >>> res = last()(source)
24
+ >>> res = source.pipe(last(lambda x: x > 3))
25
+
26
+ Args:
27
+ source: Source observable to get last item from.
28
+ predicate: [Optional] A predicate function to evaluate for
29
+ elements in the source sequence.
30
+
31
+ Returns:
32
+ An observable sequence containing the last element in the
33
+ observable sequence that satisfies the condition in the
34
+ predicate.
35
+ """
36
+ from typing import cast
37
+
38
+ if predicate:
39
+ return source.pipe(
40
+ operators.filter(predicate),
41
+ operators.last(),
42
+ )
43
+
44
+ # last_or_default_async returns Observable[_T | None], but when
45
+ # has_default=False it never emits None. Safe cast to Observable[_T].
46
+ return cast(Observable[_T], last_or_default_async(source, False))
42
47
 
43
48
 
44
49
  __all__ = ["last_"]
@@ -1,8 +1,8 @@
1
- from typing import Any, Callable, Optional, TypeVar
1
+ from collections.abc import Callable
2
+ from typing import Any, TypeVar
2
3
 
3
- from reactivex import Observable, abc
4
+ from reactivex import Observable, abc, typing
4
5
  from reactivex import operators as ops
5
- from reactivex import typing
6
6
  from reactivex.internal.exceptions import SequenceContainsNoElementsError
7
7
 
8
8
  _T = TypeVar("_T")
@@ -11,11 +11,11 @@ _T = TypeVar("_T")
11
11
  def last_or_default_async(
12
12
  source: Observable[_T],
13
13
  has_default: bool = False,
14
- default_value: Optional[_T] = None,
15
- ) -> Observable[Optional[_T]]:
14
+ default_value: _T | None = None,
15
+ ) -> Observable[_T | None]:
16
16
  def subscribe(
17
- observer: abc.ObserverBase[Optional[_T]],
18
- scheduler: Optional[abc.SchedulerBase] = None,
17
+ observer: abc.ObserverBase[_T | None],
18
+ scheduler: abc.SchedulerBase | None = None,
19
19
  ):
20
20
  value = [default_value]
21
21
  seen_value = [False]
@@ -39,7 +39,7 @@ def last_or_default_async(
39
39
 
40
40
 
41
41
  def last_or_default(
42
- default_value: Optional[_T] = None, predicate: Optional[typing.Predicate[_T]] = None
42
+ default_value: _T | None = None, predicate: typing.Predicate[_T] | None = None
43
43
  ) -> Callable[[Observable[_T]], Observable[Any]]:
44
44
  def last_or_default(source: Observable[Any]) -> Observable[Any]:
45
45
  """Return last or default element.