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,55 +1,56 @@
1
- from typing import Callable, List, 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
 
8
- def take_last_buffer_(count: int) -> Callable[[Observable[_T]], Observable[List[_T]]]:
9
- def take_last_buffer(source: Observable[_T]) -> Observable[List[_T]]:
10
- """Returns an array with the specified number of contiguous
11
- elements from the end of an observable sequence.
9
+ @curry_flip
10
+ def take_last_buffer_(source: Observable[_T], count: int) -> Observable[list[_T]]:
11
+ """Returns an array with the specified number of contiguous
12
+ elements from the end of an observable sequence.
12
13
 
13
- Example:
14
- >>> res = take_last(source)
14
+ Example:
15
+ >>> res = source.pipe(take_last_buffer(5))
16
+ >>> res = take_last_buffer(5)(source)
15
17
 
16
- This operator accumulates a buffer with a length enough to
17
- store elements count elements. Upon completion of the source
18
- sequence, this buffer is drained on the result sequence. This
19
- causes the elements to be delayed.
18
+ This operator accumulates a buffer with a length enough to
19
+ store elements count elements. Upon completion of the source
20
+ sequence, this buffer is drained on the result sequence. This
21
+ causes the elements to be delayed.
20
22
 
21
- Args:
22
- source: Source observable to take elements from.
23
+ Args:
24
+ source: Source observable to take elements from.
25
+ count: Number of elements to take from the end.
23
26
 
24
- Returns:
25
- An observable sequence containing a single list with the
26
- specified number of elements from the end of the source
27
- sequence.
28
- """
27
+ Returns:
28
+ An observable sequence containing a single list with the
29
+ specified number of elements from the end of the source
30
+ sequence.
31
+ """
29
32
 
30
- def subscribe(
31
- observer: abc.ObserverBase[List[_T]],
32
- scheduler: Optional[abc.SchedulerBase] = None,
33
- ) -> abc.DisposableBase:
34
- q: List[_T] = []
33
+ def subscribe(
34
+ observer: abc.ObserverBase[list[_T]],
35
+ scheduler: abc.SchedulerBase | None = None,
36
+ ) -> abc.DisposableBase:
37
+ q: list[_T] = []
35
38
 
36
- def on_next(x: _T) -> None:
37
- with source.lock:
38
- q.append(x)
39
- if len(q) > count:
40
- q.pop(0)
39
+ def on_next(x: _T) -> None:
40
+ with source.lock:
41
+ q.append(x)
42
+ if len(q) > count:
43
+ q.pop(0)
41
44
 
42
- def on_completed() -> None:
43
- observer.on_next(q)
44
- observer.on_completed()
45
+ def on_completed() -> None:
46
+ observer.on_next(q)
47
+ observer.on_completed()
45
48
 
46
- return source.subscribe(
47
- on_next, observer.on_error, on_completed, scheduler=scheduler
48
- )
49
+ return source.subscribe(
50
+ on_next, observer.on_error, on_completed, scheduler=scheduler
51
+ )
49
52
 
50
- return Observable(subscribe)
51
-
52
- return take_last_buffer
53
+ return Observable(subscribe)
53
54
 
54
55
 
55
56
  __all__ = ["take_last_buffer_"]
@@ -1,68 +1,72 @@
1
- from typing import Any, Callable, Dict, List, Optional, TypeVar
1
+ from typing import Any, TypeVar
2
2
 
3
3
  from reactivex import Observable, abc, typing
4
+ from reactivex.internal import curry_flip
4
5
  from reactivex.scheduler import TimeoutScheduler
5
6
 
6
7
  _T = TypeVar("_T")
7
8
 
8
9
 
