Пример #1
0
def test_groupdisposable_clear():
    disp1 = [False]
    disp2 = [False]

    def action1():
        disp1[0] = True

    d1 = Disposable(action1)

    def action2():
        disp2[0] = True

    d2 = Disposable(action2)

    g = CompositeDisposable(d1, d2)
    assert g.length == 2

    g.clear()
    assert disp1[0]
    assert disp2[0]
    assert not g.length

    disp3 = [False]

    def action3():
        disp3[0] = True

    d3 = Disposable(action3)
    g.add(d3)
    assert not disp3[0]
    assert g.length == 1
Пример #2
0
def test_groupdisposable_contains():
    d1 = Disposable()
    d2 = Disposable()

    g = CompositeDisposable(d1, d2)

    assert g.length == 2
    assert g.contains(d1)
    assert g.contains(d2)
Пример #3
0
    def _subscribe_core(self, observer: Observer, scheduler: Scheduler = None) -> typing.Disposable:
        with self.lock:
            self.check_disposed()
            if not self.is_stopped:
                self.observers.append(observer)
                return InnerSubscription(self, observer)

            if self.exception:
                observer.on_error(self.exception)
                return Disposable()

            observer.on_completed()
            return Disposable()
Пример #4
0
    def schedule_relative(self, duetime, action, state=None):
        """Schedules an action to be executed after duetime.

        Keyword arguments:
        duetime -- {timedelta} Relative time after which to execute the action.
        action -- {Function} Action to be executed.

        Returns {Disposable} The disposable object used to cancel the scheduled
        action (best effort)."""

        scheduler = self
        seconds = self.to_seconds(duetime)
        if not seconds:
            return scheduler.schedule(action, state)

        sad = SingleAssignmentDisposable()

        def interval():
            sad.disposable = action(scheduler, state)

        log.debug("timeout: %s", seconds)
        timer = [gevent.spawn_later(seconds, interval)]

        def dispose():
            # nonlocal timer
            timer[0].kill()

        return CompositeDisposable(sad, Disposable(dispose))
Пример #5
0
    def schedule_relative(self, duetime, action, state=None):
        """Schedules an action to be executed after duetime.

        Keyword arguments:
        duetime -- {timedelta} Relative time after which to execute the action.
        action -- {Function} Action to be executed.

        Returns {Disposable} The disposable object used to cancel the scheduled
        action (best effort)."""

        scheduler = self
        seconds = scheduler.to_seconds(duetime)
        if not seconds:
            return scheduler.schedule(action, state)

        sad = SingleAssignmentDisposable()

        def interval():
            sad.disposable = self.invoke_action(action, state)

        log.debug("timeout: %s", seconds)
        handle = self.loop.call_later(seconds, interval)

        def dispose():
            self.loop.remove_timeout(handle)

        return CompositeDisposable(sad, Disposable(dispose))
Пример #6
0
    def schedule_absolute(
            self,
            duetime: typing.AbsoluteTime,
            action: typing.ScheduledAction,
            state: Optional[typing.TState] = None) -> typing.Disposable:
        """Schedules an action to be executed at duetime.

        Args:
            duetime: Absolute time at which to execute the action.
            action: Action to be executed.
            state: [Optional] state to be given to the action function.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """

        if self._is_disposed:
            raise DisposedException()

        dt = self.to_datetime(duetime)
        si: ScheduledItem[typing.TState] = ScheduledItem(
            self, state, action, dt)

        with self._condition:
            if dt <= self.now:
                self._ready_list.append(si)
            else:
                self._queue.enqueue(si)
            self._condition.notify()  # signal that a new item is available
            self._ensure_thread()

        return Disposable(si.cancel)
Пример #7
0
    def schedule_relative(self,
                          duetime: typing.RelativeTime,
                          action: typing.ScheduledAction,
                          state: typing.TState = None) -> typing.Disposable:
        """Schedules an action to be executed after duetime.

        Args:
            duetime: Relative time after which to execute the action.
            action: Action to be executed.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """

        seconds = self.to_seconds(duetime)
        if not seconds:
            return self.schedule(action, state)

        sad = SingleAssignmentDisposable()

        def interval():
            sad.disposable = self.invoke_action(action, state)

        timer = [eventlet.spawn_after(seconds, interval)]

        def dispose():
            # nonlocal timer
            timer[0].kill()

        return CompositeDisposable(sad, Disposable(dispose))
