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,53 +1,58 @@
1
- from typing import Any, Callable, Optional, TypeVar
1
+ from typing import Any, TypeVar
2
2
 
3
3
  from reactivex import Observable, abc, typing
4
4
  from reactivex.disposable import CompositeDisposable
5
+ from reactivex.internal import curry_flip
5
6
  from reactivex.scheduler import TimeoutScheduler
6
7
 
7
8
  _T = TypeVar("_T")
8
9
 
9
10
 
11
+ @curry_flip
10
12
  def take_with_time_(
11
- duration: typing.RelativeTime, scheduler: Optional[abc.SchedulerBase] = None
12
- ) -> Callable[[Observable[_T]], Observable[_T]]:
13
- def take_with_time(source: Observable[_T]) -> Observable[_T]:
14
- """Takes elements for the specified duration from the start of
15
- the observable source sequence.
16
-
17
- Example:
18
- >>> res = take_with_time(source)
19
-
20
- This operator accumulates a queue with a length enough to store
21
- elements received during the initial duration window. As more
22
- elements are received, elements older than the specified
23
- duration are taken from the queue and produced on the result
24
- sequence. This causes elements to be delayed with duration.
25
-
26
- Args:
27
- source: Source observable to take elements from.
28
-
29
- Returns:
30
- An observable sequence with the elements taken during the
31
- specified duration from the start of the source sequence.
32
- """
33
-
34
- def subscribe(
35
- observer: abc.ObserverBase[_T],
36
- scheduler_: Optional[abc.SchedulerBase] = None,
37
- ) -> abc.DisposableBase:
38
- _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
39
-
40
- def action(scheduler: abc.SchedulerBase, state: Any = None):
41
- observer.on_completed()
42
-
43
- disp = _scheduler.schedule_relative(duration, action)
44
- return CompositeDisposable(
45
- disp, source.subscribe(observer, scheduler=scheduler_)
46
- )
47
-
48
- return Observable(subscribe)
49
-
50
- return take_with_time
13
+ source: Observable[_T],
14
+ duration: typing.RelativeTime,
15
+ scheduler: abc.SchedulerBase | None = None,
16
+ ) -> Observable[_T]:
17
+ """Takes elements for the specified duration from the start of
18
+ the observable source sequence.
19
+
20
+ Examples:
21
+ >>> source.pipe(take_with_time(5.0))
22
+ >>> take_with_time(5.0)(source)
23
+
24
+ This operator accumulates a queue with a length enough to store
25
+ elements received during the initial duration window. As more
26
+ elements are received, elements older than the specified
27
+ duration are taken from the queue and produced on the result
28
+ sequence. This causes elements to be delayed with duration.
29
+
30
+ Args:
31
+ source: Source observable to take elements from.
32
+ duration: Duration for taking elements from the start of
33
+ the sequence.
34
+ scheduler: Scheduler to use for timing.
35
+
36
+ Returns:
37
+ An observable sequence with the elements taken during the
38
+ specified duration from the start of the source sequence.
39
+ """
40
+
41
+ def subscribe(
42
+ observer: abc.ObserverBase[_T],
43
+ scheduler_: abc.SchedulerBase | None = None,
44
+ ) -> abc.DisposableBase:
45
+ _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
46
+
47
+ def action(scheduler: abc.SchedulerBase, state: Any = None):
48
+ observer.on_completed()
49
+
50
+ disp = _scheduler.schedule_relative(duration, action)
51
+ return CompositeDisposable(
52
+ disp, source.subscribe(observer, scheduler=scheduler_)
53
+ )
54
+
55
+ return Observable(subscribe)
51
56
 
52
57
 
53
58
  __all__ = ["take_with_time_"]
@@ -1,57 +1,64 @@
1
1
  from datetime import datetime
2
- from typing import Callable, Optional, TypeVar
2
+ from typing import TypeVar
3
3
 
4
4
  from reactivex import Observable, abc, typing
5
+ from reactivex.internal import curry_flip
5
6
  from reactivex.scheduler import TimeoutScheduler
6
7
 
7
8
  _T = TypeVar("_T")
8
9
 
9
10
 
