Ejemplo n.º 1
0
    def test_currentthread_schedule(self):
        scheduler = CurrentThreadScheduler()
        ran = False

        def action(scheduler, state=None):
            nonlocal ran
            ran = True

        scheduler.schedule(action)
        assert ran is True
Ejemplo n.º 2
0
    def test_currentthread_schedule_error(self):
        scheduler = CurrentThreadScheduler()

        class MyException(Exception):
            pass

        def action(scheduler, state=None):
            raise MyException()

        with pytest.raises(MyException):
            scheduler.schedule(action)
Ejemplo n.º 3
0
    def test_currentthread_schedule_block(self):
        scheduler = CurrentThreadScheduler()
        ran = False

        def action(scheduler, state=None):
            nonlocal ran
            ran = True

        t = scheduler.now
        scheduler.schedule_relative(0.2, action)
        t = scheduler.now - t
        assert ran is True
        assert t >= timedelta(seconds=0.2)
Ejemplo n.º 4
0
    def test_currentthread_schedule_nested(self):
        scheduler = CurrentThreadScheduler()
        ran = False

        def action(scheduler, state=None):
            def inner_action(scheduler, state=None):
                nonlocal ran
                ran = True

            return scheduler.schedule(inner_action)

        scheduler.schedule(action)

        assert ran is True
Ejemplo n.º 5
0
        def outer(scheduler, state=None):
            def action1(scheduler, state=None):
                tests.append(1)

                def action2(scheduler, state=None):
                    tests.append(2)

                CurrentThreadScheduler().schedule(action2)

            CurrentThreadScheduler().schedule(action1)

            def action3(scheduler, state=None):
                tests.append(3)

            CurrentThreadScheduler().schedule(action3)
Ejemplo n.º 6
0
    def subscribe(
            observer: abc.ObserverBase[_T],
            scheduler: Optional[abc.SchedulerBase] = None
    ) -> abc.DisposableBase:
        scheduler = scheduler or CurrentThreadScheduler.singleton()

        subscription = SerialDisposable()
        cancelable = SerialDisposable()

        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)

        cancelable.disposable = scheduler.schedule(action)
        return CompositeDisposable(subscription, cancelable)
Ejemplo n.º 7
0
    def subscribe(
            observer: abc.ObserverBase[_T],
            scheduler_: Optional[abc.SchedulerBase] = None
    ) -> abc.DisposableBase:
        _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton(
        )
        iterator = iter(iterable)
        disposed = False

        def action(_: abc.SchedulerBase, __: Any = None) -> None:
            nonlocal disposed

            try:
                while not disposed:
                    value = next(iterator)
                    observer.on_next(value)
            except StopIteration:
                observer.on_completed()
            except Exception as error:  # pylint: disable=broad-except
                observer.on_error(error)

        def dispose() -> None:
            nonlocal disposed
            disposed = True

        disp = Disposable(dispose)
        return CompositeDisposable(_scheduler.schedule(action), disp)
Ejemplo n.º 8
0
 def test_currentthread_now_units(self):
     scheduler = CurrentThreadScheduler()
     diff = scheduler.now
     sleep(1.1)
     diff = scheduler.now - diff
     assert timedelta(milliseconds=1000) < diff < timedelta(
         milliseconds=1300)
Ejemplo n.º 9
0
    def test_currentthread_ensuretrampoline_nested(self):
        scheduler = CurrentThreadScheduler()
        ran1, ran2 = False, False

        def outer_action(scheduler, state):
            def inner_action1(scheduler, state):
                nonlocal ran1
                ran1 = True

            scheduler.schedule(inner_action1)

            def inner_action2(scheduler, state):
                nonlocal ran2
                ran2 = True

            return scheduler.schedule(inner_action2)

        scheduler.ensure_trampoline(outer_action)
        assert ran1 is True
        assert ran2 is True
Ejemplo n.º 10
0
    def subscribe(
            observer: abc.ObserverBase[_T],
            scheduler_: Optional[abc.SchedulerBase] = None
    ) -> abc.DisposableBase:
        _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton(
        )

        def action(scheduler: abc.SchedulerBase, state: Any = None) -> None:
            observer.on_next(value)
            observer.on_completed()

        return _scheduler.schedule(action)
Ejemplo n.º 11
0
    def test_currentthread_ensuretrampoline_and_cancel(self):
        scheduler = CurrentThreadScheduler()
        ran1, ran2 = False, False

        def outer_action(scheduler, state):
            def inner_action1(scheduler, state):
                nonlocal ran1
                ran1 = True

                def inner_action2(scheduler, state):
                    nonlocal ran2
                    ran2 = True

                d = scheduler.schedule(inner_action2)
                d.dispose()

            return scheduler.schedule(inner_action1)

        scheduler.ensure_trampoline(outer_action)
        assert ran1 is True
        assert ran2 is False
