예제 #1
0
 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
예제 #2
0
 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
예제 #3
0
    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
예제 #4
0
 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
예제 #5
0
    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
예제 #6
0
                    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()
예제 #7
0
 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()
예제 #8
0
    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)
예제 #9
0
 def on_next(self, v):
     return Continue()
예제 #10
0
        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)])
예제 #12
0
 def on_next(v):
     send_notification(('N', v))
     return Continue()
예제 #13
0
    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)
예제 #14
0
 def on_next(v):
     if isinstance(v, Continue):
         buffer_was_drained.on_next(Continue())
         buffer_was_drained.on_completed()
예제 #15
0
        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
예제 #16
0
 def on_next(self, v):
     observer.on_next(v)
     return Continue()
예제 #17
0
 def on_next(self, v):
     received.append(v)
     return Continue()
예제 #18
0
                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)