11
+ @curry_flip
10
12
  def throttle_first_(
11
- window_duration: typing.RelativeTime, scheduler: Optional[abc.SchedulerBase] = None
12
- ) -> Callable[[Observable[_T]], Observable[_T]]:
13
- def throttle_first(source: Observable[_T]) -> Observable[_T]:
14
- """Returns an observable that emits only the first item emitted
15
- by the source Observable during sequential time windows of a
16
- specified duration.
17
-
18
- Args:
19
- source: Source observable to throttle.
20
-
21
- Returns:
22
- An Observable that performs the throttle operation.
23
- """
24
-
25
- def subscribe(
26
- observer: abc.ObserverBase[_T],
27
- scheduler_: Optional[abc.SchedulerBase] = None,
28
- ) -> abc.DisposableBase:
29
- _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
30
-
31
- duration = _scheduler.to_timedelta(window_duration or 0.0)
32
- if duration <= _scheduler.to_timedelta(0):
33
- raise ValueError("window_duration cannot be less or equal zero.")
34
- last_on_next: Optional[datetime] = None
35
-
36
- def on_next(x: _T) -> None:
37
- nonlocal last_on_next
38
- emit = False
39
- now = _scheduler.now
40
-
41
- with source.lock:
42
- if not last_on_next or now - last_on_next >= duration:
43
- last_on_next = now
44
- emit = True
45
- if emit:
46
- observer.on_next(x)
47
-
48
- return source.subscribe(
49
- on_next, observer.on_error, observer.on_completed, scheduler=_scheduler
50
- )
51
-
52
- return Observable(subscribe)
53
-
54
- return throttle_first
13
+ source: Observable[_T],
14
+ window_duration: typing.RelativeTime,
15
+ scheduler: abc.SchedulerBase | None = None,
16
+ ) -> Observable[_T]:
17
+ """Returns an observable that emits only the first item emitted
18
+ by the source Observable during sequential time windows of a
19
+ specified duration.
20
+
21
+ Examples:
22
+ >>> result = source.pipe(throttle_first(1.0))
23
+ >>> result = throttle_first(1.0)(source)
24
+
25
+ Args:
26
+ source: Source observable to throttle.
27
+ window_duration: Duration of windows during which to throttle.
28
+ scheduler: Optional scheduler to use for timing.
29
+
30
+ Returns:
31
+ An Observable that performs the throttle operation.
32
+ """
33
+
34
+ def subscribe(
35
+ observer: abc.ObserverBase[_T],
36
+ scheduler_: abc.SchedulerBase | None = None,
37
+ ) -> abc.DisposableBase:
38
+ _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
39
+
40
+ duration = _scheduler.to_timedelta(window_duration or 0.0)
41
+ if duration <= _scheduler.to_timedelta(0):
42
+ raise ValueError("window_duration cannot be less or equal zero.")
43
+ last_on_next: datetime | None = None
44
+
45
+ def on_next(x: _T) -> None:
46
+ nonlocal last_on_next
47
+ emit = False
48
+ now = _scheduler.now
49
+
50
+ with source.lock:
51
+ if not last_on_next or now - last_on_next >= duration:
52
+ last_on_next = now
53
+ emit = True
54
+ if emit:
55
+ observer.on_next(x)
56
+
57
+ return source.subscribe(
58
+ on_next, observer.on_error, observer.on_completed, scheduler=_scheduler
59
+ )
60
+
61
+ return Observable(subscribe)
55
62
 
56
63
 
57
64
  __all__ = ["throttle_first_"]
@@ -1,9 +1,10 @@
1
1
  from dataclasses import dataclass
2
2
  from datetime import timedelta
3
- from typing import Callable, Generic, Optional, TypeVar
3
+ from typing import Generic, TypeVar
4
4
 
5
5
  from reactivex import Observable, abc
6
6
  from reactivex import operators as ops
7
+ from reactivex.internal import curry_flip
7
8
  from reactivex.scheduler import TimeoutScheduler
8
9
 
9
10
  _T = TypeVar("_T")
@@ -15,39 +16,42 @@ class TimeInterval(Generic[_T]):
15
16
  interval: timedelta
16
17
 
17
18
 
