def variance(source: Observable) -> Observable: """ Returns the statistical variance of the numerical emissions. The sequence must be finite. """ squared_values = ( source.to_list().flat_map(lambda l: Observable.from_(l).average( ).flat_map(lambda avg: Observable.from_(l).map(lambda i: i - avg) )).map(lambda i: i * i).publish().auto_connect(2)) return Observable.zip(squared_values.sum(), squared_values.count(), lambda sum, ct: sum / (ct - 1))
def return_value_( value: _T, scheduler: Optional[abc.SchedulerBase] = None) -> Observable[_T]: """Returns an observable sequence that contains a single element, using the specified scheduler to send out observer messages. There is an alias called 'just'. Examples: >>> res = return(42) >>> res = return(42, rx.Scheduler.timeout) Args: value: Single element in the resulting observable sequence. Returns: An observable sequence containing the single specified element. """ def subscribe( observer: abc.ObserverBase[_T], scheduler_: Optional[abc.SchedulerBase] = None ) -> abc.DisposableBase: _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton( ) def action(scheduler: abc.SchedulerBase, state: Any = None) -> None: observer.on_next(value) observer.on_completed() return _scheduler.schedule(action) return Observable(subscribe)
def take_until_with_time(source: Observable[_T]) -> Observable[_T]: """Takes elements for the specified duration until the specified end time, using the specified scheduler to run timers. Examples: >>> res = take_until_with_time(source) Args: source: Source observale to take elements from. Returns: An observable sequence with the elements taken until the specified end time. """ def subscribe( observer: abc.ObserverBase[_T], scheduler_: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) def action(scheduler: abc.SchedulerBase, state: Any = None): observer.on_completed() if isinstance(end_time, datetime): task = _scheduler.schedule_absolute(end_time, action) else: task = _scheduler.schedule_relative(end_time, action) return CompositeDisposable( task, source.subscribe(observer, scheduler=scheduler_)) return Observable(subscribe)
def multicast( source: Observable[_TSource], ) -> Union[Observable[_TResult], ConnectableObservable[_TSource]]: if subject_factory: def subscribe( observer: abc.ObserverBase[_TResult], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: assert subject_factory connectable = source.pipe( ops.multicast(subject=subject_factory(scheduler))) assert mapper subscription = mapper(connectable).subscribe( observer, scheduler=scheduler) return CompositeDisposable(subscription, connectable.connect(scheduler)) return Observable(subscribe) if not subject: raise ValueError("multicast: Subject cannot be None") ret: ConnectableObservable[_TSource] = ConnectableObservable( source, subject) return ret
def map(source: Observable[_T1]) -> Observable[_T2]: """Partially applied map operator. Project each element of an observable sequence into a new form by incorporating the element's index. Example: >>> map(source) Args: source: The observable source to transform. Returns: Returns an observable sequence whose elements are the result of invoking the transform function on each element of the source. """ def subscribe( obv: abc.ObserverBase[_T2], scheduler: Optional[abc.SchedulerBase] = None ) -> abc.DisposableBase: def on_next(value: _T1) -> None: try: result = _mapper(value) except Exception as err: # pylint: disable=broad-except obv.on_error(err) else: obv.on_next(result) return source.subscribe( on_next, obv.on_error, obv.on_completed, scheduler=scheduler ) return Observable(subscribe)
def element_at_or_default(source: Observable[_T]) -> Observable[_T]: def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: index_ = index def on_next(x: _T) -> None: nonlocal index_ found = False with source.lock: if index_: index_ -= 1 else: found = True if found: observer.on_next(x) observer.on_completed() def on_completed(): if not has_default: observer.on_error(ArgumentOutOfRangeException()) else: observer.on_next(cast(_T, default_value)) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed, scheduler=scheduler) return Observable(subscribe)
def observable_timer_timespan_and_period( duetime: typing.RelativeTime, period: typing.RelativeTime, scheduler: Optional[abc.SchedulerBase] = None, ) -> Observable[int]: if duetime == period: def subscribe( observer: abc.ObserverBase[int], scheduler_: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: _scheduler: abc.SchedulerBase = (scheduler or scheduler_ or TimeoutScheduler.singleton()) def action(count: Optional[int] = None) -> Optional[int]: if count is not None: observer.on_next(count) return count + 1 return None if not isinstance(_scheduler, PeriodicScheduler): raise ValueError("Sceduler must be PeriodicScheduler") return _scheduler.schedule_periodic(period, action, state=0) return Observable(subscribe) return observable_timer_duetime_and_period(duetime, period, scheduler)
def materialize(source: Observable[_T]) -> Observable[Notification[_T]]: """Partially applied materialize operator. Materializes the implicit notifications of an observable sequence as explicit notification values. Args: source: Source observable to materialize. Returns: An observable sequence containing the materialized notification values from the source sequence. """ def subscribe( observer: abc.ObserverBase[Notification[_T]], scheduler: Optional[abc.SchedulerBase] = None, ): def on_next(value: _T) -> None: observer.on_next(OnNext(value)) def on_error(error: Exception) -> None: observer.on_next(OnError(error)) observer.on_completed() def on_completed() -> None: observer.on_next(OnCompleted()) observer.on_completed() return source.subscribe(on_next, on_error, on_completed, scheduler=scheduler) return Observable(subscribe)
def last_or_default_async( source: Observable[_T], has_default: bool = False, default_value: Optional[_T] = None, ) -> Observable[Optional[_T]]: def subscribe( observer: abc.ObserverBase[Optional[_T]], scheduler: Optional[abc.SchedulerBase] = None, ): value = [default_value] seen_value = [False] def on_next(x: _T) -> None: value[0] = x seen_value[0] = True def on_completed(): if not seen_value[0] and not has_default: observer.on_error(SequenceContainsNoElementsError()) else: observer.on_next(value[0]) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed, scheduler=scheduler) return Observable(subscribe)
def take_until(source: Observable[_T]) -> Observable[_T]: """Returns the values from the source observable sequence until the other observable sequence produces a value. Args: source: The source observable sequence. Returns: An observable sequence containing the elements of the source sequence up to the point the other sequence interrupted further propagation. """ def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: def on_completed(_: _T) -> None: observer.on_completed() return CompositeDisposable( source.subscribe(observer, scheduler=scheduler), obs.subscribe( on_completed, observer.on_error, noop, scheduler=scheduler ), ) return Observable(subscribe)
def do_after_terminate(source: Observable[Any], after_terminate: typing.Action): """Invokes an action after an on_complete() or on_error() event. This can be helpful for debugging, logging, and other side effects when completion or an error terminates an operation on_terminate -- Action to invoke after on_complete or throw is called """ def subscribe( observer: abc.ObserverBase[Any], scheduler: Optional[abc.SchedulerBase] = None ) -> abc.DisposableBase: def on_completed(): observer.on_completed() try: after_terminate() except Exception as err: # pylint: disable=broad-except observer.on_error(err) def on_error(exception: Exception) -> None: observer.on_error(exception) try: after_terminate() except Exception as err: # pylint: disable=broad-except observer.on_error(err) return source.subscribe(observer.on_next, on_error, on_completed, scheduler=scheduler) return Observable(subscribe)
def do_on_dispose(source: Observable[Any], on_dispose: typing.Action): """Invokes an action on disposal. This can be helpful for debugging, logging, and other side effects on the disposal of an operation. Args: on_dispose: Action to invoke on disposal """ class OnDispose(abc.DisposableBase): def dispose(self) -> None: on_dispose() def subscribe( observer: abc.ObserverBase[Any], scheduler: Optional[abc.SchedulerBase] = None ) -> abc.DisposableBase: composite_disposable = CompositeDisposable() composite_disposable.add(OnDispose()) subscription = source.subscribe( observer.on_next, observer.on_error, observer.on_completed, scheduler=scheduler, ) composite_disposable.add(subscription) return composite_disposable return Observable(subscribe)
def skip_last_with_time(source: Observable[_T]) -> Observable[_T]: def subscribe( observer: abc.ObserverBase[_T], scheduler_: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: nonlocal duration _scheduler: abc.SchedulerBase = (scheduler or scheduler_ or TimeoutScheduler.singleton()) duration = _scheduler.to_timedelta(duration) q: List[Dict[str, Any]] = [] def on_next(x: _T) -> None: now = _scheduler.now q.append({"interval": now, "value": x}) while q and now - q[0]["interval"] >= duration: observer.on_next(q.pop(0)["value"]) def on_completed() -> None: now = _scheduler.now while q and now - q[0]["interval"] >= duration: observer.on_next(q.pop(0)["value"]) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed, scheduler=_scheduler) return Observable(subscribe)
def _buffer_by_bytes_count(source: Observable) -> Observable: def subscribe(observer, scheduler=None): observer.buffer = [] def on_next(current): observer.buffer.append(current) # Emit new batch if the buffer size is greater then boundary if (_buffer_bytes_size(observer.buffer) + len(current)) >= bytes_count: # emit batch observer.on_next(observer.buffer) observer.buffer = [] def on_error(exception): observer.buffer = [] observer.on_error(exception) def on_completed(): if len(observer.buffer) >= 0: # flush rest of buffer observer.on_next(observer.buffer) observer.buffer = [] observer.on_completed() return source.subscribe(on_next, on_error, on_completed, scheduler=scheduler) return Observable(subscribe)
def time_interval(source: Observable[_T]) -> Observable[TimeInterval[_T]]: """Records the time interval between consecutive values in an observable sequence. >>> res = time_interval(source) Return: An observable sequence with time interval information on values. """ def subscribe( observer: abc.ObserverBase[TimeInterval[_T]], scheduler_: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) last = _scheduler.now def mapper(value: _T) -> TimeInterval[_T]: nonlocal last now = _scheduler.now span = now - last last = now return TimeInterval(value=value, interval=span) return source.pipe(ops.map(mapper)).subscribe(observer, scheduler=_scheduler) return Observable(subscribe)
def finally_action(source: Observable[_T]) -> Observable[_T]: """Invokes a specified action after the source observable sequence terminates gracefully or exceptionally. Example: res = finally(source) Args: source: Observable sequence. Returns: An observable sequence with the action-invoking termination behavior applied. """ def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: try: subscription = source.subscribe(observer, scheduler=scheduler) except Exception: action() raise def dispose(): try: subscription.dispose() finally: action() return Disposable(dispose) return Observable(subscribe)
def filter(source: Observable[_T]) -> Observable[_T]: """Partially applied filter operator. Filters the elements of an observable sequence based on a predicate. Example: >>> filter(source) Args: source: Source observable to filter. Returns: A filtered observable sequence. """ def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase]) -> abc.DisposableBase: def on_next(value: _T): try: should_run = predicate(value) except Exception as ex: # pylint: disable=broad-except observer.on_error(ex) return if should_run: observer.on_next(value) return source.subscribe(on_next, observer.on_error, observer.on_completed, scheduler=scheduler) return Observable(subscribe)
def find_value(source: Observable[_T]) -> Observable[Union[_T, int, None]]: def subscribe( observer: abc.ObserverBase[Union[_T, int, None]], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: index = 0 def on_next(x: _T) -> None: nonlocal index should_run = False try: should_run = predicate(x, index, source) except Exception as ex: # pylint: disable=broad-except observer.on_error(ex) return if should_run: observer.on_next(index if yield_index else x) observer.on_completed() else: index += 1 def on_completed(): observer.on_next(-1 if yield_index else None) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed, scheduler=scheduler) return Observable(subscribe)
def skip(source: Observable[_T]) -> Observable[_T]: """The skip operator. Bypasses a specified number of elements in an observable sequence and then returns the remaining elements. Args: source: The source observable. Returns: An observable sequence that contains the elements that occur after the specified index in the input sequence. """ def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ): remaining = count def on_next(value: _T) -> None: nonlocal remaining if remaining <= 0: observer.on_next(value) else: remaining -= 1 return source.subscribe(on_next, observer.on_error, observer.on_completed, scheduler=scheduler) return Observable(subscribe)
def to_iterable(source: Observable[_T]) -> Observable[List[_T]]: """Creates an iterable from an observable sequence. Returns: An observable sequence containing a single element with an iterable containing all the elements of the source sequence. """ def subscribe( observer: abc.ObserverBase[List[_T]], scheduler: Optional[abc.SchedulerBase] = None, ): nonlocal source queue: List[_T] = [] def on_next(item: _T): queue.append(item) def on_completed(): nonlocal queue observer.on_next(queue) queue = [] observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed, scheduler=scheduler) return Observable(subscribe)
def catch_handler( source: Observable[_T], handler: Callable[[Exception, Observable[_T]], Union[Observable[_T], "Future[_T]"]], ) -> Observable[_T]: def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None ) -> abc.DisposableBase: d1 = SingleAssignmentDisposable() subscription = SerialDisposable() subscription.disposable = d1 def on_error(exception: Exception) -> None: try: result = handler(exception, source) except Exception as ex: # By design. pylint: disable=W0703 observer.on_error(ex) return result = (reactivex.from_future(result) if isinstance( result, Future) else result) d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = result.subscribe(observer, scheduler=scheduler) d1.disposable = source.subscribe(observer.on_next, on_error, observer.on_completed, scheduler=scheduler) return subscription return Observable(subscribe)
def defer_( factory: Callable[[abc.SchedulerBase], Union[Observable[_T], "Future[_T]"]] ) -> Observable[_T]: """Returns an observable sequence that invokes the specified factory function whenever a new observer subscribes. Example: >>> res = defer(lambda scheduler: of(1, 2, 3)) Args: observable_factory: Observable factory function to invoke for each observer that subscribes to the resulting sequence. The factory takes a single argument, the scheduler used. Returns: An observable sequence whose observers trigger an invocation of the given observable factory function. """ def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None ) -> abc.DisposableBase: try: result = factory(scheduler or ImmediateScheduler.singleton()) except Exception as ex: # By design. pylint: disable=W0703 return throw(ex).subscribe(observer) result = from_future(result) if isinstance(result, Future) else result return result.subscribe(observer, scheduler=scheduler) return Observable(subscribe)
def function(*args: Any) -> Observable[Any]: arguments = list(args) def subscribe( observer: abc.ObserverBase[Any], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: def handler(*args: Any) -> None: results = list(args) if mapper: try: results = mapper(args) except Exception as err: # pylint: disable=broad-except observer.on_error(err) return observer.on_next(results) else: if len(results) <= 1: observer.on_next(*results) else: observer.on_next(results) observer.on_completed() arguments.append(handler) func(*arguments) return Disposable() return Observable(subscribe)
def single_or_default_async(source: Observable[_T]) -> Observable[_T]: def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ): value = cast(_T, default_value) seen_value = False def on_next(x: _T): nonlocal value, seen_value if seen_value: observer.on_error( Exception("Sequence contains more than one element") ) else: value = x seen_value = True def on_completed(): if not seen_value and not has_default: observer.on_error(SequenceContainsNoElementsError()) else: observer.on_next(value) observer.on_completed() return source.subscribe( on_next, observer.on_error, on_completed, scheduler=scheduler ) return Observable(subscribe)
def observe_on(source: Observable[_T]) -> Observable[_T]: """Wraps the source sequence in order to run its observer callbacks on the specified scheduler. This only invokes observer callbacks on a scheduler. In case the subscription and/or unsubscription actions have side-effects that require to be run on a scheduler, use subscribe_on. Args: source: Source observable. Returns: Returns the source sequence whose observations happen on the specified scheduler. """ def subscribe( observer: abc.ObserverBase[_T], subscribe_scheduler: Optional[abc.SchedulerBase] = None, ): return source.subscribe(ObserveOnObserver(scheduler, observer), scheduler=subscribe_scheduler) return Observable(subscribe)
def range_( start: int, stop: Optional[int] = None, step: Optional[int] = None, scheduler: Optional[abc.SchedulerBase] = None, ) -> Observable[int]: """Generates an observable sequence of integral numbers within a specified range, using the specified scheduler to send out observer messages. Examples: >>> res = range(10) >>> res = range(0, 10) >>> res = range(0, 10, 1) Args: start: The value of the first integer in the sequence. stop: [Optional] Generate number up to (exclusive) the stop value. Default is `sys.maxsize`. step: [Optional] The step to be used (default is 1). scheduler: The scheduler to schedule the values on. Returns: An observable sequence that contains a range of sequential integral numbers. """ _stop: int = maxsize if stop is None else stop _step: int = 1 if step is None else step if step is None and stop is None: range_t = range(start) elif step is None: range_t = range(start, _stop) else: range_t = range(start, _stop, _step) def subscribe( observer: abc.ObserverBase[int], scheduler_: Optional[abc.SchedulerBase] = None ) -> abc.DisposableBase: nonlocal range_t _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton() sd = MultipleAssignmentDisposable() def action( scheduler: abc.SchedulerBase, iterator: Optional[Iterator[int]] ) -> None: try: assert iterator observer.on_next(next(iterator)) sd.disposable = _scheduler.schedule(action, state=iterator) except StopIteration: observer.on_completed() sd.disposable = _scheduler.schedule(action, iter(range_t)) return sd return Observable(subscribe)
def mode(source: Observable[Any]) -> Observable[Any]: """ Returns the most frequently emitted value (or "values" if they have the same number of occurrences). The sequence must be finite. """ return (source.group_by(lambda v: v).flat_map( lambda grp: grp.count().map(lambda ct: (grp.key, ct))).to_sorted_list( lambda t: t[1], reverse=True).flat_map(lambda l: Observable.from_( l).take_while(lambda t: t[1] == l[0][1])).map(lambda t: t[0]))
def distinct_until_changed(source: Observable[_T]) -> Observable[_T]: """Returns an observable sequence that contains only distinct contiguous elements according to the key_mapper and the comparer. Examples: >>> op = distinct_until_changed(); >>> op = distinct_until_changed(lambda x: x.id) >>> op = distinct_until_changed(lambda x: x.id, lambda x, y: x == y) Args: key_mapper: [Optional] A function to compute the comparison key for each element. If not provided, it projects the value. comparer: [Optional] Equality comparer for computed key values. If not provided, defaults to an equality comparer function. Returns: An observable sequence only containing the distinct contiguous elements, based on a computed key value, from the source sequence. """ def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: has_current_key = False current_key: _TKey = cast(_TKey, None) def on_next(value: _T) -> None: nonlocal has_current_key, current_key comparer_equals = False try: key = key_mapper_(value) except Exception as exception: # pylint: disable=broad-except observer.on_error(exception) return if has_current_key: try: comparer_equals = comparer_(current_key, key) except Exception as exception: # pylint: disable=broad-except observer.on_error(exception) return if not has_current_key or not comparer_equals: has_current_key = True current_key = key observer.on_next(value) return source.subscribe(on_next, observer.on_error, observer.on_completed, scheduler=scheduler) return Observable(subscribe)
def merge_all(source: Observable[Observable[_T]]) -> Observable[_T]: """Partially applied merge_all operator. Merges an observable sequence of observable sequences into an observable sequence. Args: source: Source observable to merge. Returns: The observable sequence that merges the elements of the inner sequences. """ def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ): group = CompositeDisposable() is_stopped = [False] m = SingleAssignmentDisposable() group.add(m) def on_next(inner_source: Union[Observable[_T], "Future[_T]"]): inner_subscription = SingleAssignmentDisposable() group.add(inner_subscription) inner_source = (from_future(inner_source) if isinstance( inner_source, Future) else inner_source) @synchronized(source.lock) def on_completed(): group.remove(inner_subscription) if is_stopped[0] and len(group) == 1: observer.on_completed() on_next: typing.OnNext[_T] = synchronized(source.lock)( observer.on_next) on_error = synchronized(source.lock)(observer.on_error) subscription = inner_source.subscribe(on_next, on_error, on_completed, scheduler=scheduler) inner_subscription.disposable = subscription def on_completed(): is_stopped[0] = True if len(group) == 1: observer.on_completed() m.disposable = source.subscribe(on_next, observer.on_error, on_completed, scheduler=scheduler) return group return Observable(subscribe)
def add_ref(xs: "Observable[_T]", r: RefCountDisposable) -> "Observable[_T]": from reactivex import Observable def subscribe( observer: abc.ObserverBase[Any], scheduler: Optional[abc.SchedulerBase] = None ) -> abc.DisposableBase: return CompositeDisposable(r.disposable, xs.subscribe(observer)) return Observable(subscribe)