Пример #8
0
    def schedule_relative(
            self,
            duetime: typing.RelativeTime,
            action: typing.ScheduledAction,
            state: Optional[typing.TState] = None) -> typing.Disposable:
        """Schedules an action to be executed after duetime.

        Args:
            duetime: Relative time after which to execute the action.
            action: Action to be executed.
            state: [Optional] state to be given to the action function.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """

        seconds = self.to_seconds(duetime)
        if not seconds:
            return self.schedule(action, state=state)

        sad = SingleAssignmentDisposable()

        def interval() -> None:
            sad.disposable = self.invoke_action(action, state=state)

        log.debug("timeout: %s", seconds)
        timer = gevent.spawn_later(seconds, interval)

        def dispose() -> None:
            timer.kill()

        return CompositeDisposable(sad, Disposable(dispose))
Пример #9
0
    def _wxtimer_schedule(self, time, action, state, periodic=False):
        scheduler = self

        sad = SingleAssignmentDisposable()

        periodic_state = [state]

        def interval():
            if periodic:
                periodic_state[0] = action(periodic_state[0])
            else:
                sad.disposable = action(scheduler, state)

        log.debug("timeout: %s", msecs)

        msecs = int(self.to_seconds(time) * 1000.0)
        if msecs == 0:
            msecs = 1  # wx.Timer doesn't support zero.

        timer = self._timer_class(interval)
        timer.Start(
            msecs,
            self.wx.TIMER_CONTINUOUS if periodic else self.wx.TIMER_ONE_SHOT)
        self._timers.add(timer)

        def dispose():
            timer.Stop()
            self._timers.remove(timer)

        return CompositeDisposable(sad, Disposable(dispose))
Пример #10
0
    def schedule_periodic(self,
                          period: typing.RelativeTime,
                          action: typing.ScheduledPeriodicAction,
                          state: typing.TState = None) -> typing.Disposable:
        """Schedule a periodic piece of work."""

        secs: float = self.to_seconds(period)
        disposed: threading.Event = threading.Event()

        s = state

        def run() -> None:
            while True:
                disposed.wait(secs)
                if disposed.is_set():
                    return

                nonlocal s
                new_state = action(s)
                if new_state is not None:
                    s = new_state

        thread = self.thread_factory(run)
        thread.start()

        def dispose() -> None:
            disposed.set()

        return Disposable(dispose)
Пример #11
0
    def schedule_periodic(self, period: typing.RelativeTime, action: typing.ScheduledPeriodicAction,
                          state: typing.TState = None) -> typing.Disposable:
        """Schedule a periodic piece of work."""

        secs = self.to_seconds(period)
        disposed: List[bool] = []

        s = [state]

        def run() -> None:
            while True:
                time.sleep(secs)
                if disposed:
                    return

                new_state = action(s[0])
                if new_state is not None:
                    s[0] = new_state

        thread = self.thread_factory(run)
        thread.start()

        def dispose():
            disposed.append(True)

        return Disposable(dispose)
Пример #12
0
    def schedule_relative(self,
                          duetime: RelativeTime,
                          action: ScheduledAction,
                          state: TState = None):
        """Schedules an action to be executed after duetime.
        """

        duetime = int(self.to_seconds(duetime) * 1000.0)

        if duetime <= 0:
            return self.schedule(action, state)

        scheduler = self
        is_disposed = False
        sad = SingleAssignmentDisposable()

        def invoke_action():
            if not is_disposed:
                sad.disposable = action(scheduler, state)

        def dispose():
            nonlocal is_disposed
            is_disposed = True

        self._post(SCHEDULE_RELATIVE, invoke_action, duetime)

        return CompositeDisposable(sad, Disposable(dispose))
