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
def test_groupdisposable_contains(): d1 = Disposable() d2 = Disposable() g = CompositeDisposable(d1, d2) assert g.length == 2 assert g.contains(d1) assert g.contains(d2)
def test_Disposable_dispose(): disposed = [False] def action(): disposed[0] = True d = Disposable(action) assert not disposed[0] d.dispose() assert disposed[0]
def action_dispose( scheduler: abc.SchedulerBase, state: Any = None ) -> abc.DisposableBase: """Called at dispose time. Defaults to 1000""" if subscription: subscription.dispose() return Disposable()
def schedule_relative( self, duetime: typing.RelativeTime, action: typing.ScheduledAction[_TState], state: Optional[_TState] = None, ) -> abc.DisposableBase: """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 seconds <= 0.0: 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 = self._loop.call_later(seconds, interval) def dispose() -> None: self._loop.remove_timeout(timer) self._loop.remove_timeout(timer) return CompositeDisposable(sad, Disposable(dispose))
def schedule(self, action: typing.ScheduledAction[_TState], state: Optional[_TState] = None) -> abc.DisposableBase: """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 = self._eventlet.spawn(interval) def dispose() -> None: timer.kill() return CompositeDisposable(sad, Disposable(dispose))
def schedule_relative( self, duetime: typing.RelativeTime, action: typing.ScheduledAction[_TState], state: Optional[_TState] = None, ) -> abc.DisposableBase: """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))
def schedule_relative( self, duetime: typing.RelativeTime, action: typing.ScheduledAction[_TState], state: Optional[_TState] = None, ) -> abc.DisposableBase: """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))
def _subscribe_core( self, observer: Optional[abc.ObserverBase[_T]] = None, scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: self.subscriptions.append(Subscription(self.scheduler.clock)) index = len(self.subscriptions) - 1 disp = CompositeDisposable() def get_action( notification: Notification[_T]) -> abc.ScheduledAction[_T]: def action(scheduler: abc.SchedulerBase, state: Any = None) -> abc.DisposableBase: if observer: notification.accept(observer) return Disposable() return action for message in self.messages: notification = message.value if not isinstance(notification, Notification): raise ValueError("Must be notification") # 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, int(end)) disp.dispose() return Disposable(dispose)
def schedule_relative( self, duetime: typing.RelativeTime, action: typing.ScheduledAction[_TState], state: Optional[_TState] = None, ) -> abc.DisposableBase: """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 = max(0.0, self.to_seconds(duetime)) sad = SingleAssignmentDisposable() def interval() -> None: sad.disposable = action(self, state) log.debug("timeout: %s", seconds) timer = self._reactor.callLater(seconds, interval) def dispose() -> None: if not timer.called: timer.cancel() return CompositeDisposable(sad, Disposable(dispose))
def action_create( scheduler: abc.SchedulerBase, state: Any = None ) -> abc.DisposableBase: """Called at create time. Defaults to 100""" nonlocal source source = create() if create is not None else reactivex.never() return Disposable()
def schedule(self, action: typing.ScheduledAction[_TState], state: Optional[_TState] = None) -> abc.DisposableBase: """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() is_disposed = False def invoke_action() -> None: if not is_disposed: sad.disposable = action(self, state) self._wx.CallAfter(invoke_action) def dispose() -> None: nonlocal is_disposed is_disposed = True return CompositeDisposable(sad, Disposable(dispose))
def schedule(self, action: typing.ScheduledAction[_TState], state: Optional[_TState] = None) -> abc.DisposableBase: """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: if self._on_self_loop_or_not_running(): handle.cancel() return future: "Future[int]" = 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))
def _subscribe_core( self, observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: return self._subscribe(observer, scheduler) if self._subscribe else Disposable()
def subscribe( observer: abc.ObserverBase[Any], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: def handler(*args: Any) -> None: 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 len(results) <= 1: observer.on_next(*results) else: observer.on_next(results) observer.on_completed() arguments.append(handler) func(*arguments) return Disposable()
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)
def action_subscribe( scheduler: abc.SchedulerBase, state: Any = None ) -> abc.DisposableBase: """Called at subscribe time. Defaults to 200""" nonlocal subscription if source: subscription = source.subscribe(observer, scheduler=scheduler) return Disposable()
def wrapped_action( self: abc.SchedulerBase, state: Optional[_TState]) -> Optional[abc.DisposableBase]: try: return action(parent._get_recursive_wrapper(self), state) except Exception as ex: if not parent._handler(ex): raise return Disposable()
def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: return CompositeDisposable( merged_disposable.disposable if merged_disposable else Disposable(), underlying_observable.subscribe(observer, scheduler=scheduler), )
def schedule_relative( self, duetime: typing.RelativeTime, action: typing.ScheduledAction[_TState], state: Optional[_TState] = None, ) -> abc.DisposableBase: """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 seconds <= 0: return self.schedule(action, state=state) sad = SingleAssignmentDisposable() def interval() -> None: sad.disposable = self.invoke_action(action, state=state) # the operations on the list used here are atomic, so there is no # need to protect its access with a lock handle: List[asyncio.Handle] = [] def stage2() -> None: handle.append(self._loop.call_later(seconds, interval)) handle.append(self._loop.call_soon_threadsafe(stage2)) def dispose() -> None: def do_cancel_handles() -> None: try: handle.pop().cancel() handle.pop().cancel() except Exception: pass if self._on_self_loop_or_not_running(): do_cancel_handles() return future: "Future[int]" = Future() def cancel_handle() -> None: do_cancel_handles() future.set_result(0) self._loop.call_soon_threadsafe(cancel_handle) future.result() return CompositeDisposable(sad, Disposable(dispose))
def schedule_absolute(self, due: AbsoluteTime, action: ScheduledAction, state: Optional[TState] = None) -> Disposable: item = ScheduledItem(self, state, action, self.to_datetime(due)) self._queue.put(item) return Disposable(item.cancel)
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 test_groupdisposable_addafterdispose(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable(action1) def action2(): disp2[0] = True d2 = Disposable(action2) g = CompositeDisposable(d1) assert g.length == 1 g.dispose() assert disp1[0] assert g.length == 0 g.add(d2) assert disp2[0] assert g.length == 0
def test_mutabledisposable_replacebeforedispose(): disp1 = [False] disp2 = [False] m = SerialDisposable() def action1(): disp1[0] = True d1 = Disposable(action1) m.disposable = d1 assert d1 == m.disposable assert not disp1[0] def action2(): disp2[0] = True d2 = Disposable(action2) m.disposable = d2 assert d2 == m.disposable assert disp1[0] assert not disp2[0]
def test_mutabledisposable_replaceafterdispose(): disp1 = [False] disp2 = [False] m = SerialDisposable() m.dispose() def action1(): disp1[0] = True d1 = Disposable(action1) m.disposable = d1 assert m.disposable == None assert disp1[0] def action2(): disp2[0] = True d2 = Disposable(action2) m.disposable = d2 assert m.disposable == None assert disp2[0]
def test_groupdisposable_remove(): 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 assert g.contains(d1) assert g.contains(d2) assert g.remove(d1) assert g.length == 1 assert not g.contains(d1) assert g.contains(d2) assert disp1[0] assert g.remove(d2) assert not g.contains(d1) assert not g.contains(d2) assert disp2[0] disp3 = [False] def action3(): disp3[0] = True d3 = Disposable(action3) assert not g.remove(d3) assert not disp3[0]
def test_mutabledisposable_dispose(): disp = [False] m = SerialDisposable() def action(): disp[0] = True d = Disposable(action) m.disposable = d assert d == m.disposable assert not disp[0] m.dispose() assert disp[0] assert m.disposable == None
def test_futuredisposable_disposeafterset(): d = SingleAssignmentDisposable() disposed = [False] def action(): disposed[0] = True dd = Disposable(action) d.disposable = dd assert dd == d.disposable assert not disposed[0] d.dispose() assert disposed[0] d.dispose() assert disposed[0]
def subscribe( observer: abc.ObserverBase[_T], scheduler: Optional[abc.SchedulerBase] = None, ) -> abc.DisposableBase: try: subscription = source.subscribe(observer, scheduler=scheduler) except Exception: action() raise def dispose(): try: subscription.dispose() finally: action() return Disposable(dispose)
def test_futuredisposable_disposebeforeset(): disposed = [False] def dispose(): disposed[0] = True d = SingleAssignmentDisposable() dd = Disposable(dispose) assert not disposed[0] d.dispose() assert not disposed[0] d.disposable = dd assert d.disposable == None assert disposed[0] d.dispose() assert disposed[0]