19
+ @curry_flip
18
20
  def time_interval_(
19
- scheduler: Optional[abc.SchedulerBase] = None,
20
- ) -> Callable[[Observable[_T]], Observable[TimeInterval[_T]]]:
21
- def time_interval(source: Observable[_T]) -> Observable[TimeInterval[_T]]:
22
- """Records the time interval between consecutive values in an
23
- observable sequence.
24
-
25
- >>> res = time_interval(source)
26
-
27
- Return:
28
- An observable sequence with time interval information on
29
- values.
30
- """
31
-
32
- def subscribe(
33
- observer: abc.ObserverBase[TimeInterval[_T]],
34
- scheduler_: Optional[abc.SchedulerBase] = None,
35
- ) -> abc.DisposableBase:
36
- _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
37
- last = _scheduler.now
38
-
39
- def mapper(value: _T) -> TimeInterval[_T]:
40
- nonlocal last
41
-
42
- now = _scheduler.now
43
- span = now - last
44
- last = now
45
- return TimeInterval(value=value, interval=span)
46
-
47
- return source.pipe(ops.map(mapper)).subscribe(
48
- observer, scheduler=_scheduler
49
- )
50
-
51
- return Observable(subscribe)
52
-
53
- return time_interval
21
+ source: Observable[_T],
22
+ scheduler: abc.SchedulerBase | None = None,
23
+ ) -> Observable[TimeInterval[_T]]:
24
+ """Records the time interval between consecutive values in an
25
+ observable sequence.
26
+
27
+ Examples:
28
+ >>> res = source.pipe(time_interval())
29
+ >>> res = time_interval()(source)
30
+
31
+ Args:
32
+ source: The source observable sequence.
33
+ scheduler: Scheduler to use for timing.
34
+
35
+ Returns:
36
+ An observable sequence with time interval information on
37
+ values.
38
+ """
39
+
40
+ def subscribe(
41
+ observer: abc.ObserverBase[TimeInterval[_T]],
42
+ scheduler_: abc.SchedulerBase | None = None,
43
+ ) -> abc.DisposableBase:
44
+ _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
45
+ last = _scheduler.now
46
+
47
+ def mapper(value: _T) -> TimeInterval[_T]:
48
+ nonlocal last
49
+
50
+ now = _scheduler.now
51
+ span = now - last
52
+ last = now
53
+ return TimeInterval(value=value, interval=span)
54
+
55
+ return source.pipe(ops.map(mapper)).subscribe(observer, scheduler=_scheduler)
56
+
57
+ return Observable(subscribe)
@@ -1,6 +1,6 @@
1
1
  from asyncio import Future
2
2
  from datetime import datetime
3
- from typing import Any, Callable, Optional, TypeVar, Union
3
+ from typing import Any, TypeVar, Union
4
4
 
5
5
  from reactivex import Observable, abc, from_future, throw, typing
6
6
  from reactivex.disposable import (
@@ -8,94 +8,96 @@ from reactivex.disposable import (
8
8
  SerialDisposable,
9
9
  SingleAssignmentDisposable,
10
10
  )
11
+ from reactivex.internal import curry_flip
11
12
  from reactivex.scheduler import TimeoutScheduler
12
13
 
13
14
  _T = TypeVar("_T")
14
15
 
15
16
 
17
+ @curry_flip
16
18
  def timeout_(
19
+ source: Observable[_T],
17
20
  duetime: typing.AbsoluteOrRelativeTime,
18
- other: Optional[Union[Observable[_T], "Future[_T]"]] = None,
19
- scheduler: Optional[abc.SchedulerBase] = None,
20
- ) -> Callable[[Observable[_T]], Observable[_T]]:
21
-
21
+ other: Union[Observable[_T], "Future[_T]"] | None = None,
22
+ scheduler: abc.SchedulerBase | None = None,
23
+ ) -> Observable[_T]:
24
+ """Returns the source observable sequence or the other observable
25
+ sequence if duetime elapses.
26
+
27
+ Examples:
28
+ >>> source.pipe(timeout(5.0))
29
+ >>> timeout(5.0)(source)
30
+
31
+ Args:
32
+ source: Source observable to timeout.
33
+ duetime: Timeout duration.
34
+ other: Observable to switch to on timeout.
35
+ scheduler: Scheduler to use for timing.
36
+
37
+ Returns:
38
+ An observable sequence switching to the other sequence in
39
+ case of a timeout.
40
+ """
22
41
  other = other or throw(Exception("Timeout"))
23
42
  if isinstance(other, Future):
24
43
  obs = from_future(other)
25
44
  else:
26
45
  obs = other
27
46
 