Пример #13
0
    def schedule_relative(
            self,
            duetime: RelativeTime,
            action,
            state=None,
    ):
        if isinstance(duetime, datetime.datetime):
            timedelta = duetime - datetime.datetime.fromtimestamp(0)
            timespan = float(timedelta.total_seconds())
        elif isinstance(duetime, datetime.timedelta):
            timespan = float(duetime.total_seconds())
        else:
            timespan = duetime

        def func():
            action(self, None)

        disposable = [MultipleAssignmentDisposable()]

        def _():
            def __():
                future = self.executor.submit(func)
                disposable[0] = Disposable(lambda: future.cancel())
            self.loop.call_later(timespan, __)

        future = self.loop.call_soon_threadsafe(_)
        return CompositeDisposable(disposable, Disposable(lambda: future.cancel()))
Пример #14
0
    def schedule(self,
                 action: typing.ScheduledAction,
                 state: Optional[typing.TState] = None
                 ) -> typing.Disposable:
        """Schedules an action to be executed.

        Args:
            action: Action to be executed.
            state: [Optional] state to be given to the action function.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """
        sad = SingleAssignmentDisposable()

        def interval() -> None:
            sad.disposable = self.invoke_action(action, state=state)

        handle = self._loop.call_soon_threadsafe(interval)

        def dispose() -> None:
            future = Future()

            def cancel_handle() -> None:
                handle.cancel()
                future.set_result(0)

            self._loop.call_soon_threadsafe(cancel_handle)
            future.result()

        return CompositeDisposable(sad, Disposable(dispose))
Пример #15
0
    def schedule_relative(self,
                          duetime: typing.RelativeTime,
                          action: typing.ScheduledAction,
                          state: Optional[typing.TState] = None
                          ) -> typing.Disposable:
        """Schedules an action to be executed after duetime.

        Args:
            duetime: Relative time after which to execute the action.
            action: Action to be executed.
            state: [Optional] state to be given to the action function.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """

        from twisted.internet.task import deferLater

        seconds = self.to_seconds(duetime)

        sad = SingleAssignmentDisposable()

        def interval() -> None:
            sad.disposable = action(self, state)

        log.debug("timeout: %s", seconds)
        handle = deferLater(self.reactor, seconds, interval).addErrback(lambda _: None)

        def dispose() -> None:
            if not handle.called:
                handle.cancel()

        return CompositeDisposable(sad, Disposable(dispose))
Пример #16
0
    def _qtimer_schedule(self, time, action, state, periodic=False):
        scheduler = self
        msecs = int(self.to_seconds(time)*1000.0)

        sad = SingleAssignmentDisposable()

        periodic_state = [state]

        def interval():
            if periodic:
                periodic_state[0] = action(periodic_state[0])
            else:
                sad.disposable = action(scheduler, state)

        log.debug("timeout: %s", msecs)

        timer = self.qtcore.QTimer()
        timer.setSingleShot(not periodic)
        timer.timeout.connect(interval)
        timer.setInterval(msecs)
        timer.start()
        self._timers.add(timer)

        def dispose():
            timer.stop()
            self._timers.remove(timer)

        return CompositeDisposable(sad, Disposable(dispose))
    def observe(self, observer_info: ObserverInfo):
        self.observer = observer_info.observer

        def dispose_func():
            self.is_disposed = True

        return Disposable(dispose_func)