10
+ @curry_flip
9
11
  def take_last_with_time_(
10
- duration: typing.RelativeTime, scheduler: Optional[abc.SchedulerBase] = None
11
- ) -> Callable[[Observable[_T]], Observable[_T]]:
12
- def take_last_with_time(source: Observable[_T]) -> Observable[_T]:
13
- """Returns elements within the specified duration from the end
14
- of the observable source sequence.
15
-
16
- Example:
17
- >>> res = take_last_with_time(source)
18
-
19
- This operator accumulates a queue with a length enough to store
20
- elements received during the initial duration window. As more
21
- elements are received, elements older than the specified
22
- duration are taken from the queue and produced on the result
23
- sequence. This causes elements to be delayed with duration.
24
-
25
- Args:
26
- duration: Duration for taking elements from the end of the
12
+ source: Observable[_T],
13
+ duration: typing.RelativeTime,
14
+ scheduler: abc.SchedulerBase | None = None,
15
+ ) -> Observable[_T]:
16
+ """Returns elements within the specified duration from the end
17
+ of the observable source sequence.
18
+
19
+ Examples:
20
+ >>> source.pipe(take_last_with_time(5.0))
21
+ >>> take_last_with_time(5.0)(source)
22
+
23
+ This operator accumulates a queue with a length enough to store
24
+ elements received during the initial duration window. As more
25
+ elements are received, elements older than the specified
26
+ duration are taken from the queue and produced on the result
27
+ sequence. This causes elements to be delayed with duration.
28
+
29
+ Args:
30
+ source: Source observable to take elements from.
31
+ duration: Duration for taking elements from the end of the
27
32
  sequence.
28
-
29
- Returns:
30
- An observable sequence with the elements taken during the
31
- specified duration from the end of the source sequence.
32
- """
33
-
34
- def subscribe(
35
- observer: abc.ObserverBase[_T],
36
- scheduler_: Optional[abc.SchedulerBase] = None,
37
- ) -> abc.DisposableBase:
38
- nonlocal duration
39
-
40
- _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
41
- duration = _scheduler.to_timedelta(duration)
42
- q: List[Dict[str, Any]] = []
43
-
44
- def on_next(x: _T) -> None:
45
- now = _scheduler.now
46
- q.append({"interval": now, "value": x})
47
- while q and now - q[0]["interval"] >= duration:
48
- q.pop(0)
49
-
50
- def on_completed():
51
- now = _scheduler.now
52
- while q:
53
- _next = q.pop(0)
54
- if now - _next["interval"] <= duration:
55
- observer.on_next(_next["value"])
56
-
57
- observer.on_completed()
58
-
59
- return source.subscribe(
60
- on_next, observer.on_error, on_completed, scheduler=scheduler_
61
- )
62
-
63
- return Observable(subscribe)
64
-
65
- return take_last_with_time
33
+ scheduler: Scheduler to use for timing.
34
+
35
+ Returns:
36
+ An observable sequence with the elements taken during the
37
+ specified duration from the end of the source sequence.
38
+ """
39
+
40
+ def subscribe(
41
+ observer: abc.ObserverBase[_T],
42
+ scheduler_: abc.SchedulerBase | None = None,
43
+ ) -> abc.DisposableBase:
44
+ nonlocal duration
45
+
46
+ _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
47
+ duration = _scheduler.to_timedelta(duration)
48
+ q: list[dict[str, Any]] = []
49
+
50
+ def on_next(x: _T) -> None:
51
+ now = _scheduler.now
52
+ q.append({"interval": now, "value": x})
53
+ while q and now - q[0]["interval"] >= duration:
54
+ q.pop(0)
55
+
56
+ def on_completed():
57
+ now = _scheduler.now
58
+ while q:
59
+ _next = q.pop(0)
60
+ if now - _next["interval"] <= duration:
61
+ observer.on_next(_next["value"])
62
+
63
+ observer.on_completed()
64
+
65
+ return source.subscribe(
66
+ on_next, observer.on_error, on_completed, scheduler=scheduler_
67
+ )
68
+
69
+ return Observable(subscribe)
66
70
 
67
71
 
68
72
  __all__ = ["take_last_with_time_"]
@@ -1,51 +1,52 @@
1
1
  from asyncio import Future
2
- from typing import Callable, Optional, TypeVar, Union
2
+ from typing import TypeVar
3
3
 
4
4
  from reactivex import Observable, abc, from_future
5
5
  from reactivex.disposable import CompositeDisposable
6
- from reactivex.internal import noop
6
+ from reactivex.internal import curry_flip, noop
7
7
 
8
8
  _T = TypeVar("_T")
9
9
 
10
10
 