28
- def timeout(source: Observable[_T]) -> Observable[_T]:
29
- """Returns the source observable sequence or the other observable
30
- sequence if duetime elapses.
31
-
32
- Examples:
33
- >>> res = timeout(source)
34
-
35
- Args:
36
- source: Source observable to timeout
37
-
38
- Returns:
39
- An observable sequence switching to the other sequence in
40
- case of a timeout.
41
- """
42
-
43
- def subscribe(
44
- observer: abc.ObserverBase[_T],
45
- scheduler_: Optional[abc.SchedulerBase] = None,
46
- ) -> abc.DisposableBase:
47
- _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
48
-
49
- switched = [False]
50
- _id = [0]
51
-
52
- original = SingleAssignmentDisposable()
53
- subscription = SerialDisposable()
54
- timer = SerialDisposable()
55
- subscription.disposable = original
56
-
57
- def create_timer() -> None:
58
- my_id = _id[0]
59
-
60
- def action(scheduler: abc.SchedulerBase, state: Any = None):
61
- switched[0] = _id[0] == my_id
62
- timer_wins = switched[0]
63
- if timer_wins:
64
- subscription.disposable = obs.subscribe(
65
- observer, scheduler=scheduler
66
- )
67
-
68
- if isinstance(duetime, datetime):
69
- timer.disposable = _scheduler.schedule_absolute(duetime, action)
70
- else:
71
- timer.disposable = _scheduler.schedule_relative(duetime, action)
72
-
73
- create_timer()
74
-
75
- def on_next(value: _T) -> None:
76
- send_wins = not switched[0]
77
- if send_wins:
78
- _id[0] += 1
79
- observer.on_next(value)
80
- create_timer()
81
-
82
- def on_error(error: Exception) -> None:
83
- on_error_wins = not switched[0]
84
- if on_error_wins:
85
- _id[0] += 1
86
- observer.on_error(error)
87
-
88
- def on_completed() -> None:
89
- on_completed_wins = not switched[0]
90
- if on_completed_wins:
91
- _id[0] += 1
92
- observer.on_completed()
93
-
94
- original.disposable = source.subscribe(
95
- on_next, on_error, on_completed, scheduler=scheduler_
96
- )
97
- return CompositeDisposable(subscription, timer)
98
-
99
- return Observable(subscribe)
100
-
101
- return timeout
47
+ def subscribe(
48
+ observer: abc.ObserverBase[_T],
49
+ scheduler_: abc.SchedulerBase | None = None,
50
+ ) -> abc.DisposableBase:
51
+ _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
52
+
53
+ switched = [False]
54
+ _id = [0]
55
+
56
+ original = SingleAssignmentDisposable()
57
+ subscription = SerialDisposable()
58
+ timer = SerialDisposable()
59
+ subscription.disposable = original
60
+
61
+ def create_timer() -> None:
62
+ my_id = _id[0]
63
+
64
+ def action(scheduler: abc.SchedulerBase, state: Any = None):
65
+ switched[0] = _id[0] == my_id
66
+ timer_wins = switched[0]
67
+ if timer_wins:
68
+ subscription.disposable = obs.subscribe(
69
+ observer, scheduler=scheduler
70
+ )
71
+
72
+ if isinstance(duetime, datetime):
73
+ timer.disposable = _scheduler.schedule_absolute(duetime, action)
74
+ else:
75
+ timer.disposable = _scheduler.schedule_relative(duetime, action)
76
+
77
+ create_timer()
78
+
79
+ def on_next(value: _T) -> None:
80
+ send_wins = not switched[0]
81
+ if send_wins:
82
+ _id[0] += 1
83
+ observer.on_next(value)
84
+ create_timer()
85
+
86
+ def on_error(error: Exception) -> None:
87
+ on_error_wins = not switched[0]
88
+ if on_error_wins:
89
+ _id[0] += 1
90
+ observer.on_error(error)
91
+
92
+ def on_completed() -> None:
93
+ on_completed_wins = not switched[0]
94
+ if on_completed_wins:
95
+ _id[0] += 1
96
+ observer.on_completed()
97
+
98
+ original.disposable = source.subscribe(
99
+ on_next, on_error, on_completed, scheduler=scheduler_
100
+ )
101
+ return CompositeDisposable(subscription, timer)
102
+
103
+ return Observable(subscribe)
@@ -1,4 +1,5 @@
1
- from typing import Any, Callable, Optional, TypeVar
1
+ from collections.abc import Callable
2
+ from typing import Any, TypeVar
2
3
 
