def skip_until_( other: Union[Observable[Any], "Future[Any]"] ) -> Callable[[Observable[_T]], Observable[_T]]: """Returns the values from the source observable sequence only after the other observable sequence produces a value. Args: 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. """ if isinstance(other, Future): obs: Observable[Any] = from_future(other) else: obs = other def skip_until(source: Observable[_T]) -> Observable[_T]: def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ): is_open = [False] def on_next(left: _T) -> None: if is_open[0]: observer.on_next(left) def on_completed() -> None: if is_open[0]: observer.on_completed() subs = source.subscribe( on_next, observer.on_error, on_completed, scheduler=scheduler ) subscriptions = CompositeDisposable(subs) right_subscription = SingleAssignmentDisposable() subscriptions.add(right_subscription) def on_next2(x: Any) -> None: is_open[0] = True right_subscription.dispose() def on_completed2(): right_subscription.dispose() right_subscription.disposable = obs.subscribe( on_next2, observer.on_error, on_completed2, scheduler=scheduler ) return subscriptions return Observable(subscribe) return skip_until
def on_next(inner_source: Union[Observable[_T], "Future[_T]"]) -> None: if not has_current[0]: has_current[0] = True inner_source = ( reactivex.from_future(inner_source) if isinstance(inner_source, Future) else 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, scheduler=scheduler, )
def on_next(inner_source: Union[Observable[_T], "Future[_T]"]) -> None: nonlocal source d = SingleAssignmentDisposable() with source.lock: latest[0] += 1 _id = latest[0] has_latest[0] = True inner_subscription.disposable = d # Check if Future or Observable if isinstance(inner_source, Future): obs = from_future(inner_source) else: obs = inner_source def on_next(x: Any) -> None: if latest[0] == _id: observer.on_next(x) def on_error(e: Exception) -> None: if latest[0] == _id: observer.on_error(e) def on_completed() -> None: if latest[0] == _id: has_latest[0] = False if is_stopped[0]: observer.on_completed() d.disposable = obs.subscribe( on_next, on_error, on_completed, scheduler=scheduler )
def start_async_(function_async: Callable[[], "Future[_T]"]) -> Observable[_T]: try: future = function_async() except Exception as ex: # pylint: disable=broad-except return throw(ex) return from_future(future)
def if_then_( condition: Callable[[], bool], then_source: Union[Observable[_T], "Future[_T]"], else_source: Union[None, Observable[_T], "Future[_T]"] = None, ) -> Observable[_T]: """Determines whether an observable collection contains values. Example: 1 - res = reactivex.if_then(condition, obs1) 2 - res = reactivex.if_then(condition, obs1, obs2) Args: 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 reactivex.empty Returns: An observable sequence which is either the then_source or else_source. """ else_source_: Union[Observable[_T], "Future[_T]"] = else_source or reactivex.empty() then_source = ( reactivex.from_future(then_source) if isinstance(then_source, Future) else then_source ) else_source_ = ( reactivex.from_future(else_source_) if isinstance(else_source_, Future) else else_source_ ) def factory(_: abc.SchedulerBase) -> Union[Observable[_T], "Future[_T]"]: return then_source if condition() else else_source_ return reactivex.defer(factory)
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)
def projection(x: _T1, i: int) -> Observable[Any]: mapper_result: Any = (mapper(x) if mapper else mapper_indexed(x, i) if mapper_indexed else identity) if isinstance(mapper_result, Future): result: Observable[Any] = from_future( cast("Future[Any]", mapper_result)) elif isinstance(mapper_result, Observable): result = mapper_result else: result = from_(mapper_result) return result
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)
def factory(_: abc.SchedulerBase) -> Observable[_T]: try: result: Union[Observable[_T], "Future[_T]"] = sources[mapper()] except KeyError: result = default_source_ if isinstance(result, Future): result_: Observable[_T] = from_future(result) else: result_ = result return result_
async def go(): future = Future() source = reactivex.from_future(future) def on_next(x): success[0] = False def on_error(err): success[1] = type(err) == asyncio.CancelledError def on_completed(): success[2] = False source.subscribe(on_next, on_error, on_completed) future.cancel()
def func(i: int) -> None: source: Observable[Any] = sources[i] if isinstance(source, Future): source = from_future(source) sad = SingleAssignmentDisposable() def on_next(x: Any) -> None: queues[i].append(x) next_(i) sad.disposable = source.subscribe(on_next, observer.on_error, lambda: completed(i), scheduler=scheduler) subscriptions[i] = sad
async def go(): future = Future() future.set_result(42) source = reactivex.from_future(future) def on_next(x): success[0] = x == 42 def on_error(err): success[1] = False def on_completed(): success[2] = True source.subscribe(on_next, on_error, on_completed)
async def go(): error = Exception("woops") future = Future() future.set_exception(error) source = reactivex.from_future(future) def on_next(x): success[0] = False def on_error(err): success[1] = str(err) == str(error) def on_completed(): success[2] = False source.subscribe(on_next, on_error, on_completed)
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 take_until_( other: Union[Observable[_T], "Future[_T]"] ) -> Callable[[Observable[_T]], Observable[_T]]: if isinstance(other, Future): obs: Observable[_T] = from_future(other) else: obs = other 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) return take_until
def action(scheduler: abc.SchedulerBase, state: Optional[Exception] = None) -> 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 = (reactivex.from_future(source) if isinstance( source, Future) else source) d = SingleAssignmentDisposable() subscription.disposable = d def on_resume(state: Optional[Exception] = None) -> None: scheduler.schedule(action, state) d.disposable = current.subscribe(observer.on_next, on_resume, on_resume, scheduler=scheduler)
async def main(): async with InfluxDBClientAsync(url='http://localhost:8086', token='my-token', org='my-org') as client: write_api = client.write_api() """ Async write """ async def async_write(batch): """ Prepare async task """ await write_api.write(bucket='my-bucket', record=batch) return batch """ Prepare batches from generator """ batches = rx \ .from_iterable(csv_to_generator('vix-daily.csv')) \ .pipe(ops.buffer_with_count(500)) \ .pipe(ops.map(lambda batch: rx.from_future(asyncio.ensure_future(async_write(batch)))), ops.merge_all()) done = asyncio.Future() """ Write batches by subscribing to Rx generator """ batches.subscribe( on_next=lambda batch: print(f'Written batch... {len(batch)}'), on_error=lambda ex: print(f'Unexpected error: {ex}'), on_completed=lambda: done.set_result(0), scheduler=AsyncIOScheduler(asyncio.get_event_loop())) """ Wait to finish all writes """ await done
def timeout_( duetime: typing.AbsoluteOrRelativeTime, other: Optional[Union[Observable[_T], "Future[_T]"]] = None, scheduler: Optional[abc.SchedulerBase] = None, ) -> Callable[[Observable[_T]], Observable[_T]]: other = other or throw(Exception("Timeout")) if isinstance(other, Future): obs = from_future(other) else: obs = other def timeout(source: Observable[_T]) -> Observable[_T]: """Returns the source observable sequence or the other observable sequence if duetime elapses. Examples: >>> res = timeout(source) Args: source: Source observable to timeout Returns: An obserable sequence switching to the other sequence in case of a timeout. """ def subscribe( observer: abc.ObserverBase[_T], scheduler_: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) switched = [False] _id = [0] original = SingleAssignmentDisposable() subscription = SerialDisposable() timer = SerialDisposable() subscription.disposable = original def create_timer() -> None: my_id = _id[0] def action(scheduler: abc.SchedulerBase, state: Any = None): switched[0] = _id[0] == my_id timer_wins = switched[0] if timer_wins: subscription.disposable = obs.subscribe( observer, scheduler=scheduler) if isinstance(duetime, datetime): timer.disposable = _scheduler.schedule_absolute( duetime, action) else: timer.disposable = _scheduler.schedule_relative( duetime, action) create_timer() def on_next(value: _T) -> None: send_wins = not switched[0] if send_wins: _id[0] += 1 observer.on_next(value) create_timer() def on_error(error: Exception) -> None: on_error_wins = not switched[0] if on_error_wins: _id[0] += 1 observer.on_error(error) def on_completed() -> None: 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=scheduler_) return CompositeDisposable(subscription, timer) return Observable(subscribe) return timeout
def amb_( right_source: Union[Observable[_T], "Future[_T]"] ) -> Callable[[Observable[_T]], Observable[_T]]: if isinstance(right_source, Future): obs: Observable[_T] = from_future(right_source) else: obs = right_source def amb(left_source: Observable[_T]) -> Observable[_T]: def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: choice: List[Optional[str]] = [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: _T) -> None: with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_next(value) def on_error_left(err: Exception) -> None: with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_error(err) def on_completed_left() -> None: with left_source.lock: choice_left() if choice[0] == left_choice: observer.on_completed() left_d = left_source.subscribe(on_next_left, on_error_left, on_completed_left, scheduler=scheduler) left_subscription.disposable = left_d def send_right(value: _T) -> None: with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_next(value) def on_error_right(err: Exception) -> None: with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_error(err) def on_completed_right() -> None: with left_source.lock: choice_right() if choice[0] == right_choice: observer.on_completed() right_d = obs.subscribe(send_right, on_error_right, on_completed_right, scheduler=scheduler) right_subscription.disposable = right_d return CompositeDisposable(left_subscription, right_subscription) return Observable(subscribe) return amb