11
+ @curry_flip
11
12
  def take_until_(
12
- other: Union[Observable[_T], "Future[_T]"]
13
- ) -> Callable[[Observable[_T]], Observable[_T]]:
13
+ source: Observable[_T],
14
+ other: Observable[_T] | Future[_T],
15
+ ) -> Observable[_T]:
16
+ """Returns the values from the source observable sequence until
17
+ the other observable sequence produces a value.
18
+
19
+ Examples:
20
+ >>> source.pipe(take_until(other))
21
+ >>> take_until(other)(source)
22
+
23
+ Args:
24
+ source: The source observable sequence.
25
+ other: Observable or Future that terminates propagation.
26
+
27
+ Returns:
28
+ An observable sequence containing the elements of the source
29
+ sequence up to the point the other sequence interrupted
30
+ further propagation.
31
+ """
14
32
  if isinstance(other, Future):
15
33
  obs: Observable[_T] = from_future(other)
16
34
  else:
17
35
  obs = other
18
36
 
19
- def take_until(source: Observable[_T]) -> Observable[_T]:
20
- """Returns the values from the source observable sequence until
21
- the other observable sequence produces a value.
37
+ def subscribe(
38
+ observer: abc.ObserverBase[_T],
39
+ scheduler: abc.SchedulerBase | None = None,
40
+ ) -> abc.DisposableBase:
41
+ def on_completed(_: _T) -> None:
42
+ observer.on_completed()
22
43
 
23
- Args:
24
- source: The source observable sequence.
44
+ return CompositeDisposable(
45
+ source.subscribe(observer, scheduler=scheduler),
46
+ obs.subscribe(on_completed, observer.on_error, noop, scheduler=scheduler),
47
+ )
25
48
 
26
- Returns:
27
- An observable sequence containing the elements of the source
28
- sequence up to the point the other sequence interrupted
29
- further propagation.
30
- """
31
-
32
- def subscribe(
33
- observer: abc.ObserverBase[_T],
34
- scheduler: Optional[abc.SchedulerBase] = None,
35
- ) -> abc.DisposableBase:
36
- def on_completed(_: _T) -> None:
37
- observer.on_completed()
38
-
39
- return CompositeDisposable(
40
- source.subscribe(observer, scheduler=scheduler),
41
- obs.subscribe(
42
- on_completed, observer.on_error, noop, scheduler=scheduler
43
- ),
44
- )
45
-
46
- return Observable(subscribe)
47
-
48
- return take_until
49
+ return Observable(subscribe)
49
50
 
50
51
 
51
52
  __all__ = ["take_until_"]
@@ -1,53 +1,56 @@
1
1
  from datetime import datetime
2
- from typing import Any, Callable, Optional, TypeVar
2
+ from typing import Any, TypeVar
3
3
 
4
4
  from reactivex import Observable, abc, typing
5
5
  from reactivex.disposable import CompositeDisposable
6
+ from reactivex.internal import curry_flip
6
7
  from reactivex.scheduler import TimeoutScheduler
7
8
 
8
9
  _T = TypeVar("_T")
9
10
 
10
11
 
12
+ @curry_flip
11
13
  def take_until_with_time_(
14
+ source: Observable[_T],
12
15
  end_time: typing.AbsoluteOrRelativeTime,
13
- scheduler: Optional[abc.SchedulerBase] = None,
14
- ) -> Callable[[Observable[_T]], Observable[_T]]:
15
- def take_until_with_time(source: Observable[_T]) -> Observable[_T]:
16
- """Takes elements for the specified duration until the specified end
17
- time, using the specified scheduler to run timers.
18
-
19
- Examples:
20
- >>> res = take_until_with_time(source)
21
-
22
- Args:
23
- source: Source observale to take elements from.
24
-
25
- Returns:
26
- An observable sequence with the elements taken
27
- until the specified end time.
28
- """
29
-
30
- def subscribe(
31
- observer: abc.ObserverBase[_T],
32
- scheduler_: Optional[abc.SchedulerBase] = None,
33
- ) -> abc.DisposableBase:
34
- _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
35
-
36
- def action(scheduler: abc.SchedulerBase, state: Any = None):
37
- observer.on_completed()
38
-
39
- if isinstance(end_time, datetime):
40
- task = _scheduler.schedule_absolute(end_time, action)
41
- else:
42
- task = _scheduler.schedule_relative(end_time, action)
43
-
44
- return CompositeDisposable(
45
- task, source.subscribe(observer, scheduler=scheduler_)
46
- )
47
-
48
- return Observable(subscribe)
49
-
50
- return take_until_with_time
16
+ scheduler: abc.SchedulerBase | None = None,
17
+ ) -> Observable[_T]:
18
+ """Takes elements for the specified duration until the specified end
19
+ time, using the specified scheduler to run timers.
20
+
21
+ Examples:
22
+ >>> source.pipe(take_until_with_time(dt))
23
+ >>> take_until_with_time(5.0)(source)
24
+
25
+ Args:
26
+ source: Source observable to take elements from.
27
+ end_time: Absolute or relative time when to complete.
28
+ scheduler: Scheduler to use for timing.
29
+
30
+ Returns:
31
+ An observable sequence with the elements taken
32
+ until the specified end time.
33
+ """
34
+
35
+ def subscribe(
36
+ observer: abc.ObserverBase[_T],
37
+ scheduler_: abc.SchedulerBase | None = None,
38
+ ) -> abc.DisposableBase:
39
+ _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton()
40
+
41
+ def action(scheduler: abc.SchedulerBase, state: Any = None):
42
+ observer.on_completed()
43
+
44
+ if isinstance(end_time, datetime):
45
+ task = _scheduler.schedule_absolute(end_time, action)
46
+ else:
47
+ task = _scheduler.schedule_relative(end_time, action)
48
+
49
+ return CompositeDisposable(
50
+ task, source.subscribe(observer, scheduler=scheduler_)
51
+ )
52
+
53
+ return Observable(subscribe)
51
54
 
