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,52 +1,55 @@
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
 
5
6
  _T = TypeVar("_T")
6
7
 
7
8
 
9
+ @curry_flip
8
10
  def default_if_empty_(
9
- default_value: Optional[_T] = None,
10
- ) -> Callable[[Observable[_T]], Observable[Optional[_T]]]:
11
- def default_if_empty(source: Observable[_T]) -> Observable[Optional[_T]]:
12
- """Returns the elements of the specified sequence or the
13
- specified value in a singleton sequence if the sequence is
14
- empty.
15
-
16
- Examples:
17
- >>> obs = default_if_empty(source)
18
-
19
- Args:
20
- source: Source observable.
21
-
22
- Returns:
23
- An observable sequence that contains the specified default
24
- value if the source is empty otherwise, the elements of the
25
- source.
26
- """
27
-
28
- def subscribe(
29
- observer: abc.ObserverBase[Optional[_T]],
30
- scheduler: Optional[abc.SchedulerBase] = None,
31
- ) -> abc.DisposableBase:
32
- found = [False]
33
-
34
- def on_next(x: _T):
35
- found[0] = True
36
- observer.on_next(x)
37
-
38
- def on_completed():
39
- if not found[0]:
40
- observer.on_next(default_value)
41
- observer.on_completed()
42
-
43
- return source.subscribe(
44
- on_next, observer.on_error, on_completed, scheduler=scheduler
45
- )
46
-
47
- return Observable(subscribe)
48
-
49
- return default_if_empty
11
+ source: Observable[_T],
12
+ default_value: _T | None = None,
13
+ ) -> Observable[_T | None]:
14
+ """Returns the elements of the specified sequence or the
15
+ specified value in a singleton sequence if the sequence is
16
+ empty.
17
+
18
+ Examples:
19
+ >>> obs = source.pipe(default_if_empty())
20
+ >>> obs = default_if_empty()(source)
21
+ >>> obs = source.pipe(default_if_empty(42))
22
+
23
+ Args:
24
+ source: Source observable.
25
+ default_value: The value to return if the sequence is empty.
26
+
27
+ Returns:
28
+ An observable sequence that contains the specified default
29
+ value if the source is empty otherwise, the elements of the
30
+ source.
31
+ """
32
+
33
+ def subscribe(
34
+ observer: abc.ObserverBase[_T | None],
35
+ scheduler: abc.SchedulerBase | None = None,
36
+ ) -> abc.DisposableBase:
37
+ found = [False]
38
+
39
+ def on_next(x: _T):
40
+ found[0] = True
41
+ observer.on_next(x)
42
+
43
+ def on_completed():
44
+ if not found[0]:
45
+ observer.on_next(default_value)
46
+ observer.on_completed()
47
+
48
+ return source.subscribe(
49
+ on_next, observer.on_error, on_completed, scheduler=scheduler
50
+ )
51
+
52
+ return Observable(subscribe)
50
53
 
51
54
 
52
55
  __all__ = ["default_if_empty_"]
@@ -1,14 +1,14 @@
1
1
  from datetime import datetime
2
- from typing import Any, Callable, List, Optional, TypeVar
2
+ from typing import Any, TypeVar
3
3
 
4
- from reactivex import Notification, Observable, abc
4
+ from reactivex import Notification, Observable, abc, typing
5
5
  from reactivex import operators as ops
6
- from reactivex import typing
7
6
  from reactivex.disposable import (
8
7
  CompositeDisposable,
9
8
  MultipleAssignmentDisposable,
10
9
  SerialDisposable,
11
10
  )
11
+ from reactivex.internal import curry_flip
12
12
  from reactivex.internal.constants import DELTA_ZERO
13
13
  from reactivex.notification import OnError
14
14
  from reactivex.scheduler import TimeoutScheduler
@@ -21,10 +21,10 @@ _T = TypeVar("_T")
21
21
  def observable_delay_timespan(
22
22
  source: Observable[_T],
23
23
  duetime: typing.RelativeTime,
24
- scheduler: Optional[abc.SchedulerBase] = None,
24
+ scheduler: abc.SchedulerBase | None = None,
25
25
  ) -> Observable[_T]:
26
26
  def subscribe(
27
- observer: abc.ObserverBase[_T], scheduler_: Optional[abc.SchedulerBase] = None
27
+ observer: abc.ObserverBase[_T], scheduler_: abc.SchedulerBase | None = None
28
28
  ):
29
29
  nonlocal duetime
30
30
 
@@ -36,10 +36,10 @@ def observable_delay_timespan(
36
36
  duetime_ = _scheduler.to_timedelta(duetime)
37
37
 
38
38
  cancelable = SerialDisposable()
39
- exception: Optional[Exception] = None
39
+ exception: Exception | None = None
40
40
  active = [False]
41
41
  running = [False]
42
- queue: List[Timestamp[Notification[_T]]] = []
42
+ queue: list[Timestamp[Notification[_T]]] = []
43
43
 
44
44
  def on_next(notification: Timestamp[Notification[_T]]) -> None:
45
45
  nonlocal exception
@@ -116,26 +116,27 @@ def observable_delay_timespan(
116
116
  return Observable(subscribe)
117
117
 
118
118
 
119
+ @curry_flip
119
120
  def delay_(
120
- duetime: typing.RelativeTime, scheduler: Optional[abc.SchedulerBase] = None
121
- ) -> Callable[[Observable[_T]], Observable[_T]]:
122
- def delay(source: Observable[_T]) -> Observable[_T]:
123
- """Time shifts the observable sequence.
124
-
125
- A partially applied delay operator function.
126
-
127
- Examples:
128
- >>> res = delay(source)
121
+ source: Observable[_T],
122
+ duetime: typing.RelativeTime,
123
+ scheduler: abc.SchedulerBase | None = None,
124
+ ) -> Observable[_T]:
125
+ """Time shifts the observable sequence.
129
126
 
130
- Args:
131
- source: The observable sequence to delay.
127
+ Examples:
128
+ >>> res = source.pipe(delay(5.0))
129
+ >>> res = delay(5.0)(source)
132
130
 
133
- Returns:
134
- A time-shifted observable sequence.
135
- """
136
- return observable_delay_timespan(source, duetime, scheduler)
131
+ Args:
132
+ source: The observable sequence to delay.
133
+ duetime: Time to shift the sequence by.
134
+ scheduler: Scheduler to use for time operations.
137
135
 
138
- return delay
136
+ Returns:
137
+ A time-shifted observable sequence.
138
+ """
139
+ return observable_delay_timespan(source, duetime, scheduler)
139
140
 
140
141
 
141
142
  __all__ = ["delay_"]
@@ -1,38 +1,40 @@
1
- from typing import Any, Callable, Optional, TypeVar
1
+ from typing import Any, TypeVar
2
2
 
3
3
  import reactivex
4
- from reactivex import Observable, abc
4
+ from reactivex import Observable, abc, typing
5
5
  from reactivex import operators as ops
6
- from reactivex import typing
6
+ from reactivex.internal import curry_flip
7
7
 
8
8
  _T = TypeVar("_T")
9
9
 
10
10
 
11
+ @curry_flip
11
12
  def delay_subscription_(
13
+ source: Observable[_T],
12
14
  duetime: typing.AbsoluteOrRelativeTime,
13
- scheduler: Optional[abc.SchedulerBase] = None,
14
- ) -> Callable[[Observable[_T]], Observable[_T]]:
15
- def delay_subscription(source: Observable[_T]) -> Observable[_T]:
16
- """Time shifts the observable sequence by delaying the subscription.
15
+ scheduler: abc.SchedulerBase | None = None,
16
+ ) -> Observable[_T]:
17
+ """Time shifts the observable sequence by delaying the subscription.
17
18
 
18
- Exampeles.
19
- >>> res = source.delay_subscription(5)
19
+ Examples:
20
+ >>> source.pipe(delay_subscription(5))
21
+ >>> delay_subscription(5)(source)
20
22
 
21
- Args:
22
- source: Source subscription to delay.
23
+ Args:
24
+ source: Source subscription to delay.
25
+ duetime: Time to delay subscription.
26
+ scheduler: Scheduler to use for timing.
23
27
 
24
- Returns:
25
- Time-shifted sequence.
26
- """
28
+ Returns:
29
+ Time-shifted sequence.
30
+ """
27
31
 
28
- def mapper(_: Any) -> Observable[_T]:
29
- return reactivex.empty()
32
+ def mapper(_: Any) -> Observable[_T]:
33
+ return reactivex.empty()
30
34
 
31
- return source.pipe(
32
- ops.delay_with_mapper(reactivex.timer(duetime, scheduler=scheduler), mapper)
33
- )
34
-
35
- return delay_subscription
35
+ return source.pipe(
36
+ ops.delay_with_mapper(reactivex.timer(duetime, scheduler=scheduler), mapper)
37
+ )
36
38
 
37
39
 
38
40
  __all__ = ["delay_subscription_"]
@@ -1,4 +1,5 @@
1
- from typing import Any, Callable, Optional, TypeVar, Union
1
+ from collections.abc import Callable
2
+ from typing import Any, TypeVar, cast
2
3
 
3
4
  from reactivex import Observable, abc, typing
4
5
  from reactivex.disposable import (
@@ -11,12 +12,10 @@ _T = TypeVar("_T")
11
12
 
12
13
 
13
14
  def delay_with_mapper_(
14
- subscription_delay: Union[
15
- Observable[Any],
16
- typing.Mapper[Any, Observable[Any]],
17
- None,
18
- ] = None,
19
- delay_duration_mapper: Optional[typing.Mapper[_T, Observable[Any]]] = None,
15
+ subscription_delay: Observable[Any]
16
+ | typing.Mapper[Any, Observable[Any]]
17
+ | None = None,
18
+ delay_duration_mapper: typing.Mapper[_T, Observable[Any]] | None = None,
20
19
  ) -> Callable[[Observable[_T]], Observable[_T]]:
21
20
  def delay_with_mapper(source: Observable[_T]) -> Observable[_T]:
22
21
  """Time shifts the observable sequence based on a subscription
@@ -35,18 +34,18 @@ def delay_with_mapper_(
35
34
  Returns:
36
35
  Time-shifted observable sequence.
37
36
  """
38
- sub_delay: Optional[Observable[Any]] = None
39
- mapper: Optional[typing.Mapper[Any, Observable[Any]]] = None
37
+ sub_delay: Observable[Any] | None = None
38
+ mapper: typing.Mapper[Any, Observable[Any]] | None = None
40
39
 
41
40
  if isinstance(subscription_delay, abc.ObservableBase):
42
41
  mapper = delay_duration_mapper
43
- sub_delay = subscription_delay
42
+ sub_delay = cast(Observable[Any], subscription_delay)
44
43
  else:
45
44
  mapper = subscription_delay
46
45
 
47
46
  def subscribe(
48
47
  observer: abc.ObserverBase[_T],
49
- scheduler: Optional[abc.SchedulerBase] = None,
48
+ scheduler: abc.SchedulerBase | None = None,
50
49
  ) -> abc.DisposableBase:
51
50
  delays = CompositeDisposable()
52
51
  at_end = [False]
@@ -1,36 +1,40 @@
1
- from typing import Callable, Optional, TypeVar
1
+ from typing import TypeVar
2
2
 
3
3
  from reactivex import Notification, Observable, abc
4
+ from reactivex.internal import curry_flip
4
5
 
5
6
  _T = TypeVar("_T")
6
7
 
7
8
 
8
- def dematerialize_() -> Callable[[Observable[Notification[_T]]], Observable[_T]]:
9
- def dematerialize(source: Observable[Notification[_T]]) -> Observable[_T]:
10
- """Partially applied dematerialize operator.
9
+ @curry_flip
10
+ def dematerialize_(source: Observable[Notification[_T]]) -> Observable[_T]:
11
+ """Dematerializes the explicit notification values of an
12
+ observable sequence as implicit notifications.
11
13
 
12
- Dematerializes the explicit notification values of an
13
- observable sequence as implicit notifications.
14
+ Examples:
15
+ >>> res = source.pipe(dematerialize())
16
+ >>> res = dematerialize()(source)
14
17
 
15
- Returns:
16
- An observable sequence exhibiting the behavior
17
- corresponding to the source sequence's notification values.
18
- """
18
+ Args:
19
+ source: Source observable with notifications to dematerialize.
19
20
 
20
- def subscribe(
21
- observer: abc.ObserverBase[_T],
22
- scheduler: Optional[abc.SchedulerBase] = None,
23
- ):
24
- def on_next(value: Notification[_T]) -> None:
25
- return value.accept(observer)
21
+ Returns:
22
+ An observable sequence exhibiting the behavior
23
+ corresponding to the source sequence's notification values.
24
+ """
26
25
 
27
- return source.subscribe(
28
- on_next, observer.on_error, observer.on_completed, scheduler=scheduler
29
- )
26
+ def subscribe(
27
+ observer: abc.ObserverBase[_T],
28
+ scheduler: abc.SchedulerBase | None = None,
29
+ ):
30
+ def on_next(value: Notification[_T]) -> None:
31
+ return value.accept(observer)
30
32
 
31
- return Observable(subscribe)
33
+ return source.subscribe(
34
+ on_next, observer.on_error, observer.on_completed, scheduler=scheduler
35
+ )
32
36
 
33
- return dematerialize
37
+ return Observable(subscribe)
34
38
 
35
39
 
36
40
  __all__ = ["dematerialize_"]
@@ -1,6 +1,7 @@
1
- from typing import Callable, Generic, List, Optional, TypeVar, cast
1
+ from typing import Generic, TypeVar, cast
2
2
 
3
3
  from reactivex import Observable, abc, typing
4
+ from reactivex.internal import curry_flip
4
5
  from reactivex.internal.basic import default_comparer
5
6
 
6
7
  _T = TypeVar("_T")
@@ -8,7 +9,7 @@ _TKey = TypeVar("_TKey")
8
9
 
9
10
 
10
11
  def array_index_of_comparer(
11
- array: List[_TKey], item: _TKey, comparer: typing.Comparer[_TKey]
12
+ array: list[_TKey], item: _TKey, comparer: typing.Comparer[_TKey]
12
13
  ):
13
14
  for i, a in enumerate(array):
14
15
  if comparer(a, item):
@@ -19,7 +20,7 @@ def array_index_of_comparer(
19
20
  class HashSet(Generic[_TKey]):
20
21
  def __init__(self, comparer: typing.Comparer[_TKey]):
21
22
  self.comparer = comparer
22
- self.set: List[_TKey] = []
23
+ self.set: list[_TKey] = []
23
24
 
24
25
  def push(self, value: _TKey):
25
26
  ret_value = array_index_of_comparer(self.set, value, self.comparer) == -1
@@ -28,57 +29,60 @@ class HashSet(Generic[_TKey]):
28
29
  return ret_value
29
30
 
30
31
 
32
+ @curry_flip
31
33
  def distinct_(
32
- key_mapper: Optional[typing.Mapper[_T, _TKey]] = None,
33
- comparer: Optional[typing.Comparer[_TKey]] = None,
34
- ) -> Callable[[Observable[_T]], Observable[_T]]:
34
+ source: Observable[_T],
35
+ key_mapper: typing.Mapper[_T, _TKey] | None = None,
36
+ comparer: typing.Comparer[_TKey] | None = None,
37
+ ) -> Observable[_T]:
38
+ """Returns an observable sequence that contains only distinct elements.
39
+
40
+ Returns an observable sequence that contains only distinct
41
+ elements according to the key_mapper and the comparer. Usage of
42
+ this operator should be considered carefully due to the
43
+ maintenance of an internal lookup structure which can grow large.
44
+
45
+ Examples:
46
+ >>> result = source.pipe(distinct())
47
+ >>> result = distinct()(source)
48
+ >>> result = source.pipe(distinct(lambda x: x.id))
49
+
50
+ Args:
51
+ source: Source observable to return distinct items from.
52
+ key_mapper: Optional function to compute a comparison key.
53
+ comparer: Optional equality comparer for computed keys.
54
+
55
+ Returns:
56
+ An observable sequence only containing the distinct
57
+ elements, based on a computed key value, from the source
58
+ sequence.
59
+ """
35
60
  comparer_ = comparer or cast(typing.Comparer[_TKey], default_comparer)
36
61
 
37
- def distinct(source: Observable[_T]) -> Observable[_T]:
38
- """Returns an observable sequence that contains only distinct
39
- elements according to the key_mapper and the comparer. Usage of
40
- this operator should be considered carefully due to the
41
- maintenance of an internal lookup structure which can grow
42
- large.
62
+ def subscribe(
63
+ observer: abc.ObserverBase[_T],
64
+ scheduler: abc.SchedulerBase | None = None,
65
+ ) -> abc.DisposableBase:
66
+ hashset = HashSet(comparer_)
43
67
 
44
- Examples:
45
- >>> res = obs = distinct(source)
68
+ def on_next(x: _T) -> None:
69
+ key = cast(_TKey, x)
46
70
 
47
- Args:
48
- source: Source observable to return distinct items from.
71
+ if key_mapper:
72
+ try:
73
+ key = key_mapper(x)
74
+ except Exception as ex:
75
+ observer.on_error(ex)
76
+ return
49
77
 
50
- Returns:
51
- An observable sequence only containing the distinct
52
- elements, based on a computed key value, from the source
53
- sequence.
54
- """
78
+ if hashset.push(key):
79
+ observer.on_next(x)
55
80
 
56
- def subscribe(
57
- observer: abc.ObserverBase[_T],
58
- scheduler: Optional[abc.SchedulerBase] = None,
59
- ) -> abc.DisposableBase:
60
- hashset = HashSet(comparer_)
81
+ return source.subscribe(
82
+ on_next, observer.on_error, observer.on_completed, scheduler=scheduler
83
+ )
61
84
 
62
- def on_next(x: _T) -> None:
63
- key = cast(_TKey, x)
64
-
65
- if key_mapper:
66
- try:
67
- key = key_mapper(x)
68
- except Exception as ex:
69
- observer.on_error(ex)
70
- return
71
-
72
- if hashset.push(key):
73
- observer.on_next(x)
74
-
75
- return source.subscribe(
76
- on_next, observer.on_error, observer.on_completed, scheduler=scheduler
77
- )
78
-
79
- return Observable(subscribe)
80
-
81
- return distinct
85
+ return Observable(subscribe)
82
86
 
83
87
 
84
88
  __all__ = ["distinct_"]
@@ -1,6 +1,8 @@
1
- from typing import Callable, Optional, TypeVar, cast
1
+ from collections.abc import Callable
2
+ from typing import TypeVar, cast
2
3
 
3
4
  from reactivex import Observable, abc
5
+ from reactivex.internal import curry_flip
4
6
  from reactivex.internal.basic import default_comparer, identity
5
7
  from reactivex.typing import Comparer, Mapper
6
8
 
@@ -8,73 +10,74 @@ _T = TypeVar("_T")
8
10
  _TKey = TypeVar("_TKey")
9
11
 
10
12
 
13
+ @curry_flip
11
14
  def distinct_until_changed_(
12
- key_mapper: Optional[Mapper[_T, _TKey]] = None,
13
- comparer: Optional[Comparer[_TKey]] = None,
14
- ) -> Callable[[Observable[_T]], Observable[_T]]:
15
-
15
+ source: Observable[_T],
16
+ key_mapper: Mapper[_T, _TKey] | None = None,
17
+ comparer: Comparer[_TKey] | None = None,
18
+ ) -> Observable[_T]:
19
+ """Returns an observable sequence that contains only distinct
20
+ contiguous elements according to the key_mapper and the
21
+ comparer.
22
+
23
+ Examples:
24
+ >>> res = source.pipe(distinct_until_changed())
25
+ >>> res = distinct_until_changed()(source)
26
+ >>> res = source.pipe(distinct_until_changed(lambda x: x.id))
27
+ >>> res = source.pipe(
28
+ ... distinct_until_changed(lambda x: x.id, lambda x, y: x == y)
29
+ ... )
30
+
31
+ Args:
32
+ source: The source observable sequence.
33
+ key_mapper: [Optional] A function to compute the comparison
34
+ key for each element. If not provided, it projects the
35
+ value.
36
+ comparer: [Optional] Equality comparer for computed key
37
+ values. If not provided, defaults to an equality
38
+ comparer function.
39
+
40
+ Returns:
41
+ An observable sequence only containing the distinct
42
+ contiguous elements, based on a computed key value, from
43
+ the source sequence.
44
+ """
16
45
  key_mapper_ = key_mapper or cast(Callable[[_T], _TKey], identity)
17
46
  comparer_ = comparer or default_comparer
18
47
 
19
- def distinct_until_changed(source: Observable[_T]) -> Observable[_T]:
20
- """Returns an observable sequence that contains only distinct
21
- contiguous elements according to the key_mapper and the
22
- comparer.
23
-
24
- Examples:
25
- >>> op = distinct_until_changed();
26
- >>> op = distinct_until_changed(lambda x: x.id)
27
- >>> op = distinct_until_changed(lambda x: x.id, lambda x, y: x == y)
28
-
29
- Args:
30
- key_mapper: [Optional] A function to compute the comparison
31
- key for each element. If not provided, it projects the
32
- value.
33
- comparer: [Optional] Equality comparer for computed key
34
- values. If not provided, defaults to an equality
35
- comparer function.
36
-
37
- Returns:
38
- An observable sequence only containing the distinct
39
- contiguous elements, based on a computed key value, from
40
- the source sequence.
41
- """
42
-
43
- def subscribe(
44
- observer: abc.ObserverBase[_T],
45
- scheduler: Optional[abc.SchedulerBase] = None,
46
- ) -> abc.DisposableBase:
47
- has_current_key = False
48
- current_key: _TKey = cast(_TKey, None)
49
-
50
- def on_next(value: _T) -> None:
51
- nonlocal has_current_key, current_key
52
- comparer_equals = False
48
+ def subscribe(
49
+ observer: abc.ObserverBase[_T],
50
+ scheduler: abc.SchedulerBase | None = None,
51
+ ) -> abc.DisposableBase:
52
+ has_current_key = False
53
+ current_key: _TKey = cast(_TKey, None)
54
+
55
+ def on_next(value: _T) -> None:
56
+ nonlocal has_current_key, current_key
57
+ comparer_equals = False
58
+ try:
59
+ key = key_mapper_(value)
60
+ except Exception as exception: # pylint: disable=broad-except
61
+ observer.on_error(exception)
62
+ return
63
+
64
+ if has_current_key:
53
65
  try:
54
- key = key_mapper_(value)
66
+ comparer_equals = comparer_(current_key, key)
55
67
  except Exception as exception: # pylint: disable=broad-except
56
68
  observer.on_error(exception)
57
69
  return
58
70
 
59
- if has_current_key:
60
- try:
61
- comparer_equals = comparer_(current_key, key)
62
- except Exception as exception: # pylint: disable=broad-except
63
- observer.on_error(exception)
64
- return
65
-
66
- if not has_current_key or not comparer_equals:
67
- has_current_key = True
68
- current_key = key
69
- observer.on_next(value)
70
-
71
- return source.subscribe(
72
- on_next, observer.on_error, observer.on_completed, scheduler=scheduler
73
- )
71
+ if not has_current_key or not comparer_equals:
72
+ has_current_key = True
73
+ current_key = key
74
+ observer.on_next(value)
74
75
 
75
- return Observable(subscribe)
76
+ return source.subscribe(
77
+ on_next, observer.on_error, observer.on_completed, scheduler=scheduler
78
+ )
76
79
 
77
- return distinct_until_changed
80
+ return Observable(subscribe)
78
81
 
79
82
 
80
83
  __all__ = ["distinct_until_changed_"]