def if_then(condition: Callable[[], bool], then_source: ObservableBase, else_source: ObservableBase = None) -> ObservableBase: """Determines whether an observable collection contains values. Example: 1 - res = rx.Observable.if(condition, obs1) 2 - res = rx.Observable.if(condition, obs1, obs2) Keyword parameters: condition -- The condition which determines if the then_source or else_source will be run. then_source -- The observable sequence or Promise that will be run if the condition function returns true. else_source -- [Optional] The observable sequence or Promise that will be run if the condition function returns False. If this is not provided, it defaults to rx.Observable.empty Returns an observable sequence which is either the then_source or else_source. """ else_source = else_source or Observable.empty() then_source = Observable.from_future(then_source) if is_future( then_source) else then_source else_source = Observable.from_future(else_source) if is_future( else_source) else else_source def factory(_: abc.Scheduler): return then_source if condition() else else_source return Observable.defer(factory)
def on_next(inner_source): d = SingleAssignmentDisposable() with self.lock: latest[0] += 1 _id = latest[0] has_latest[0] = True inner_subscription.disposable = d # Check if Future or Observable inner_source = Observable.from_future(inner_source) def on_next(x): if latest[0] == _id: observer.on_next(x) def on_error(e): if latest[0] == _id: observer.on_error(e) def on_completed(): if latest[0] == _id: has_latest[0] = False if is_stopped[0]: observer.on_completed() d.disposable = inner_source.subscribe(on_next, on_error, on_completed)
def projection(x, i): mapper_result = mapper(x) if mapper else mapper_indexed(x, i) if isinstance(mapper_result, collections.Iterable): result = Observable.from_(mapper_result) else: result = Observable.from_future(mapper_result) if is_future(mapper_result) else mapper_result return result
def take_until(source: ObservableBase, other: ObservableBase) -> ObservableBase: """Returns the values from the source observable sequence until the other observable sequence produces a value. Keyword arguments: other -- Observable sequence that terminates propagation of elements of the source sequence. Returns an observable sequence containing the elements of the source sequence up to the point the other sequence interrupted further propagation. """ other = Observable.from_future(other) if is_future(other) else other def subscribe(observer, scheduler=None): def on_completed(_): observer.on_completed() return CompositeDisposable( source.subscribe(observer), other.subscribe_(on_completed, observer.on_error, noop, scheduler)) return AnonymousObservable(subscribe)
def take_until(self, other): """Returns the values from the source observable sequence until the other observable sequence produces a value. Keyword arguments: other -- Observable sequence that terminates propagation of elements of the source sequence. Returns an observable sequence containing the elements of the source sequence up to the point the other sequence interrupted further propagation. """ source = self other = Observable.from_future(other) def subscribe(observer): def on_completed(x): observer.on_completed() return CompositeDisposable( source.subscribe(observer), other.subscribe(on_completed, observer.on_error, noop)) return AnonymousObservable(subscribe)
def take_until(self, other): """Returns the values from the source observable sequence until the other observable sequence produces a value. Keyword arguments: other -- Observable sequence that terminates propagation of elements of the source sequence. Returns an observable sequence containing the elements of the source sequence up to the point the other sequence interrupted further propagation. """ source = self other = Observable.from_future(other) def subscribe(observer): def on_completed(x): observer.on_completed() return CompositeDisposable( source.subscribe(observer), other.subscribe(on_completed, observer.on_error, noop) ) return AnonymousObservable(subscribe)
def subscribe(observer, scheduler=None): try: result = observable_factory(scheduler) except Exception as ex: return Observable.throw(ex).subscribe(observer) result = Observable.from_future(result) if is_future(result) else result return result.subscribe(observer, scheduler)
def subscribe(observer): try: result = observable_factory() except Exception as ex: return Observable.throw_exception(ex).subscribe(observer) result = Observable.from_future(result) return result.subscribe(observer)
def projection(x: Any, idx: int) -> Any: mapper_result = mapper(x) if isinstance(mapper_result, collections.abc.Iterable): result = Observable.from_(mapper_result) else: result = Observable.from_future( mapper_result) if is_future( mapper_result) else mapper_result return result.map(lambda y: result_mapper(x, y))
def factory(_) -> ObservableBase: try: result = sources[mapper()] except KeyError: result = default_source result = Observable.from_future(result) if is_future( result) else result return result
def func(i): source = sources[i] sad = SingleAssignmentDisposable() source = Observable.from_future(source) def on_next(x): queues[i].append(x) next(i) sad.disposable = source.subscribe(on_next, observer.on_error, lambda: done(i)) subscriptions[i] = sad
def projection(x: Any, idx: int) -> Any: mapper_result = mapper(x) if mapper else mapper_indexed(x, idx) if isinstance(mapper_result, collections.Iterable): result = Observable.from_(mapper_result) else: result = Observable.from_future(mapper_result) if is_future(mapper_result) else mapper_result if result_mapper: return result.map(lambda y: result_mapper(x, y)) else: return result.map(mapper_indexed=lambda y, i: result_mapper_indexed(x, y, i))
def on_error(exception): try: result = handler(exception) except Exception as ex: observer.on_error(ex) return result = Observable.from_future(result) d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = result.subscribe(observer)
def on_error(exception): try: result = handler(exception) except Exception as ex: # By design. pylint: disable=W0703 observer.on_error(ex) return result = Observable.from_future(result) if is_future(result) else result d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = result.subscribe(observer, scheduler)
def func(i): # subscribe to the ith input source = sources[i] sad = SingleAssignmentDisposable() source = Observable.from_future(source) def on_next(x): queues[i].append(x) next() sad.disposable = source.subscribe(on_next, observer.on_error, lambda: done(i)) subscriptions[i] = sad
def func(i): source = sources[i] sad = SingleAssignmentDisposable() source = Observable.from_future(source) if is_future( source) else source def on_next(x): queues[i].append(x) next(i) sad.disposable = source.subscribe_(on_next, observer.on_error, lambda: done(i), scheduler) subscriptions[i] = sad
def on_next(inner_source): inner_subscription = SingleAssignmentDisposable() group.add(inner_subscription) inner_source = Observable.from_future(inner_source) if is_future(inner_source) else inner_source def on_completed(): group.remove(inner_subscription) if is_stopped[0] and len(group) == 1: observer.on_completed() disposable = inner_source.subscribe_(observer.on_next, observer.on_error, on_completed, scheduler) inner_subscription.disposable = disposable
def while_do(condition, source: ObservableBase) -> ObservableBase: """Repeats source as long as condition holds emulating a while loop. Keyword arguments: condition -- The condition which determines if the source will be repeated. source -- The observable sequence that will be run if the condition function returns true. Returns an observable sequence which is repeated as long as the condition holds. """ source = Observable.from_future(source) if is_future(source) else source from .concat import concat return concat(Iterable.while_do(condition, source))
def on_next(inner_source): inner_subscription = SingleAssignmentDisposable() group.add(inner_subscription) inner_source = Observable.from_future(inner_source) def on_next(x): observer.on_next(x) def on_completed(): group.remove(inner_subscription) if is_stopped[0] and len(group) == 1: observer.on_completed() disposable = inner_source.subscribe(on_next, observer.on_error, on_completed) inner_subscription.disposable = disposable
def while_do(cls, condition, source): """Repeats source as long as condition holds emulating a while loop. Keyword arguments: :param types.FunctionType condition: The condition which determines if the source will be repeated. :param Observable source: The observable sequence that will be run if the condition function returns true. :returns: An observable sequence which is repeated as long as the condition holds. :rtype: Observable """ source = Observable.from_future(source) return Observable.concat(Enumerable.while_do(condition, source))
def on_next(inner_source): if not has_current[0]: has_current[0] = True inner_source = Observable.from_future(inner_source) inner_subscription = SingleAssignmentDisposable() g.add(inner_subscription) def on_completed_inner(): g.remove(inner_subscription) has_current[0] = False if is_stopped[0] and len(g) == 1: observer.on_completed() inner_subscription.disposable = inner_source.subscribe( observer.on_next, observer.on_error, on_completed_inner)
def action(this, state=None): try: source = next(sources) except StopIteration: observer.on_completed() return # Allow source to be a factory method taking an error source = source(state) if callable(source) else source current = Observable.from_future(source) d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe( observer.on_next, lambda ex: this(ex), this)
def while_do(cls, condition, source): """Repeats source as long as condition holds emulating a while loop. Arguments: condition (types.FunctionType): The condition which determines if the source will be repeated. source (Observable): The observable sequence that will be run if the condition function returns True. Returns: (Observable): An observable sequence which is repeated as long as the condition holds. """ source = Observable.from_future(source) return Observable.concat(Enumerable.while_do(condition, source))
def skip_until(self, other): """Returns the values from the source observable sequence only after the other observable sequence produces a value. other -- The observable sequence that triggers propagation of elements of the source sequence. Returns an observable sequence containing the elements of the source sequence starting from the point the other sequence triggered propagation. """ source = self other = Observable.from_future(other) def subscribe(observer): is_open = [False] def on_next(left): if is_open[0]: observer.on_next(left) def on_completed(): if is_open[0]: observer.on_completed() subs = source.subscribe(on_next, observer.on_error, on_completed) disposables = CompositeDisposable(subs) right_subscription = SingleAssignmentDisposable() disposables.add(right_subscription) def on_next2(x): is_open[0] = True right_subscription.dispose() def on_completed2(): right_subscription.dispose() right_subscription.disposable = other.subscribe( on_next2, observer.on_error, on_completed2) return disposables return AnonymousObservable(subscribe)
def action(scheduler, state=None): try: source = next(sources) except StopIteration: observer.on_completed() return # Allow source to be a factory method taking an error source = source(state) if callable(source) else source current = Observable.from_future(source) d = SingleAssignmentDisposable() subscription.disposable = d def on_resume(state=None): scheduler.schedule(action, state) d.disposable = current.subscribe(observer.on_next, on_resume, on_resume)
def start_async(function_async) -> ObservableBase: """Invokes the asynchronous function, surfacing the result through an observable sequence. Keyword arguments: function_async -- Asynchronous function which returns a Future to run. Returns an observable sequence exposing the function's result value, or an exception. """ try: future = function_async() except Exception as ex: return Observable.throw(ex) return Observable.from_future(future)
def start_async(cls, function_async): """Invokes the asynchronous function, surfacing the result through an observable sequence. Keyword arguments: :param types.FunctionType function_async: Asynchronous function which returns a Future to run. :returns: An observable sequence exposing the function's result value, or an exception. :rtype: Observable """ try: future = function_async() except Exception as ex: return Observable.throw(ex) return Observable.from_future(future)
def skip_until(self, other): """Returns the values from the source observable sequence only after the other observable sequence produces a value. other -- The observable sequence that triggers propagation of elements of the source sequence. Returns an observable sequence containing the elements of the source sequence starting from the point the other sequence triggered propagation. """ source = self other = Observable.from_future(other) def subscribe(observer): is_open = [False] def on_next(left): if is_open[0]: observer.on_next(left) def on_completed(): if is_open[0]: observer.on_completed() subs = source.subscribe(on_next, observer.on_error, on_completed) disposables = CompositeDisposable(subs) right_subscription = SingleAssignmentDisposable() disposables.add(right_subscription) def on_next2(x): is_open[0] = True right_subscription.dispose() def on_completed2(): right_subscription.dispose() right_subscription.disposable = other.subscribe(on_next2, observer.on_error, on_completed2) return disposables return AnonymousObservable(subscribe)
def on_next(inner_source): if not has_current[0]: has_current[0] = True inner_source = Observable.from_future(inner_source) inner_subscription = SingleAssignmentDisposable() g.add(inner_subscription) def on_completed_inner(): g.remove(inner_subscription) has_current[0] = False if is_stopped[0] and len(g) == 1: observer.on_completed() inner_subscription.disposable = inner_source.subscribe( observer.on_next, observer.on_error, on_completed_inner )
def amb(self, right_source): """Propagates the observable sequence that reacts first. Arguments: right_source (Observable): Second observable sequence. Returns: Observable: an observable sequence that surfaces either of the given sequences, whichever reacted first. """ left_source = self right_source = Observable.from_future(right_source) def subscribe(observer): choice = [None] left_choice = 'L' right_choice = 'R', left_subscription = SingleAssignmentDisposable() right_subscription = SingleAssignmentDisposable() def choice_left(): if not choice[0]: choice[0] = left_choice right_subscription.dispose() def choice_right(): if not choice[0]: choice[0] = right_choice left_subscription.dispose() def on_next_left(value): with self.lock: choice_left() if choice[0] == left_choice: observer.on_next(value) def on_error_left(err): with self.lock: choice_left() if choice[0] == left_choice: observer.on_error(err) def on_completed_left(): with self.lock: choice_left() if choice[0] == left_choice: observer.on_completed() ld = left_source.subscribe(on_next_left, on_error_left, on_completed_left) left_subscription.disposable = ld def on_next_right(value): with self.lock: choice_right() if choice[0] == right_choice: observer.on_next(value) def on_error_right(err): with self.lock: choice_right() if choice[0] == right_choice: observer.on_error(err) def on_completed_right(): with self.lock: choice_right() if choice[0] == right_choice: observer.on_completed() rd = right_source.subscribe(on_next_right, on_error_right, on_completed_right) right_subscription.disposable = rd return CompositeDisposable(left_subscription, right_subscription) return AnonymousObservable(subscribe)
def timeout(self, duetime, other=None, scheduler=None): """Returns the source observable sequence or the other observable sequence if duetime elapses. Example:: from datetime import datetime # As a date res = source.timeout(datetime.now()) # 5 seconds (5000 milliseconds) res = source.timeout(5000); # 5 seconds # As a date and timeout observable res = source.timeout(datetime.now(), rx.Observable.return_value(42)) # 5 seconds and timeout observable res = source.timeout(5000, rx.Observable.return_value(42)) # As a date and timeout observable res = source.timeout(datetime.now(), rx.Observable.return_value(42), rx.Scheduler.timeout) # 5 seconds and timeout observable res = source.timeout(5000, rx.Observable.return_value(42), rx.Scheduler.timeout) Keyword arguments: duetime (int, datetime.datetime): Absolute (specified as a :class:`datetime.datetime` object) or relative time (specified as an integer denoting milliseconds) when a timeout occurs. other (Observable): Sequence to return in case of a timeout. If not specified, a timeout error throwing sequence will be used. scheduler (Scheduler): Scheduler to run the timeout timers on. If not specified, the timeout scheduler is used. Returns: (Observable): The source sequence switching to the other sequence in case of a timeout. """ scheduler_method = None source = self other = other or Observable.throw_exception(Exception("Timeout")) other = Observable.from_future(other) scheduler = scheduler or timeout_scheduler if isinstance(duetime, datetime): scheduler_method = scheduler.schedule_absolute else: scheduler_method = scheduler.schedule_relative def subscribe(observer): switched = [False] _id = [0] original = SingleAssignmentDisposable() subscription = SerialDisposable() timer = SerialDisposable() subscription.disposable = original def create_timer(): my_id = _id[0] def action(scheduler, state=None): switched[0] = (_id[0] == my_id) timer_wins = switched[0] if timer_wins: subscription.disposable = other.subscribe(observer) timer.disposable = scheduler_method(duetime, action) create_timer() def on_next(x): on_next_wins = not switched[0] if on_next_wins: _id[0] += 1 observer.on_next(x) create_timer() def on_error(e): on_error_wins = not switched[0] if on_error_wins: _id[0] += 1 observer.on_error(e) def on_completed(): on_completed_wins = not switched[0] if on_completed_wins: _id[0] += 1 observer.on_completed() original.disposable = source.subscribe(on_next, on_error, on_completed) return CompositeDisposable(subscription, timer) return AnonymousObservable(subscribe)
def amb(self, right_source): """Propagates the observable sequence that reacts first. right_source Second observable sequence. returns an observable sequence that surfaces either of the given sequences, whichever reacted first. """ left_source = self right_source = Observable.from_future(right_source) def subscribe(observer): choice = [None] left_choice = 'L' right_choice = 'R', left_subscription = SingleAssignmentDisposable() right_subscription = SingleAssignmentDisposable() def choice_left(): if not choice[0]: choice[0] = left_choice right_subscription.dispose() def choice_right(): if not choice[0]: choice[0] = right_choice left_subscription.dispose() def on_next_left(value): with self.lock: choice_left() if choice[0] == left_choice: observer.on_next(value) def on_error_left(err): with self.lock: choice_left() if choice[0] == left_choice: observer.on_error(err) def on_completed_left(): with self.lock: choice_left() if choice[0] == left_choice: observer.on_completed() ld = left_source.subscribe(on_next_left, on_error_left, on_completed_left) left_subscription.disposable = ld def on_next_right(value): with self.lock: choice_right() if choice[0] == right_choice: observer.on_next(value) def on_error_right(err): with self.lock: choice_right() if choice[0] == right_choice: observer.on_error(err) def on_completed_right(): with self.lock: choice_right() if choice[0] == right_choice: observer.on_completed() rd = right_source.subscribe(on_next_right, on_error_right, on_completed_right) right_subscription.disposable = rd return CompositeDisposable(left_subscription, right_subscription) return AnonymousObservable(subscribe)
def _amb(left_source, right_source): right_source = Observable.from_future(right_source) if is_future( right_source) else right_source def subscribe(observer, scheduler=None): choice = [None] left_choice = 'L' right_choice = 'R' left_subscription = SingleAssignmentDisposable() right_subscription = SingleAssignmentDisposable() def choice_left(): if not choice[0]: choice[0] = left_choice right_subscription.dispose() def choice_right(): if not choice[0]: choice[0] = right_choice left_subscription.dispose() def on_next_left(value): with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_next(value) def on_error_left(err): with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_error(err) def on_completed_left(): with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_completed() lelf_d = left_source.subscribe_(on_next_left, on_error_left, on_completed_left, scheduler) left_subscription.disposable = lelf_d def send_right(value): with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_next(value) def on_error_right(err): with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_error(err) def on_completed_right(): with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_completed() right_d = right_source.subscribe_(send_right, on_error_right, on_completed_right, scheduler) right_subscription.disposable = right_d return CompositeDisposable(left_subscription, right_subscription) return AnonymousObservable(subscribe)
def timeout(source: ObservableBase, duetime: Union[int, datetime], other: ObservableBase = None) -> ObservableBase: """Returns the source observable sequence or the other observable sequence if duetime elapses. 1 - res = source.timeout(5000); # 5 seconds # As a date and timeout observable 2 - res = source.timeout(datetime(), Observable.return_value(42)) # 5 seconds and timeout observable 3 - res = source.timeout(5000, Observable.return_value(42)) # As a date and timeout observable Keyword arguments: duetime -- Absolute (specified as a datetime object) or relative time (specified as an integer denoting milliseconds) when a timeout occurs. other -- Sequence to return in case of a timeout. If not specified, a timeout error throwing sequence will be used. Returns the source sequence switching to the other sequence in case of a timeout. """ other = other or Observable.throw(Exception("Timeout")) other = Observable.from_future(other) if is_future(other) else other def subscribe(observer, scheduler=None): scheduler = scheduler or timeout_scheduler if isinstance(duetime, datetime): scheduler_method = scheduler.schedule_absolute else: scheduler_method = scheduler.schedule_relative switched = [False] _id = [0] original = SingleAssignmentDisposable() subscription = SerialDisposable() timer = SerialDisposable() subscription.disposable = original def create_timer(): my_id = _id[0] def action(scheduler, state=None): switched[0] = (_id[0] == my_id) timer_wins = switched[0] if timer_wins: subscription.disposable = other.subscribe( observer, scheduler) timer.disposable = scheduler_method(duetime, action) create_timer() def on_next(value): send_wins = not switched[0] if send_wins: _id[0] += 1 observer.on_next(value) create_timer() def on_error(error): on_error_wins = not switched[0] if on_error_wins: _id[0] += 1 observer.on_error(error) def on_completed(): on_completed_wins = not switched[0] if on_completed_wins: _id[0] += 1 observer.on_completed() original.disposable = source.subscribe_(on_next, on_error, on_completed, scheduler) return CompositeDisposable(subscription, timer) return AnonymousObservable(subscribe)
def _amb(left_source, right_source): """Propagates the observable sequence that reacts first. right_source Second observable sequence. returns an observable sequence that surfaces either of the given sequences, whichever reacted first. """ right_source = Observable.from_future(right_source) if is_future(right_source) else right_source def subscribe(observer, scheduler=None): choice = [None] left_choice = 'L' right_choice = 'R', left_subscription = SingleAssignmentDisposable() right_subscription = SingleAssignmentDisposable() def choice_left(): if not choice[0]: choice[0] = left_choice right_subscription.dispose() def choice_right(): if not choice[0]: choice[0] = right_choice left_subscription.dispose() def on_next_left(value): with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_next(value) def on_error_left(err): with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_error(err) def on_completed_left(): with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_completed() lelf_d = left_source.subscribe_(on_next_left, on_error_left, on_completed_left, scheduler) left_subscription.disposable = lelf_d def send_right(value): with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_next(value) def on_error_right(err): with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_error(err) def on_completed_right(): with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_completed() right_d = right_source.subscribe_(send_right, on_error_right, on_completed_right, scheduler) right_subscription.disposable = right_d return CompositeDisposable(left_subscription, right_subscription) return AnonymousObservable(subscribe)
def timeout(self, duetime, other=None, scheduler=None): """Returns the source observable sequence or the other observable sequence if duetime elapses. 1 - res = source.timeout(new Date()); # As a date 2 - res = source.timeout(5000); # 5 seconds # As a date and timeout observable 3 - res = source.timeout(datetime(), rx.Observable.return_value(42)) # 5 seconds and timeout observable 4 - res = source.timeout(5000, rx.Observable.return_value(42)) # As a date and timeout observable 5 - res = source.timeout(datetime(), rx.Observable.return_value(42), rx.Scheduler.timeout) # 5 seconds and timeout observable 6 - res = source.timeout(5000, rx.Observable.return_value(42), rx.Scheduler.timeout) Keyword arguments: :param datetime|int duetime: Absolute (specified as a datetime object) or relative time (specified as an integer denoting milliseconds) when a timeout occurs. :param Observable other: Sequence to return in case of a timeout. If not specified, a timeout error throwing sequence will be used. :param Scheduler scheduler: Scheduler to run the timeout timers on. If not specified, the timeout scheduler is used. :returns: The source sequence switching to the other sequence in case of a timeout. :rtype: Observable """ scheduler_method = None source = self other = other or Observable.throw_exception(Exception("Timeout")) other = Observable.from_future(other) scheduler = scheduler or timeout_scheduler if isinstance(duetime, datetime): scheduler_method = scheduler.schedule_absolute else: scheduler_method = scheduler.schedule_relative def subscribe(observer): switched = [False] _id = [0] original = SingleAssignmentDisposable() subscription = SerialDisposable() timer = SerialDisposable() subscription.disposable = original def create_timer(): my_id = _id[0] def action(scheduler, state=None): switched[0] = (_id[0] == my_id) timer_wins = switched[0] if timer_wins: subscription.disposable = other.subscribe(observer) timer.disposable = scheduler_method(duetime, action) create_timer() def on_next(x): on_next_wins = not switched[0] if on_next_wins: _id[0] += 1 observer.on_next(x) create_timer() def on_error(e): on_error_wins = not switched[0] if on_error_wins: _id[0] += 1 observer.on_error(e) def on_completed(): on_completed_wins = not switched[0] if on_completed_wins: _id[0] += 1 observer.on_completed() original.disposable = source.subscribe(on_next, on_error, on_completed) return CompositeDisposable(subscription, timer) return AnonymousObservable(subscribe)