Пример #18
0
    def _gtk_schedule(self, time, action, state, periodic=False):
        # Do not import GLib into global scope because Qt and GLib
        # don't like each other there
        from gi.repository import GLib

        scheduler = self
        msecs = int(self.to_seconds(time)*1000)

        sad = SingleAssignmentDisposable()

        periodic_state = [state]
        stopped = [False]

        def timer_handler(_):
            if stopped[0]:
                return False

            if periodic:
                periodic_state[0] = action(periodic_state[0])
            else:
                sad.disposable = action(scheduler, state)

            return periodic

        GLib.timeout_add(msecs, timer_handler, None)

        def dispose():
            stopped[0] = True

        return CompositeDisposable(sad, Disposable(dispose))
    def schedule_relative(self,
                          duetime: typing.RelativeTime,
                          action: typing.ScheduledAction,
                          state: Optional[typing.TState] = None
                          ) -> typing.Disposable:
        """Schedules an action to be executed after duetime.

        Args:
            duetime: Relative time after which to execute the action.
            action: Action to be executed.
            state: [Optional] state to be given to the action function.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """

        sad = SingleAssignmentDisposable()

        def invoke_action() -> None:
            sad.disposable = self.invoke_action(action, state=state)

        msecs = max(0, int(self.to_seconds(duetime) * 1000.0))
        timer = self._root.after(msecs, invoke_action)

        def dispose() -> None:
            self._root.after_cancel(timer)

        return CompositeDisposable(sad, Disposable(dispose))
Пример #20
0
    def _wxtimer_schedule(self,
                          time: typing.AbsoluteOrRelativeTime,
                          action: typing.ScheduledSingleOrPeriodicAction,
                          state: Optional[typing.TState] = None,
                          periodic: bool = False) -> typing.Disposable:
        scheduler = self

        sad = SingleAssignmentDisposable()

        def interval() -> None:
            nonlocal state
            if periodic:
                state = action(state)
            else:
                sad.disposable = action(scheduler, state)

        msecs = int(self.to_seconds(time) * 1000.0)

        log.debug("timeout wx: %s", msecs)

        timer = self._timer_class(interval)
        timer.Start(
            msecs,
            self.wx.TIMER_CONTINUOUS if periodic else self.wx.TIMER_ONE_SHOT)
        self._timers.add(timer)

        def dispose() -> None:
            timer.Stop()
            self._timers.remove(timer)

        return CompositeDisposable(sad, Disposable(dispose))
Пример #21
0
    def schedule(self,
                 action: typing.ScheduledAction,
                 state: Optional[typing.TState] = None) -> typing.Disposable:
        """Schedules an action to be executed.

        Args:
            action: Action to be executed.
            state: [Optional] state to be given to the action function.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """

        sad = SingleAssignmentDisposable()

        def interval() -> None:
            sad.disposable = self.invoke_action(action, state=state)

        timer = gevent.spawn(interval)

        def dispose() -> None:
            timer.kill()

        return CompositeDisposable(sad, Disposable(dispose))
Пример #22
0
    def _gtk_schedule(self,
                      time: typing.AbsoluteOrRelativeTime,
                      action: typing.ScheduledSingleOrPeriodicAction,
                      state: Optional[typing.TState] = None,
                      periodic: bool = False) -> typing.Disposable:
        # Do not import GLib into global scope because Qt and GLib
        # don't like each other there
        from gi.repository import GLib

        msecs = int(self.to_seconds(time) * 1000.0)

        sad = SingleAssignmentDisposable()

        periodic_state = state
        stopped = False

        def timer_handler(_) -> bool:
            if stopped:
                return False

            if periodic:
                nonlocal periodic_state
                periodic_state = action(periodic_state)
            else:
                sad.disposable = self.invoke_action(action, state=state)

            return periodic

        GLib.timeout_add(msecs, timer_handler, None)

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

        return CompositeDisposable(sad, Disposable(dispose))
Пример #23
0
        def subscribe(
                observer: typing.Observer,
                scheduler: Optional[typing.Scheduler] = None
        ) -> typing.Disposable:
            def handler(*args):
                results = list(args)
                if mapper:
                    try:
                        results = mapper(args)
                    except Exception as err:  # pylint: disable=broad-except
                        observer.on_error(err)
                        return

                    observer.on_next(results)
                else:
                    if isinstance(results, list) and len(results) <= 1:
                        observer.on_next(*results)
                    else:
                        observer.on_next(results)

                    # observer.on_completed()

            arguments.append(handler)
            func(*arguments)
            return Disposable()