Ejemplo n.º 12
0
    def test_currentthread_extend(self):
        class MyScheduler(CurrentThreadScheduler):
            pass

        scheduler = [
            MyScheduler(),
            MyScheduler.singleton(),
            MyScheduler.singleton(),
            CurrentThreadScheduler.singleton(),
        ]
        assert scheduler[0] is not scheduler[1]
        assert scheduler[1] is scheduler[2]
        assert scheduler[1] is not scheduler[3]
Ejemplo n.º 13
0
    def test_currentthread_singleton(self):
        scheduler = [
            CurrentThreadScheduler(),
            CurrentThreadScheduler.singleton(),
            CurrentThreadScheduler.singleton(),
        ]
        assert scheduler[0] is not scheduler[1]
        assert scheduler[1] is scheduler[2]

        gate = [threading.Semaphore(0), threading.Semaphore(0)]
        scheduler = [None, None]

        def run(idx):
            scheduler[idx] = CurrentThreadScheduler.singleton()
            gate[idx].release()

        for idx in (0, 1):
            threading.Thread(target=run, args=(idx, )).start()
            gate[idx].acquire()

        assert scheduler[0] is not None
        assert scheduler[1] is not None
        assert scheduler[0] is not scheduler[1]
Ejemplo n.º 14
0
    def test_currentthread_schedule_nested_order(self):
        scheduler = CurrentThreadScheduler()
        tests = []

        def outer(scheduler, state=None):
            def action1(scheduler, state=None):
                tests.append(1)

                def action2(scheduler, state=None):
                    tests.append(2)

                CurrentThreadScheduler().schedule(action2)

            CurrentThreadScheduler().schedule(action1)

            def action3(scheduler, state=None):
                tests.append(3)

            CurrentThreadScheduler().schedule(action3)

        scheduler.ensure_trampoline(outer)

        assert tests == [1, 2, 3]
Ejemplo n.º 15
0
    def subscribe(
            observer: abc.ObserverBase[_T],
            scheduler_: Optional[abc.SchedulerBase] = None
    ) -> abc.DisposableBase:
        _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton(
        )

        def action(_: abc.SchedulerBase, __: Any = None) -> None:
            nonlocal observer

            try:
                observer.on_next(supplier())
                observer.on_completed()
            except Exception as e:  # pylint: disable=broad-except
                observer.on_error(e)

        return _scheduler.schedule(action)
Ejemplo n.º 16
0
    def subscribe(
        observer: abc.ObserverBase[_T], scheduler_: Optional[abc.SchedulerBase] = None
    ) -> abc.DisposableBase:
        _scheduler = scheduler_ or CurrentThreadScheduler.singleton()

        subscription = SerialDisposable()
        cancelable = SerialDisposable()
        last_exception = None
        is_disposed = False

        def action(scheduler: abc.SchedulerBase, state: Any = None) -> None:
            def on_error(exn: Exception) -> None:
                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=scheduler_,
                )

        cancelable.disposable = _scheduler.schedule(action)

        def dispose() -> None:
            nonlocal is_disposed
            is_disposed = True

        return CompositeDisposable(subscription, cancelable, Disposable(dispose))
Ejemplo n.º 17
0
Archivo: range.py Proyecto: lizh06/RxPY
    def subscribe(
        observer: abc.ObserverBase[int], scheduler_: Optional[abc.SchedulerBase] = None
    ) -> abc.DisposableBase:
        nonlocal range_t

        _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton()
        sd = MultipleAssignmentDisposable()

        def action(
            scheduler: abc.SchedulerBase, iterator: Optional[Iterator[int]]
        ) -> None:
            try:
                assert iterator
                observer.on_next(next(iterator))
                sd.disposable = _scheduler.schedule(action, state=iterator)
            except StopIteration:
                observer.on_completed()

        sd.disposable = _scheduler.schedule(action, iter(range_t))
        return sd