3
4
  import reactivex
4
5
  from reactivex import Observable, abc
@@ -12,9 +13,9 @@ _T = TypeVar("_T")
12
13
 
13
14
 
14
15
  def timeout_with_mapper_(
15
- first_timeout: Optional[Observable[_T]] = None,
16
- timeout_duration_mapper: Optional[Callable[[Any], Observable[Any]]] = None,
17
- other: Optional[Observable[_T]] = None,
16
+ first_timeout: Observable[_T] | None = None,
17
+ timeout_duration_mapper: Callable[[Any], Observable[Any]] | None = None,
18
+ other: Observable[_T] | None = None,
18
19
  ) -> Callable[[Observable[_T]], Observable[_T]]:
19
20
  """Returns the source observable sequence, switching to the other
20
21
  observable sequence if a timeout is signaled.
@@ -48,7 +49,7 @@ def timeout_with_mapper_(
48
49
  def timeout_with_mapper(source: Observable[_T]) -> Observable[_T]:
49
50
  def subscribe(
50
51
  observer: abc.ObserverBase[_T],
51
- scheduler: Optional[abc.SchedulerBase] = None,
52
+ scheduler: abc.SchedulerBase | None = None,
52
53
  ) -> abc.DisposableBase:
53
54
  subscription = SerialDisposable()
54
55
  timer = SerialDisposable()
@@ -1,8 +1,9 @@
1
1
  from dataclasses import dataclass
2
2
  from datetime import datetime
3
- from typing import Callable, Generic, Optional, TypeVar
3
+ from typing import Generic, TypeVar
4
4
 
5
5
  from reactivex import Observable, abc, defer, operators
6
+ from reactivex.internal import curry_flip
6
7
  from reactivex.scheduler import TimeoutScheduler
7
8
 
8
9
  _T = TypeVar("_T")
@@ -14,36 +15,37 @@ class Timestamp(Generic[_T]):
14
15
  timestamp: datetime
15
16
 
16
17
 
18
+ @curry_flip
17
19
  def timestamp_(
18
- scheduler: Optional[abc.SchedulerBase] = None,
19
- ) -> Callable[[Observable[_T]], Observable[Timestamp[_T]]]:
20
- def timestamp(source: Observable[_T]) -> Observable[Timestamp[_T]]:
21
- """Records the timestamp for each value in an observable sequence.
20
+ source: Observable[_T],
21
+ scheduler: abc.SchedulerBase | None = None,
22
+ ) -> Observable[Timestamp[_T]]:
23
+ """Records the timestamp for each value in an observable sequence.
22
24
 
23
- Examples:
24
- >>> timestamp(source)
25
+ Examples:
26
+ >>> result = source.pipe(timestamp())
27
+ >>> result = timestamp()(source)
25
28
 
26
- Produces objects with attributes `value` and `timestamp`, where
27
- value is the original value.
29
+ Produces objects with attributes `value` and `timestamp`, where
30
+ value is the original value.
28
31
 
29
- Args:
30
- source: Observable source to timestamp.
32
+ Args:
33
+ source: Observable source to timestamp.
34
+ scheduler: Optional scheduler to use for timestamping.
31
35
 
32
- Returns:
33
- An observable sequence with timestamp information on values.
34
- """
36
+ Returns:
37
+ An observable sequence with timestamp information on values.
38
+ """
35
39
 
36
- def factory(scheduler_: Optional[abc.SchedulerBase] = None):
37
- _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
40
+ def factory(scheduler_: abc.SchedulerBase | None = None):
41
+ _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
38
42
 
39
- def mapper(value: _T) -> Timestamp[_T]:
40
- return Timestamp(value=value, timestamp=_scheduler.now)
43
+ def mapper(value: _T) -> Timestamp[_T]:
44
+ return Timestamp(value=value, timestamp=_scheduler.now)
41
45
 
42
- return source.pipe(operators.map(mapper))
46
+ return source.pipe(operators.map(mapper))
43
47
 
44
- return defer(factory)
45
-
46
- return timestamp
48
+ return defer(factory)
47
49
 
48
50
 
49
51
  __all__ = ["timestamp_"]