52
55
 
53
56
  __all__ = ["take_until_with_time_"]
@@ -1,121 +1,129 @@
1
- from typing import Any, Callable, Optional, TypeVar
1
+ from typing import Any, TypeVar
2
2
 
3
3
  from reactivex import Observable, abc
4
+ from reactivex.internal import curry_flip
4
5
  from reactivex.typing import Predicate, PredicateIndexed
5
6
 
6
7
  _T = TypeVar("_T")
7
8
 
8
9
 
10
+ @curry_flip
9
11
  def take_while_(
10
- predicate: Predicate[_T], inclusive: bool = False
11
- ) -> Callable[[Observable[_T]], Observable[_T]]:
12
- def take_while(source: Observable[_T]) -> Observable[_T]:
13
- """Returns elements from an observable sequence as long as a
14
- specified condition is true.
15
-
16
- Example:
17
- >>> take_while(source)
18
-
19
- Args:
20
- source: The source observable to take from.
21
-
22
- Returns:
23
- An observable sequence that contains the elements from the
24
- input sequence that occur before the element at which the
25
- test no longer passes.
26
- """
27
-
28
- def subscribe(
29
- observer: abc.ObserverBase[_T],
30
- scheduler: Optional[abc.SchedulerBase] = None,
31
- ) -> abc.DisposableBase:
32
- running = True
33
-
34
- def on_next(value: _T):
35
- nonlocal running
36
-
37
- with source.lock:
38
- if not running:
39
- return
40
-
41
- try:
42
- running = predicate(value)
43
- except Exception as exn:
44
- observer.on_error(exn)
45
- return
46
-
47
- if running:
12
+ source: Observable[_T],
13
+ predicate: Predicate[_T],
14
+ inclusive: bool = False,
15
+ ) -> Observable[_T]:
16
+ """Returns elements from an observable sequence as long as a
17
+ specified condition is true.
18
+
19
+ Examples:
20
+ >>> result = source.pipe(take_while(lambda x: x < 10))
21
+ >>> result = take_while(lambda x: x < 10)(source)
22
+ >>> result = source.pipe(take_while(lambda x: x < 10, inclusive=True))
23
+
24
+ Args:
25
+ source: The source observable to take from.
26
+ predicate: A function to test each element for a condition.
27
+ inclusive: Include the element that fails the predicate.
28
+
29
+ Returns:
30
+ An observable sequence that contains the elements from the
31
+ input sequence that occur before the element at which the
32
+ test no longer passes.
33
+ """
34
+
35
+ def subscribe(
36
+ observer: abc.ObserverBase[_T],
37
+ scheduler: abc.SchedulerBase | None = None,
38
+ ) -> abc.DisposableBase:
39
+ running = True
40
+
41
+ def on_next(value: _T):
42
+ nonlocal running
43
+
44
+ with source.lock:
45
+ if not running:
46
+ return
47
+
48
+ try:
49
+ running = predicate(value)
50
+ except Exception as exn:
51
+ observer.on_error(exn)
52
+ return
53
+
54
+ if running:
55
+ observer.on_next(value)
56
+ else:
57
+ if inclusive:
48
58
  observer.on_next(value)