Ejemplo n.º 18
0
    def __init__(
        self,
        buffer_size: Optional[int] = None,
        window: Optional[typing.RelativeTime] = None,
        scheduler: Optional[abc.SchedulerBase] = None,
    ) -> None:
        """Initializes a new instance of the ReplaySubject class with
        the specified buffer size, window and scheduler.

        Args:
            buffer_size: [Optional] Maximum element count of the replay
                buffer.
            window [Optional]: Maximum time length of the replay buffer.
            scheduler: [Optional] Scheduler the observers are invoked on.
        """

        super().__init__()
        self.buffer_size = sys.maxsize if buffer_size is None else buffer_size
        self.scheduler = scheduler or CurrentThreadScheduler.singleton()
        self.window = (
            timedelta.max if window is None else self.scheduler.to_timedelta(window)
        )
        self.queue: List[QueueItem] = []
Ejemplo n.º 19
0
 def test_currentthread_now(self):
     scheduler = CurrentThreadScheduler()
     diff = scheduler.now - default_now()
     assert abs(diff) < timedelta(milliseconds=5)
Ejemplo n.º 20
0
 def run(idx):
     scheduler[idx] = CurrentThreadScheduler.singleton()
     gate[idx].release()
Ejemplo n.º 21
0
    def subscribe(
        self,
        on_next: Optional[Union[abc.ObserverBase[_T], abc.OnNext[_T],
                                None]] = None,
        on_error: Optional[abc.OnError] = None,
        on_completed: Optional[abc.OnCompleted] = None,
        *,
        scheduler: Optional[abc.SchedulerBase] = None,
    ) -> abc.DisposableBase:
        """Subscribe an observer to the observable sequence.

        You may subscribe using an observer or callbacks, not both; if the first
        argument is an instance of :class:`Observer <..abc.ObserverBase>` or if
        it has a (callable) attribute named :code:`on_next`, then any callback
        arguments will be ignored.

        Examples:
            >>> source.subscribe()
            >>> source.subscribe(observer)
            >>> source.subscribe(observer, scheduler=scheduler)
            >>> source.subscribe(on_next)
            >>> source.subscribe(on_next, on_error)
            >>> source.subscribe(on_next, on_error, on_completed)
            >>> source.subscribe(on_next, on_error, on_completed, scheduler=scheduler)

        Args:
            observer: [Optional] The object that is to receive
                notifications.
            on_error: [Optional] Action to invoke upon exceptional termination
                of the observable sequence.
            on_completed: [Optional] Action to invoke upon graceful termination
                of the observable sequence.
            on_next: [Optional] Action to invoke for each element in the
                observable sequence.
            scheduler: [Optional] The default scheduler to use for this
                subscription.

        Returns:
            Disposable object representing an observer's subscription to
            the observable sequence.
        """
        if (isinstance(on_next, abc.ObserverBase)
                or hasattr(on_next, "on_next")
                and callable(getattr(on_next, "on_next"))):
            obv = cast(abc.ObserverBase[_T], on_next)
            on_next = obv.on_next
            on_error = obv.on_error
            on_completed = obv.on_completed

        auto_detach_observer: AutoDetachObserver[_T] = AutoDetachObserver(
            on_next, on_error, on_completed)

        def fix_subscriber(
            subscriber: Union[abc.DisposableBase, Callable[[], None]]
        ) -> abc.DisposableBase:
            """Fixes subscriber to make sure it returns a Disposable instead
            of None or a dispose function"""

            if isinstance(subscriber, abc.DisposableBase) or hasattr(
                    subscriber, "dispose"):
                # Note: cast can be avoided using Protocols (Python 3.9)
                return cast(abc.DisposableBase, subscriber)

            return Disposable(subscriber)

        def set_disposable(_: Optional[abc.SchedulerBase] = None,
                           __: Any = None) -> None:
            try:
                subscriber = self._subscribe_core(auto_detach_observer,
                                                  scheduler)
            except Exception as ex:  # By design. pylint: disable=W0703
                if not auto_detach_observer.fail(ex):
                    raise
            else:
                auto_detach_observer.subscription = fix_subscriber(subscriber)

        # Subscribe needs to set up the trampoline before for subscribing.
        # Actually, the first call to Subscribe creates the trampoline so
        # that it may assign its disposable before any observer executes
        # OnNext over the CurrentThreadScheduler. This enables single-
        # threaded cancellation
        # https://social.msdn.microsoft.com/Forums/en-US/eb82f593-9684-4e27-
        # 97b9-8b8886da5c33/whats-the-rationale-behind-how-currentthreadsche
        # dulerschedulerequired-behaves?forum=rx
        current_thread_scheduler = CurrentThreadScheduler.singleton()
        if current_thread_scheduler.schedule_required():
            current_thread_scheduler.schedule(set_disposable)
        else:
            set_disposable()

        # Hide the identity of the auto detach observer
        return Disposable(auto_detach_observer.dispose)