def on_next(self, v): self.received.append(v) if 0 < self.immediate_continue: self.immediate_continue -= 1 return Continue() else: self.ack = Ack() return self.ack
def on_next(v): if is_first[0]: is_first[0] = False last_elem[0] = v return Continue() else: new = self.selector(last_elem[0], v) last_elem[0] = v ack = observer.on_next(new) return ack
def send_on_next_to_all(self, subscribers: List, v): result = None index = 0 while index < len(subscribers): subscriber = subscribers[index] observer = subscriber.observer index += 1 try: ack = observer.on_next(v) except: raise NotImplementedError if ack.has_value: if not isinstance(ack, Continue) and ack.exception is not None: self.unsubscribe(observer) else: if not isinstance(ack, Continue): if result is None: result = PromiseCounter(Continue(), 1) result.acquire() def on_next(v): if isinstance(v, Continue): result.countdown() else: self.unsubscribe(observer) result.countdown() def on_error(err): self.unsubscribe(observer) result.countdown() ack.first().subscribe(on_next=on_next, on_error=on_error) if result is None: return Continue() else: result.countdown() return result.promise
def on_next(v): if isinstance(v, Continue): self.root_ack.on_next(Continue()) self.root_ack.on_completed() source.is_connected = True source.queue = None # source.connected_ack = None # todo: fill in elif isinstance(v, Stop): raise NotImplementedError else: raise NotImplementedError
def on_next(self, elem): with self.lock: state = self.state if not state.is_done: self.state = state.append_elem(elem) iterator = iter(state.subscribers) result = None for obs in iterator: try: ack = obs.on_next(elem) except: raise NotImplementedError if isinstance(ack, Stop): self.remove_subscriber(obs) else: if result is None: result = PromiseCounter(Continue(), 1) result.acquire() def on_next(v): if isinstance(v, Continue): result.countdown() else: self.remove_subscriber(obs) result.countdown() ack.observe_on(obs.scheduler).subscribe(on_next) if result is None: return Continue() else: result.countdown() return result.promise
def on_completed(self): if not source.scheduled_done: if self.ack is None: buffer_was_drained.on_next(Continue()) buffer_was_drained.on_completed() else: def on_next(v): if isinstance(v, Continue): buffer_was_drained.on_next(Continue()) buffer_was_drained.on_completed() self.ack.subscribe(on_next) elif source.schedule_error is not None: raise NotImplementedError else: source.underlying.on_completed()
def __init__(self, out: Observer, scheduler, async_upstream_ack: Ack, concat_observer): self.out = out self.scheduler = scheduler self.async_upstream_ack = async_upstream_ack self.concat_observer = concat_observer self.ack = Continue()
def unsafe_subscribe(self, observer, scheduler, subscribe_scheduler): source = self class State: pass class WaitOnNextChild(State): def __init__(self, ack): self.ack = ack class WaitOnActiveChild(State): pass class Active(State): def __init__(self, disposable): self.disposable = disposable class WaitComplete(State): def __init__(self, ex, disposable: Optional[Disposable]): self.ex = ex self.disposable = disposable class Cancelled(State): pass is_active = [True] state = [WaitOnNextChild(Continue())] class ChildObserver(Observer): def __init__(self, out: Observer, scheduler, async_upstream_ack: Ack, concat_observer): self.out = out self.scheduler = scheduler self.async_upstream_ack = async_upstream_ack self.concat_observer = concat_observer self.ack = Continue() def signal_child_on_error(self, ex): with source.lock: current_state = state[0] state[0] = WaitComplete(ex, None) if isinstance(current_state, WaitOnActiveChild) or isinstance(current_state, WaitOnNextChild) \ or isinstance(current_state, Active): observer.on_error(ex) self.async_upstream_ack.on_next(stop_ack) self.async_upstream_ack.on_completed() elif isinstance(current_state, WaitComplete): current_state: WaitComplete = current_state scheduler.report_failure(current_state.ex) observer.on_error(ex) self.async_upstream_ack.on_next(stop_ack) self.async_upstream_ack.on_completed() elif isinstance(current_state, Cancelled): scheduler.report_failure(ex) else: raise Exception('observer is in a unrecognized state: {}'.format(current_state)) def send_on_complete(self): # todo: complete here return self.concat_observer.signal_finish() def signal_child_on_complete(self, ack: Ack, is_stop: bool): with source.lock: current_state = state[0] state[0] = WaitOnNextChild(ack) if isinstance(current_state, WaitOnNextChild) or isinstance(current_state, Active): ack.subscribe(self.async_upstream_ack) elif isinstance(current_state, Cancelled): ack.on_next(Stop()) ack.on_completed() elif isinstance(current_state, WaitComplete): state_: WaitComplete = current_state if not is_stop: if state_.ex is None: self.send_on_complete() else: observer.on_error(state_.ex) else: scheduler.report_failure(state_.ex) def on_stop_or_failure_ref(self, err=None): if err: scheduler.report_failure(err) self.signal_child_on_complete(Stop(), is_stop=True) def on_next(self, v): ack = self.out.on_next(v) if isinstance(ack, Stop): self.on_stop_or_failure_ref() elif not isinstance(v, Continue): def _(v): if isinstance(v, Stop): self.on_stop_or_failure_ref() ack.subscribe(_) return ack def on_error(self, err): self.signal_child_on_error(err) def on_completed(self): # self.async_upstream_ack.on_next(Continue()) # self.async_upstream_ack.on_completed() self.signal_child_on_complete(self.ack, is_stop=False) class ConcatMapObserver(Observer): def __init__(self): self.errors = [] if source.delay_errors else None def cancel_state(self): pass def report_invalid_state(self, state: State, method: str): self.cancel_state() scheduler.report_failure(Exception('State {} in the ConcatMap.{} implementation is invalid'.format(state, method))) def on_next(self, elem): stream_error = True if not is_active[0]: return stop_ack else: async_upstream_ack = Ack() child = source.selector(elem) stream_error = False with source.lock: state[0] = WaitOnActiveChild() child_observer = ChildObserver(observer, scheduler, async_upstream_ack, self) disposable = child.subscribe(child_observer, scheduler, subscribe_scheduler) with source.lock: current_state = state[0] state[0] = Active(disposable) if isinstance(current_state, WaitOnNextChild): with source.lock: state[0] = current_state state_: WaitOnNextChild = current_state return state_.ack elif isinstance(current_state, WaitOnActiveChild): if is_active[0]: return async_upstream_ack else: self.cancel_state() return stop_ack elif isinstance(current_state, Cancelled): self.cancel_state() return stop_ack else: self.report_invalid_state(current_state, 'on_next') return stop_ack def send_on_complete(self): # if not source.delay_errors: observer.on_completed() # else: # errors = self.errors # if len(errors) == 0: # observer.on_completed() # else: # observer.on_error(errors[0]) def signal_finish(self, ex: Exception = None): current_state = state[0] if isinstance(current_state, Active): state_: Active = current_state child_ref = state_.disposable elif isinstance(current_state, WaitComplete): state_: WaitComplete = current_state child_ref = state_.disposable else: child_ref = None with source.lock: current_state = state[0] state[0] = WaitComplete(ex, child_ref) if isinstance(current_state, WaitOnNextChild): if ex is None: self.send_on_complete() else: observer.on_error(ex) with source.lock: state[0] = Cancelled() elif isinstance(current_state, Active): if not is_active[0]: self.cancel_state() elif isinstance(current_state, WaitOnNextChild): with source.lock: state[0] = Cancelled() elif isinstance(current_state, Cancelled): self.cancel_state() with source.lock: state[0] = Cancelled() else: self.report_invalid_state(current_state, 'signal_finish') def on_error(self, exc): self.signal_finish(exc) def on_completed(self): self.signal_finish() concat_map_observer = ConcatMapObserver() return self.source.unsafe_subscribe(concat_map_observer, scheduler, subscribe_scheduler)
def on_next(self, v): return Continue()
def on_next_right(right): ack = Ack() upper_ack = None has_inner_left_elem = False request_left_right = False request_right = False with self.lock: if 0 < inner_left_completed[0]: inner_left_completed[0] -= 1 request_right = True upper_ack = Continue() # new_state = self.WaitForLeftOrRight() new_state = state[0] elif isinstance(state[0], self.WaitForLeftOrRight): new_state = self.WaitForLeft(right_elem=right, right_ack=ack) elif isinstance(state[0], self.WaitForRightOrInner): state_: FlatZipObservable.WaitForRightOrInner = state[0] if inner_left_completed[0] == 0: new_state = self.Active(left_ack=state_.left_ack, right_elem=right, right_ack=ack, upper_ack=Continue()) else: inner_left_completed[0] -= 1 new_state = self.WaitForLeftOrRight() elif isinstance(state[0], self.WaitForRight): state_: FlatZipObservable.WaitForRight = state[0] has_inner_left_elem = True left_elem = state_.left_elem left_ack = state_.left_ack inner_left_elem = state_.inner_left_elem inner_left_ack = state_.inner_left_ack new_state = state[0] elif isinstance(state[0], source.Completed): return stop_ack else: raise NotImplementedError state[0] = new_state if has_inner_left_elem: zipped_elem = self.selector(left_elem, right, inner_left_elem) upper_ack = observer.on_next(zipped_elem) if isinstance(upper_ack, Stop): with self.lock: state[0] = self.Completed return upper_ack request_inner_elem = False with self.lock: if 0 < inner_left_completed[0]: # inner left completed, request new left and right new_state = self.WaitForLeftOrRight() request_left_right = True else: # state is the same, change state to active new_state = self.Active(left_ack=left_ack, right_elem=right, right_ack=ack, upper_ack=upper_ack) request_inner_elem = True state[0] = new_state if request_inner_elem: if isinstance(upper_ack, Continue) or isinstance( upper_ack, Stop): inner_left_ack.on_next(upper_ack) inner_left_ack.on_completed() else: upper_ack.observe_on(scheduler).subscribe( inner_left_ack) if request_left_right: if isinstance(upper_ack, Continue): left_ack.on_next(upper_ack) left_ack.on_completed() else: upper_ack.observe_on(scheduler).subscribe(left_ack) if request_left_right or request_right: if isinstance(upper_ack, Continue): ack.on_next(upper_ack) ack.on_completed() else: upper_ack.observe_on(scheduler).subscribe(ack) return ack
def test_1(self): ack_left = self.left_in.on_next(5) # left should emit immediately a PublishSubject self.assertEqual(self.left_out.received[0][0], 5) self.assertIsInstance(self.left_out.received[0][1], PublishSubject) ack_right = self.right_in.on_next(4) # right.is_lower should be selected; # - (False, 4) should be send over right # - ack is directly forwarded to right_in self.assertListEqual(self.right_out.received, [(False, 4)]) self.assertEqual(self.right_out.ack, ack_right) # request next right self.right_out.ack.on_next(Continue()) self.right_out.ack.on_completed() ack_right = self.right_in.on_next(5) # right.is_equal should be selected; # - 5 should be send over inner left # - (True, 5) should be send over right self.assertEqual(self.left_out.inner_obs.received, [5]) self.assertListEqual(self.right_out.received, [(False, 4), (True, 5)]) self.right_out.ack.on_next(Continue()) self.right_out.ack.on_completed() self.assertFalse(ack_right.has_value) self.left_out.inner_obs.ack.on_next(Continue()) self.left_out.inner_obs.ack.on_completed() self.assertIsInstance(ack_right.value, Continue) ack_right = self.right_in.on_next(6) # right.is_higher should be selected; self.assertTrue(self.left_out.inner_obs.is_completed) self.left_out.ack.on_next(Continue()) self.left_out.ack.on_completed() self.assertIsInstance(ack_left.value, Continue) self.assertEqual(self.left_out.inner_obs.received, [5]) self.assertListEqual(self.right_out.received, [(False, 4), (True, 5)]) ack_left = self.left_in.on_next(6) # left.is_equal should be selected self.assertEqual(self.left_out.received[1][0], 6) self.assertListEqual(self.right_out.received, [(False, 4), (True, 5), (True, 6)]) self.right_out.ack.on_next(Continue()) self.right_out.ack.on_completed() self.left_out.inner_obs.ack.on_next(Continue()) self.left_out.inner_obs.ack.on_completed() self.assertIsInstance(ack_right.value, Continue) ack_right = self.right_in.on_next(7) # right.is_higher should be selected; self.assertTrue(self.left_out.inner_obs.is_completed) self.left_out.ack.on_next(Continue()) self.left_out.ack.on_completed() self.assertIsInstance(ack_left.value, Continue) self.assertEqual(self.left_out.inner_obs.received, [6]) self.assertListEqual(self.right_out.received, [(False, 4), (True, 5), (True, 6)]) # ---------------------------------- # left.is_higher ack_left = self.left_in.on_next(8) # left.is_higher should be selected self.assertListEqual(self.right_out.received, [(False, 4), (True, 5), (True, 6), (False, 7)]) self.right_out.ack.on_next(Continue()) self.right_out.ack.on_completed() self.assertIsInstance(ack_right.value, Continue) # ---------------------------------- # left.is_lower ack_right = self.right_in.on_next(10) self.left_out.ack.on_next(Continue()) self.left_out.ack.on_completed() ack_left = self.left_in.on_next(9) # left.is_lower should be selected self.assertEqual(self.left_out.received[3][0], 9) self.assertTrue(self.left_out.inner_obs.is_completed) self.assertListEqual(self.right_out.received, [(False, 4), (True, 5), (True, 6), (False, 7)])
def on_next(v): send_notification(('N', v)) return Continue()
def test_left_and_inner_first(self): s: TestScheduler = self.scheduler class TestObserver(Observer): def __init__(self): self.received = [] self.was_completed = False self.ack = None def on_next(self, v): self.received.append(v) self.ack = Ack() return self.ack def on_error(self, err): pass def on_completed(self): self.was_completed = True class TestObservable(Observable): def __init__(self): self.observer = None def on_next(self, v): return self.observer.on_next(v) def unsafe_subscribe(self, observer: Observer, scheduler: SchedulerBase, subscribe_scheduler: SchedulerBase): self.observer = observer return Disposable.empty() s1 = TestObservable() s2 = TestObservable() s3 = TestObservable() o1 = TestObserver() obs = FlatZipObservable(s1, s2, lambda v: v) obs.subscribe(o1, s, CurrentThreadScheduler()) ack1 = s1.on_next(s3) self.assertListEqual(o1.received, []) self.assertFalse(ack1.has_value) ack3 = s3.on_next(10) self.assertListEqual(o1.received, []) self.assertFalse(ack3.has_value) ack2 = s2.on_next(100) self.assertListEqual(o1.received, [(10, 100)]) o1.ack.on_next(Continue()) o1.ack.on_completed() s.advance_by(1) self.assertFalse(ack1.has_value) self.assertFalse(ack2.has_value) self.assertTrue(ack3.has_value) self.assertIsInstance(ack3.value, Continue)
def on_next(v): if isinstance(v, Continue): buffer_was_drained.on_next(Continue()) buffer_was_drained.on_completed()
def on_next_left(left_elem): ack = Ack() with self.lock: if isinstance(state[0], self.WaitForLeftOrRight): new_state = self.WaitForRightOrInner(left_ack=ack) elif isinstance(state[0], self.WaitForLeft): state_: source.WaitForLeft = state[0] new_state = self.Active(left_ack=ack, right_elem=state_.right_elem, right_ack=state_.right_ack, upper_ack=Continue()) elif isinstance(state[0], source.Completed): return stop_ack else: raise NotImplementedError state[0] = new_state class ChildObserver(Observer): def __init__(self, out: Observer, scheduler): self.out = out self.scheduler = scheduler def on_next(self, inner_left): ack = Ack() has_right_elem = False right_elem = None with source.lock: if isinstance(state[0], source.WaitForRightOrInner): # not much to do state_typed: source.WaitForRightOrInner = state[0] state[0] = source.WaitForRight( inner_left_elem=inner_left, left_ack=state_typed.left_ack, inner_left_ack=ack, left_elem=source.selector_left(left_elem)) elif isinstance(state[0], source.Active): # send zipped item to observer state_typed: source.Active = state[0] has_right_elem = True right_elem = state_typed.right_elem state[0] = source.Active( left_ack=state_typed.left_ack, right_elem=state_typed.right_elem, right_ack=state_typed.right_ack, upper_ack=ack) elif isinstance(state[0], source.Completed): return stop_ack else: raise NotImplementedError if has_right_elem: # send triple to observer zipped_elem = source.selector( source.selector_left(left_elem), right_elem, inner_left) upper_ack = observer.on_next(zipped_elem) # race condition with on_completed if isinstance(state[0], source.Active): typed_state: source.Active = state[0] typed_state.upper_ack = upper_ack if isinstance(upper_ack, Stop): with source.lock: state[0] = source.Completed() else: def _(v): if isinstance(v, Stop): with source.lock: state[0] = source.Completed() upper_ack.observe_on(scheduler).subscribe(_) return upper_ack else: return ack def on_error(self, err): with source.lock: state[0] = source.Completed() observer.on_error(err) def on_completed(self): back_pressure_right = False back_pressure_left = False left_ack = None right_ack = None upper_ack = None complete_observer = False with source.lock: if isinstance(state[0], source.Active): # normal complete if right_completed[0]: state[0] = source.Completed() complete_observer = True else: # request new left and new right state_typed: source.Active = state[0] back_pressure_right = True back_pressure_left = True left_ack = state_typed.left_ack right_ack = state_typed.right_ack upper_ack = state_typed.upper_ack state[0] = source.WaitForLeftOrRight() elif isinstance(state[0], source.WaitForRightOrInner): # empty inner observable state_typed: source.WaitForRight = state[0] # count up number of inner completed (without right completed) inner_left_completed[0] += 1 state[0] = source.WaitForLeftOrRight() back_pressure_left = True left_ack = state_typed.left_ack upper_ack = Continue() if complete_observer: observer.on_completed() if back_pressure_left or back_pressure_right: def _(v): if isinstance(v, Stop): with source.lock: state[0] = source.Completed() upper_ack.subscribe(_) if back_pressure_left: # upper_ack should not be Stop if isinstance(upper_ack, Continue): left_ack.on_next(upper_ack) left_ack.on_completed() else: upper_ack.observe_on(scheduler).subscribe(left_ack) if back_pressure_right: if isinstance(upper_ack, Continue): right_ack.on_next(upper_ack) right_ack.on_completed() else: upper_ack.observe_on(scheduler).subscribe( right_ack) child = self.selector_inner(left_elem) child_observer = ChildObserver(observer, scheduler) disposable = child.subscribe(child_observer, scheduler, CurrentThreadScheduler()) inner_disposable.disposable = disposable return ack
def on_next(self, v): observer.on_next(v) return Continue()
def on_next(self, v): received.append(v) return Continue()
def on_completed(self): back_pressure_right = False back_pressure_left = False left_ack = None right_ack = None upper_ack = None complete_observer = False with source.lock: if isinstance(state[0], source.Active): # normal complete if right_completed[0]: state[0] = source.Completed() complete_observer = True else: # request new left and new right state_typed: source.Active = state[0] back_pressure_right = True back_pressure_left = True left_ack = state_typed.left_ack right_ack = state_typed.right_ack upper_ack = state_typed.upper_ack state[0] = source.WaitForLeftOrRight() elif isinstance(state[0], source.WaitForRightOrInner): # empty inner observable state_typed: source.WaitForRight = state[0] # count up number of inner completed (without right completed) inner_left_completed[0] += 1 state[0] = source.WaitForLeftOrRight() back_pressure_left = True left_ack = state_typed.left_ack upper_ack = Continue() if complete_observer: observer.on_completed() if back_pressure_left or back_pressure_right: def _(v): if isinstance(v, Stop): with source.lock: state[0] = source.Completed() upper_ack.subscribe(_) if back_pressure_left: # upper_ack should not be Stop if isinstance(upper_ack, Continue): left_ack.on_next(upper_ack) left_ack.on_completed() else: upper_ack.observe_on(scheduler).subscribe(left_ack) if back_pressure_right: if isinstance(upper_ack, Continue): right_ack.on_next(upper_ack) right_ack.on_completed() else: upper_ack.observe_on(scheduler).subscribe( right_ack)