Пример #1
0
    def test_on_error(self):
        sink = TObserver()
        observer = ConnectableObserver(
            sink,
        )

        observer.on_error(self.exception)
Пример #2
0
    def test_connect_empty(self):
        sink = TObserver()
        observer = ConnectableObserver(
            sink,
        )

        observer.connect()

        self.assertEqual(0, len(sink.received))
Пример #3
0
    def test_on_next(self):
        sink = TObserver()
        observer = ConnectableObserver(
            sink,
        )

        ack = observer.on_next([1])

        self.assertEqual(0, len(sink.received))
Пример #4
0
    def test_on_next_then_connect(self):
        sink = TObserver()
        observer = ConnectableObserver(
            sink,
        )
        ack = observer.on_next([1])

        observer.connect()

        self.assertEqual([1], sink.received)
        self.assertIsInstance(ack.value, ContinueAck)
Пример #5
0
 def gen_connectable_observer():
     for _ in obs_list:
         conn_observer = ConnectableObserver(
             underlying=self.inner_observer,
             # scheduler=self.scheduler,
         )
         yield conn_observer
Пример #6
0
    def observe(self, observer_info: ObserverInfo):
        """
        sources[0] ------------------------> Subject --
                                                       \
        sources[1] -> ConnectableObserver -> Subject -----> ConcatObserver
        ...                                            /
        sources[n] -> ConnectableObserver -> Subject --
        """

        conn_observers = [
            ConnectableObserver(underlying=None, ) for _ in self.sources
        ]

        iter_conn_obs = iter(conn_observers)

        concat_observer = ConcatObserver(
            next_observer=observer_info.observer,
            connectables=iter_conn_obs,
        )

        for conn_observer in conn_observers:
            conn_observer.underlying = concat_observer

        def gen_disposable_from_observer():
            for source, conn_observer in zip(self.sources[1:], conn_observers):
                yield source.observe(
                    observer_info.copy(observer=conn_observer, ))

        others_disposables = gen_disposable_from_observer()

        first_disposable = self.sources[0].observe(
            observer_info.copy(observer=concat_observer, ))

        return CompositeDisposable(first_disposable, *others_disposables)
Пример #7
0
    def test_on_next_on_error_then_connect_on_next(self):
        sink = TObserver()
        observer = ConnectableObserver(
            sink,
        )
        ack = observer.on_next([1])
        observer.on_error(self.exception)

        observer.connect()

        ack = observer.on_next([2])

        self.assertEqual([1], sink.received)
        self.assertEqual(self.exception, sink.exception)
        self.assertIsInstance(ack, StopAck)
Пример #8
0
    def test_on_error_then_continue(self):
        sink = TObserver()
        observer = ConnectableObserver(
            sink,
        )
        observer.on_error(self.exception)

        observer.connect()

        self.assertEqual(self.exception, sink.exception)
Пример #9
0
 def test_initialize(self):
     sink = TObserver()
     observer = ConnectableObserver(
         sink,
     )
        def gen_conn_flowables():
            for source in self.sources:

                # buffers elements received before outgoing Flowable is subscribed
                conn_observer = ConnectableObserver(
                    underlying=None,
                    # scheduler=self.multicast_scheduler,
                )

                outer_self = self

                @dataclass
                class InnerObserver(Observer):
                    underlying: Observer
                    outer_observer: MultiCastObserver

                    def on_next(self, elem: ElementType):
                        if not outer_self.is_sent:

                            outer_self.is_sent = True
                            try:
                                observer_info.observer.on_next([flowables])
                                observer_info.observer.on_completed()
                            except Exception as exc:
                                observer_info.observer.on_error(exc)

                        return self.underlying.on_next(elem)

                    def on_error(self, err):
                        self.outer_observer.on_error(err)
                        self.underlying.on_error(err)

                    def on_completed(self):
                        self.underlying.on_completed()

                disposable = source.observe(
                    observer_info=init_multicast_observer_info(
                        observer=InnerObserver(
                            underlying=conn_observer,
                            outer_observer=observer_info.observer,
                        ), ), )

                # select a single Flowable per MultiCast
                def to_flowable(value):
                    if isinstance(value, FlowableMixin):
                        flowable = value

                    else:
                        raise Exception(f'illegal value "{value}"')

                    return flowable

                flattened_flowable = FlatConcatNoBackpressureFlowable(
                    source=ConnectableFlowable(
                        conn_observer=conn_observer,
                        disposable=disposable,
                    ),
                    selector=to_flowable,
                    subscribe_scheduler=self.source_scheduler,
                )

                # The outgoing Flowables are shared such that they can be subscribed more
                # than once
                yield init_flowable(
                    RefCountFlowable(
                        source=flattened_flowable,
                        stack=self.stack,
                    ))
Пример #11
0
        def subscribe_action(_, __):

            conn_observer = None

            for val in reversed(outer_vals[1:]):

                # create a new `InnerObserver` for each inner observable
                inner_observer = FlatMapInnerObserver(
                    observer_info=self.observer_info,
                    next_conn_observer=conn_observer,
                    outer_upstream_ack=async_upstream_ack,
                    state=self.state,
                    lock=self.lock,
                )

                # add ConnectableObserver to observe all inner observables simultaneously, and
                # to get control of activating one after the other
                conn_observer = ConnectableObserver(
                    underlying=inner_observer, )

                # apply selector to get inner observable (per element received)
                try:
                    inner_observable = self.func(val)

                    # for mypy to type check correctly
                    assert isinstance(self.observer_info, ObserverInfo)

                    # observe inner observable
                    disposable = inner_observable.observe(
                        self.observer_info.copy(observer=conn_observer, ))
                    self.composite_disposable.add(disposable)
                except Exception as exc:
                    self.on_error(exc)
                    return stop_ack

            # create a new `InnerObserver` for each inner observable
            inner_observer = FlatMapInnerObserver(
                observer_info=self.observer_info,
                next_conn_observer=conn_observer,
                outer_upstream_ack=async_upstream_ack,
                state=self.state,
                lock=self.lock,
            )

            next_state = RawFlatMapStates.Active()

            with self.lock:
                next_state.raw_prev_state = self.state[0]
                self.state[0] = next_state

            meas_state = next_state.raw_prev_state.get_measured_state()

            if isinstance(meas_state, FlatMapStates.Stopped):
                return stop_ack

            # for mypy to type check correctly
            assert isinstance(self.observer_info, ObserverInfo)

            try:
                # apply selector to get inner observable (per element received)
                inner_observable = self.func(outer_vals[0])

                # observe inner observable
                disposable = inner_observable.observe(
                    self.observer_info.copy(observer=inner_observer, ))
                self.composite_disposable.add(disposable)
            except Exception as exc:
                self.observer_info.observer.on_error(exc)
                return stop_ack