def subscribe(observer, scheduler=None): delays = CompositeDisposable() at_end = [False] def done(): if (at_end[0] and delays.length == 0): observer.on_completed() subscription = SerialDisposable() def start(): def on_next(x): try: delay = mapper(x) except Exception as error: observer.on_error(error) return d = SingleAssignmentDisposable() delays.add(d) def on_next(_): observer.on_next(x) delays.remove(d) done() def on_completed(): observer.on_next(x) delays.remove(d) done() d.disposable = delay.subscribe_(on_next, observer.on_error, on_completed, scheduler) def on_completed(): at_end[0] = True subscription.dispose() done() subscription.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) if not sub_delay: start() else: subscription.disposable(sub_delay.subscribe_( lambda _: start(), observer.on_error, start)) return CompositeDisposable(subscription, delays)
def subscribe(observer, scheduler=None): scheduler = scheduler or current_thread_scheduler subscription = SerialDisposable() cancelable = SerialDisposable() last_exception = [None] is_disposed = [] def action(action1, state=None): def on_error(exn): last_exception[0] = exn cancelable.disposable = scheduler.schedule(action) if is_disposed: return try: current = next(sources) except StopIteration: if last_exception[0]: observer.on_error(last_exception[0]) else: observer.on_completed() except Exception as ex: # pylint: disable=broad-except observer.on_error(ex) else: d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe_(observer.on_next, on_error, observer.on_completed, scheduler) cancelable.disposable = scheduler.schedule(action) def dispose(): is_disposed.append(True) return CompositeDisposable(subscription, cancelable, Disposable(dispose))
def subscribe(observer, scheduler=None): scheduler = scheduler or current_thread_scheduler subscription = SerialDisposable() cancelable = SerialDisposable() last_exception = [None] is_disposed = [] def action(action1, state=None): def on_error(exn): last_exception[0] = exn cancelable.disposable = scheduler.schedule(action) if is_disposed: return try: current = next(sources_) except StopIteration: if last_exception[0]: observer.on_error(last_exception[0]) else: observer.on_completed() except Exception as ex: # pylint: disable=broad-except observer.on_error(ex) else: d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe_(observer.on_next, on_error, observer.on_completed, scheduler) cancelable.disposable = scheduler.schedule(action) def dispose(): is_disposed.append(True) return CompositeDisposable(subscription, cancelable, Disposable(dispose))
def subscribe(observer, scheduler=None): scheduler = scheduler or current_thread_scheduler subscription = SerialDisposable() cancelable = SerialDisposable() 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 = rx.from_future(source) if is_future(source) else 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, scheduler) cancelable.disposable = scheduler.schedule(action) return CompositeDisposable(subscription, cancelable)
def subscribe(observer, scheduler=None): scheduler = scheduler or current_thread_scheduler subscription = SerialDisposable() cancelable = SerialDisposable() is_disposed = False def action(action1, state=None): nonlocal is_disposed if is_disposed: return def on_completed(): cancelable.disposable = scheduler.schedule(action) try: current = next(sources_) except StopIteration: observer.on_completed() except Exception as ex: # pylint: disable=broad-except observer.on_error(ex) else: d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe_(observer.on_next, observer.on_error, on_completed, scheduler) cancelable.disposable = scheduler.schedule(action) def dispose(): nonlocal is_disposed is_disposed = True return CompositeDisposable(subscription, cancelable, Disposable(dispose))
def test_map_disposeinsidemapper(self): scheduler = TestScheduler() xs = scheduler.create_hot_observable(on_next(100, 1), on_next(200, 2), on_next(500, 3), on_next(600, 4)) results = scheduler.create_observer() d = SerialDisposable() invoked = [0] def projection(x, *args, **kw): invoked[0] += 1 if scheduler.clock > 400: d.dispose() return x d.disposable = xs.pipe( map(projection) ).subscribe(results, scheduler) def action(scheduler, state): return d.dispose() scheduler.schedule_absolute(ReactiveTest.disposed, action) scheduler.start() assert results.messages == [on_next(100, 1), on_next(200, 2)] assert xs.subscriptions == [ReactiveTest.subscribe(0, 500)] assert invoked[0] == 3
def subscribe(observer, scheduler=None): scheduler = scheduler or current_thread_scheduler subscription = SerialDisposable() cancelable = SerialDisposable() 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 = rx.from_future(source) if is_future(source) else 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, scheduler) cancelable.disposable = scheduler.schedule(action) return CompositeDisposable(subscription, cancelable)
def subscribe(observer, scheduler=None): d1 = SingleAssignmentDisposable() subscription = SerialDisposable() subscription.disposable = d1 def on_error(exception): try: result = handler(exception, source) except Exception as ex: # By design. pylint: disable=W0703 observer.on_error(ex) return result = rx.from_future(result) if is_future(result) 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 ) return subscription
def test_starmap_dispose_inside_mapper(self): scheduler = TestScheduler() xs = scheduler.create_hot_observable( # 100 create on_next(110, (1, 10)), # 200 subscribe on_next(210, (2, 20)), on_next(310, (3, 30)), on_next(410, (4, 40))) results = scheduler.create_observer() d = SerialDisposable() invoked = [0] def mapper(x, y): invoked[0] += 1 if scheduler.clock > 250: d.dispose() return x + y d.disposable = xs.pipe(ops.starmap(mapper)).subscribe( results, scheduler) def action(scheduler, state): return d.dispose() scheduler.schedule_absolute(ReactiveTest.disposed, action) scheduler.start() assert results.messages == [on_next(110, 11), on_next(210, 22)] assert xs.subscriptions == [ReactiveTest.subscribe(0, 310)] assert invoked[0] == 3
def test_map_disposeinsidemapper(self): scheduler = TestScheduler() xs = scheduler.create_hot_observable(on_next(100, 1), on_next(200, 2), on_next(500, 3), on_next(600, 4)) results = scheduler.create_observer() d = SerialDisposable() invoked = [0] def projection(x, *args, **kw): invoked[0] += 1 if scheduler.clock > 400: d.dispose() return x d.disposable = xs.pipe(map(projection)).subscribe(results, scheduler) def action(scheduler, state): return d.dispose() scheduler.schedule_absolute(ReactiveTest.disposed, action) scheduler.start() assert results.messages == [on_next(100, 1), on_next(200, 2)] assert xs.subscriptions == [ReactiveTest.subscribe(0, 500)] assert invoked[0] == 3
def test_map_with_index_dispose_inside_mapper(self): scheduler = TestScheduler() xs = scheduler.create_hot_observable(on_next(100, 4), on_next(200, 3), on_next(500, 2), on_next(600, 1)) invoked = [0] results = scheduler.create_observer() d = SerialDisposable() def projection(x, index): invoked[0] += 1 if scheduler.clock > 400: d.dispose() return x + index * 10 d.disposable = xs.pipe(map_indexed(projection)).subscribe(results) def action(scheduler, state): return d.dispose() scheduler.schedule_absolute(disposed, action) scheduler.start() assert results.messages == [on_next(100, 4), on_next(200, 13)] assert xs.subscriptions == [subscribe(0, 500)] assert invoked[0] == 3
def subscribe(observer, _=None): m = SingleAssignmentDisposable() d = SerialDisposable() d.disposable = m def action(scheduler, state): d.disposable = ScheduledDisposable(scheduler, source.subscribe(observer)) m.disposable = scheduler.schedule(action) return d
def subscribe(observer, _=None): m = SingleAssignmentDisposable() d = SerialDisposable() d.disposable = m def action(scheduler, state): d.disposable = ScheduledDisposable(scheduler, source.subscribe(observer)) m.disposable = scheduler.schedule(action) return d
def subscribe(observer): m = SingleAssignmentDisposable() d = SerialDisposable() d.disposable = m def action(): d.disposable = SchedulerDisposable(scheduler, self.subscribeSafe(observer)) m.disposable = scheduler.schedule(action) return d
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) 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 = obs.subscribe( observer, scheduler=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)
def test_mutabledisposable_replaceafterdispose(): disp1 = [False] disp2 = [False] m = SerialDisposable() m.dispose() def action1(): disp1[0] = True d1 = Disposable(action1) m.disposable = d1 assert m.disposable == None assert disp1[0] def action2(): disp2[0] = True d2 = Disposable(action2) m.disposable = d2 assert m.disposable == None assert disp2[0]
def test_mutabledisposable_replacebeforedispose(): disp1 = [False] disp2 = [False] m = SerialDisposable() def action1(): disp1[0] = True d1 = Disposable(action1) m.disposable = d1 assert d1 == m.disposable assert not disp1[0] def action2(): disp2[0] = True d2 = Disposable(action2) m.disposable = d2 assert d2 == m.disposable assert disp1[0] assert not disp2[0]
def test_mutabledisposable_dispose(): disp = [False] m = SerialDisposable() def action(): disp[0] = True d = Disposable(action) m.disposable = d assert d == m.disposable assert not disp[0] m.dispose() assert disp[0] assert m.disposable == None
def subscribe(observer, scheduler_=None): _scheduler = scheduler or 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=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)
def test_mutabledisposable_replaceafterdispose(): disp1 = [False] disp2 = [False] m = SerialDisposable() m.dispose() def action1(): disp1[0] = True d1 = Disposable(action1) m.disposable = d1 assert m.disposable == None assert disp1[0] def action2(): disp2[0] = True d2 = Disposable(action2) m.disposable = d2 assert m.disposable == None assert disp2[0]
def test_mutabledisposable_replacebeforedispose(): disp1 = [False] disp2 = [False] m = SerialDisposable() def action1(): disp1[0] = True d1 = Disposable(action1) m.disposable = d1 assert d1 == m.disposable assert not disp1[0] def action2(): disp2[0] = True d2 = Disposable(action2) m.disposable = d2 assert d2 == m.disposable assert disp1[0] assert not disp2[0]
def test_mutabledisposable_dispose(): disp = [False] m = SerialDisposable() def action(): disp[0] = True d = Disposable(action) m.disposable = d assert d == m.disposable assert not disp[0] m.dispose() assert disp[0] assert m.disposable == None
def schedule_periodic(self, period: typing.RelativeTime, action: ScheduledPeriodicAction, state: TState = None) -> typing.Disposable: """Schedules a periodic piece of work. Args: period: Period in seconds or timedelta for running the work periodically. action: Action to be executed. state: [Optional] Initial state passed to the action upon the first iteration. Returns: The disposable object used to cancel the scheduled recurring action (best effort).""" disp = SerialDisposable() def invoke_action(scheduler: typing.Scheduler, _: TState) -> Optional[Disposable]: nonlocal state if disp.is_disposed: return None disp.disposable = self.schedule_relative(period, invoke_action, None) try: new_state = action(state) except Exception: disp.dispose() raise if state is not None: state = new_state return None disp.disposable = self.schedule_relative(period, invoke_action, state) return disp
def subscribe(observer, scheduler_=None): _scheduler = scheduler_ or CurrentThreadScheduler.singleton() subscription = SerialDisposable() cancelable = SerialDisposable() last_exception = None is_disposed = False def action(action1, state=None): def on_error(exn): nonlocal last_exception last_exception = exn cancelable.disposable = _scheduler.schedule(action) if is_disposed: return try: current = next(sources_) except StopIteration: if last_exception: observer.on_error(last_exception) else: observer.on_completed() except Exception as ex: # pylint: disable=broad-except observer.on_error(ex) else: d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe_(observer.on_next, on_error, observer.on_completed, scheduler_) cancelable.disposable = _scheduler.schedule(action) def dispose(): nonlocal is_disposed is_disposed = True return CompositeDisposable(subscription, cancelable, Disposable(dispose))
def test_map_with_index_dispose_inside_mapper(self): scheduler = TestScheduler() xs = scheduler.create_hot_observable(on_next(100, 4), on_next(200, 3), on_next(500, 2), on_next(600, 1)) invoked = [0] results = scheduler.create_observer() d = SerialDisposable() def projection(x, index): invoked[0] += 1 if scheduler.clock > 400: d.dispose() return x + index * 10 d.disposable = xs.pipe(map_indexed(projection)).subscribe(results) def action(scheduler, state): return d.dispose() scheduler.schedule_absolute(disposed, action) scheduler.start() assert results.messages == [on_next(100, 4), on_next(200, 13)] assert xs.subscriptions == [subscribe(0, 500)] assert invoked[0] == 3
def test_starmap_dispose_inside_mapper(self): scheduler = TestScheduler() xs = scheduler.create_hot_observable( # 100 create on_next(110, (1, 10)), # 200 subscribe on_next(210, (2, 20)), on_next(310, (3, 30)), on_next(410, (4, 40))) results = scheduler.create_observer() d = SerialDisposable() invoked = [0] def mapper(x, y): invoked[0] += 1 if scheduler._clock > 250: d.dispose() return x + y d.disposable = xs.pipe( ops.starmap(mapper) ).subscribe(results, scheduler) def action(scheduler, state): return d.dispose() scheduler.schedule_absolute(ReactiveTest.disposed, action) scheduler.start() assert results.messages == [ on_next(110, 11), on_next(210, 22)] assert xs.subscriptions == [ReactiveTest.subscribe(0, 310)] assert invoked[0] == 3
def subscribe(observer, scheduler=None): subscription = SerialDisposable() timer = SerialDisposable() original = SingleAssignmentDisposable() subscription.disposable = original switched = False _id = [0] def set_timer(timeout: Observable) -> None: my_id = _id[0] def timer_wins(): return _id[0] == my_id d = SingleAssignmentDisposable() timer.disposable = d def on_next(x): if timer_wins(): subscription.disposable = other.subscribe(observer, scheduler=scheduler) d.dispose() def on_error(e): if timer_wins(): observer.on_error(e) def on_completed(): if timer_wins(): subscription.disposable = other.subscribe(observer) d.disposable = timeout.subscribe_(on_next, on_error, on_completed, scheduler) set_timer(first_timeout) def observer_wins(): res = not switched if res: _id[0] += 1 return res def on_next(x): if observer_wins(): observer.on_next(x) timeout = None try: timeout = timeout_duration_mapper(x) except Exception as e: observer.on_error(e) return set_timer(timeout) def on_error(error): if observer_wins(): observer.on_error(error) def on_completed(): if observer_wins(): observer.on_completed() original.disposable = source.subscribe_(on_next, on_error, on_completed, scheduler) return CompositeDisposable(subscription, timer)
def subscribe(observer, scheduler=None): subscription = SerialDisposable() timer = SerialDisposable() original = SingleAssignmentDisposable() subscription.disposable = original switched = False _id = [0] def set_timer(timeout: Observable) -> None: my_id = _id[0] def timer_wins(): return _id[0] == my_id d = SingleAssignmentDisposable() timer.disposable = d def on_next(x): if timer_wins(): subscription.disposable = other.subscribe( observer, scheduler=scheduler) d.dispose() def on_error(e): if timer_wins(): observer.on_error(e) def on_completed(): if timer_wins(): subscription.disposable = other.subscribe(observer) d.disposable = timeout.subscribe_(on_next, on_error, on_completed, scheduler) set_timer(first_timeout) def observer_wins(): res = not switched if res: _id[0] += 1 return res def on_next(x): if observer_wins(): observer.on_next(x) timeout = None try: timeout = timeout_duration_mapper(x) except Exception as e: observer.on_error(e) return set_timer(timeout) def on_error(error): if observer_wins(): observer.on_error(error) def on_completed(): if observer_wins(): observer.on_completed() original.disposable = source.subscribe_(on_next, on_error, on_completed, scheduler) return CompositeDisposable(subscription, timer)