Пример #24
0
    def schedule_relative(self, duetime: typing.RelativeTime, action: typing.ScheduledAction,
                          state: typing.TState = None) -> typing.Disposable:
        """Schedules an action to be executed after duetime.

        Args:
            duetime: Relative time after which to execute the action.
            action: Action to be executed.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """

        sad = SingleAssignmentDisposable()

        def invoke_action():
            sad.disposable = self.invoke_action(action, state)

        msecs = int(self.to_seconds(duetime)*1000.0)
        alarm = self.master.after(msecs, invoke_action)

        def dispose():
            self.master.after_cancel(alarm)

        return CompositeDisposable(sad, Disposable(dispose))
Пример #25
0
        def fix_subscriber(subscriber):
            """Fixes subscriber to make sure it returns a Disposable instead
            of None or a dispose function"""
            if not hasattr(subscriber, "dispose"):
                subscriber = Disposable(subscriber)

            return subscriber
Пример #26
0
    def schedule_relative(self,
                          duetime: RelativeTime,
                          action: ScheduledAction,
                          state=None):

        if isinstance(duetime, datetime.datetime):
            timedelta = duetime - datetime.datetime.fromtimestamp(0)
            timespan = float(timedelta.total_seconds())
        elif isinstance(duetime, datetime.timedelta):
            timespan = float(duetime.total_seconds())
        else:
            timespan = duetime

        def _():
            def func():
                action(self, state)

            self.loop.call_later(timespan, func)

        handle = self.loop.call_soon_threadsafe(_)

        def dispose():
            handle.cancel()

        return Disposable(dispose)
Пример #27
0
    def _subscribe_core(self, observer=None, scheduler=None) -> typing.Disposable:
        clock = self.scheduler.to_seconds(self.scheduler.now)
        self.subscriptions.append(Subscription(clock))
        index = len(self.subscriptions) - 1
        disp = CompositeDisposable()

        def get_action(notification):
            def action(scheduler, state):
                notification.accept(observer)
                return Disposable()
            return action

        for message in self.messages:
            notification = message.value

            # Don't make closures within a loop
            action = get_action(notification)
            disp.add(self.scheduler.schedule_relative(message.time, action))

        def dispose() -> None:
            start = self.subscriptions[index].subscribe
            end = self.scheduler.to_seconds(self.scheduler.now)
            self.subscriptions[index] = Subscription(start, end)
            disp.dispose()

        return Disposable(dispose)
Пример #28
0
    def schedule(self,
                 action: typing.ScheduledAction,
                 state: Optional[typing.TState] = None) -> typing.Disposable:
        """Schedules an action to be executed.

        Args:
            action: Action to be executed.
            state: [Optional] state to be given to the action function.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """

        sad = SingleAssignmentDisposable()
        disposed = False

        def interval() -> None:
            if not disposed:
                sad.disposable = self.invoke_action(action, state=state)

        self._loop.add_callback(interval)

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

        return CompositeDisposable(sad, Disposable(dispose))
Пример #29
0
    def schedule_relative(
            self,
            duetime: typing.RelativeTime,
            action: typing.ScheduledAction,
            state: Optional[typing.TState] = None) -> typing.Disposable:
        """Schedules an action to be executed after duetime.

        Args:
            duetime: Relative time after which to execute the action.
            action: Action to be executed.
            state: [Optional] state to be given to the action function.

        Returns:
            The disposable object used to cancel the scheduled action
            (best effort).
        """
        msecs = max(0, int(self.to_seconds(duetime) * 1000.0))
        sad = SingleAssignmentDisposable()
        is_disposed = False

        def invoke_action() -> None:
            if not is_disposed:
                sad.disposable = action(self, state)

        log.debug("relative timeout: %sms", msecs)

        # Use static method, let Qt C++ handle QTimer lifetime
        self._qtcore.QTimer.singleShot(msecs, invoke_action)

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

        return CompositeDisposable(sad, Disposable(dispose))
Пример #30
0
    def subscribe(
            observer: typing.Observer,
            scheduler_: Optional[typing.Scheduler] = None
    ) -> typing.Disposable:
        _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton(
        )
        iterator = iter(iterable)
        disposed = False

        def action(_: typing.Scheduler, __: 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)