49
- else:
50
- if inclusive:
51
- observer.on_next(value)
52
- observer.on_completed()
53
-
54
- return source.subscribe(
55
- on_next, observer.on_error, observer.on_completed, scheduler=scheduler
56
- )
59
+ observer.on_completed()
57
60
 
58
- return Observable(subscribe)
61
+ return source.subscribe(
62
+ on_next, observer.on_error, observer.on_completed, scheduler=scheduler
63
+ )
59
64
 
60
- return take_while
65
+ return Observable(subscribe)
61
66
 
62
67
 
68
+ @curry_flip
63
69
  def take_while_indexed_(
64
- predicate: PredicateIndexed[_T], inclusive: bool = False
65
- ) -> Callable[[Observable[_T]], Observable[_T]]:
66
- def take_while_indexed(source: Observable[_T]) -> Observable[_T]:
67
- """Returns elements from an observable sequence as long as a
68
- specified condition is true. The element's index is used in the
69
- logic of the predicate function.
70
-
71
- Example:
72
- >>> take_while(source)
73
-
74
- Args:
75
- source: Source observable to take from.
76
-
77
- Returns:
78
- An observable sequence that contains the elements from the
79
- input sequence that occur before the element at which the
80
- test no longer passes.
81
- """
82
-
83
- def subscribe(
84
- observer: abc.ObserverBase[_T],
85
- scheduler: Optional[abc.SchedulerBase] = None,
86
- ) -> abc.DisposableBase:
87
- running = True
88
- i = 0
89
-
90
- def on_next(value: Any) -> None:
91
- nonlocal running, i
92
-
93
- with source.lock:
94
- if not running:
95
- return
96
-
97
- try:
98
- running = predicate(value, i)
99
- except Exception as exn:
100
- observer.on_error(exn)
101
- return
102
- else:
103
- i += 1
104
-
105
- if running:
106
- observer.on_next(value)
70
+ source: Observable[_T],
71
+ predicate: PredicateIndexed[_T],
72
+ inclusive: bool = False,
73
+ ) -> Observable[_T]:
74
+ """Returns elements from an observable sequence as long as a
75
+ specified condition is true. The element's index is used in the
76
+ logic of the predicate function.
77
+
78
+ Examples:
79
+ >>> result = source.pipe(take_while_indexed(lambda x, i: i < 10))
80
+ >>> result = take_while_indexed(lambda x, i: i < 10)(source)
81
+
82
+ Args:
83
+ source: Source observable to take from.
84
+ predicate: A function to test each element with its index.
85
+ inclusive: Include the element that fails the predicate.
86
+
87
+ Returns:
88
+ An observable sequence that contains the elements from the
89
+ input sequence that occur before the element at which the
90
+ test no longer passes.
91
+ """
92
+
93
+ def subscribe(
94
+ observer: abc.ObserverBase[_T],
95
+ scheduler: abc.SchedulerBase | None = None,
96
+ ) -> abc.DisposableBase:
97
+ running = True
98
+ i = 0
99
+
100
+ def on_next(value: Any) -> None:
101
+ nonlocal running, i
102
+
103
+ with source.lock:
104
+ if not running:
105
+ return
106
+
107
+ try:
108
+ running = predicate(value, i)
109
+ except Exception as exn:
110
+ observer.on_error(exn)
111
+ return
107
112
  else:
108
- if inclusive:
109
- observer.on_next(value)
110
- observer.on_completed()
113
+ i += 1
111
114
 
112
- return source.subscribe(
113
- on_next, observer.on_error, observer.on_completed, scheduler=scheduler
114
- )
115
+ if running:
116
+ observer.on_next(value)
117
+ else:
118
+ if inclusive:
119
+ observer.on_next(value)
120
+ observer.on_completed()
115
121
 
116
- return Observable(subscribe)
122
+ return source.subscribe(
123
+ on_next, observer.on_error, observer.on_completed, scheduler=scheduler
124
+ )
117
125
 
118
- return take_while_indexed
126
+ return Observable(subscribe)
119
127
 
120
128
 
121
129
  __all__ = ["take_while_", "take_while_indexed_"]