def test_groupdisposable_clear(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable.create(action1) def action2(): disp2[0] = True d2 = Disposable.create(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.create(action3) g.add(d3); assert not disp3[0] assert g.length == 1
def test_groupdisposable_remove(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable.create(action1) def action2(): disp2[0] = True d2 = Disposable.create(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.create(action3) assert not g.remove(d3) assert not disp3[0]
def test_groupdisposable_clear(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable.create(action1) def action2(): disp2[0] = True d2 = Disposable.create(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.create(action3) g.add(d3) assert not disp3[0] assert g.length == 1
def test_groupdisposable_contains(): d1 = Disposable.empty() d2 = Disposable.empty() g = CompositeDisposable(d1, d2) assert g.length == 2 assert g.contains(d1) assert g.contains(d2)
def _subscribe_core(self, observer): 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.empty() observer.on_completed() return Disposable.empty()
def schedule_relative(self, duetime: Union[int, float], action: Callable[[SchedulerBase, Any], None], state=None): if isinstance(duetime, datetime.datetime): timespan = duetime - datetime.datetime.fromtimestamp(0) timespan = int(timespan.total_seconds()) elif isinstance(duetime, datetime.timedelta): timespan = int(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.create(dispose)
def _gtk_schedule(self, time, action, state, periodic=False): scheduler = self msecs = self.to_relative(time) disposable = SingleAssignmentDisposable() periodic_state = [state] stopped = [False] def timer_handler(_): if stopped[0]: return False if periodic: periodic_state[0] = action(periodic_state[0]) else: disposable.disposable = action(scheduler, state) return periodic GLib.timeout_add(msecs, timer_handler, None) def dispose(): stopped[0] = True return CompositeDisposable(disposable, Disposable.create(dispose))
def schedule_periodic(self, period, action, state=None): """Schedules a periodic piece of work by dynamically discovering the schedulers capabilities. Keyword arguments: period -- Period for running the work periodically. action -- Action to be executed. state -- [Optional] Initial state passed to the action upon the first iteration. Returns the disposable object used to cancel the scheduled recurring action (best effort).""" period /= 1000.0 timer = [None] s = [state] def interval(): new_state = action(s[0]) if new_state is not None: # Update state if other than None s[0] = new_state timer[0] = Timer(period, interval) timer[0].setDaemon(True) timer[0].start() timer[0] = Timer(period, interval) timer[0].setDaemon(True) timer[0].start() def dispose(): timer[0].cancel() return Disposable.create(dispose)
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_relative(duetime) / 1000.0 if not seconds: return scheduler.schedule(action, state) disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = action(scheduler, state) log.debug("timeout: %s", seconds) timer = [gevent.spawn_later(seconds, interval)] def dispose(): # nonlocal timer timer[0].kill() return CompositeDisposable(disposable, Disposable.create(dispose))
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 = self.to_relative(time) disposable = SingleAssignmentDisposable() periodic_state = [state] stopped = [False] def timer_handler(_): if stopped[0]: return False if periodic: periodic_state[0] = action(periodic_state[0]) else: disposable.disposable = action(scheduler, state) return periodic GLib.timeout_add(msecs, timer_handler, None) def dispose(): stopped[0] = True return CompositeDisposable(disposable, Disposable.create(dispose))
def wrapped_action(self, state): try: return action(parent._get_recursive_wrapper(self), state) except Exception as ex: if not parent._handler(ex): raise Exception(ex) return Disposable.empty()
def schedule_periodic(self, period, action, state=None): """Schedules a periodic piece of work to be executed in the tkinter mainloop. Keyword arguments: period -- Period in milliseconds for running the work periodically. action -- Action to be executed. state -- [Optional] Initial state passed to the action upon the first iteration. Returns the disposable object used to cancel the scheduled recurring action (best effort).""" state = [state] def interval(): state[0] = action(state[0]) alarm[0] = self.master.after(period, interval) log.debug("timeout: %s", period) alarm = [self.master.after(period, interval)] def dispose(): # nonlocal alarm self.master.after_cancel(alarm[0]) return Disposable.create(dispose)
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 msecs = self.to_relative(duetime) if msecs == 0: return scheduler.schedule(action, state) disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = self.invoke_action(action, state) log.debug("timeout: %s", msecs) alarm = self.master.after(msecs, interval) def dispose(): # nonlocal alarm self.master.after_cancel(alarm) return CompositeDisposable(disposable, Disposable.create(dispose))
def unsafe_subscribe(self, observer: Observer, scheduler: SchedulerBase, subscribe_scheduler: SchedulerBase): state = self.state subscribers = state.subscribers subscriber = self.Subscriber(observer, subscribe_scheduler) if isinstance(subscribers, self.Empty): self.on_subscribe_completed(subscriber, state.error_thrown) else: update_set = subscribers | {subscriber} update = self.State(subscribers=update_set) with self.lock: if self.state is state: is_updated = True self.state = update else: is_updated = False if is_updated: def dispose(): self.unsubscribe(subscriber) disposable = Disposable.create(dispose) return disposable else: return self.unsafe_subscribe(observer, scheduler, subscribe_scheduler)
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).""" from twisted.internet.task import deferLater scheduler = self seconds = self.to_relative(duetime) / 1000.0 disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = action(scheduler, state) log.debug("timeout: %s", seconds) handle = deferLater(self.reactor, seconds, interval).addErrback(lambda _: None) def dispose(): if not handle.called: handle.cancel() return CompositeDisposable(disposable, Disposable.create(dispose))
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).""" from twisted.internet.task import deferLater scheduler = self seconds = self.to_relative(duetime)/1000.0 disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = action(scheduler, state) log.debug("timeout: %s", seconds) handle = deferLater(self.reactor, seconds, interval).addErrback(lambda _: None) def dispose(): if not handle.called: handle.cancel() return CompositeDisposable(disposable, Disposable.create(dispose))
def _schedule_relative_threadsafe(self, duetime, action, state=None): scheduler = self seconds = self.to_relative(duetime) / 1000.0 if seconds == 0: return scheduler.schedule(action, state) disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = self.invoke_action(action, state) # the operations on the list used here are atomic, so there is no # need to protect its access with a lock handle = [] def stage2(): handle.append(self.loop.call_later(seconds, interval)) handle.append(self.loop.call_soon_threadsafe(stage2)) def dispose(): future = Future() def cancel_handle(): try: handle.pop().cancel() handle.pop().cancel() except Exception: pass future.set_result(0) self.loop.call_soon_threadsafe(cancel_handle) future.result() return CompositeDisposable(disposable, Disposable.create(dispose))
def schedule_periodic(self, period, action, state=None): """Schedules an action to be executed periodically. Keyword arguments: period -- Period for running the work periodically. action -- {Function} Action to be executed. state -- [Optional] Initial state passed to the action upon the first iteration. Returns {Disposable} The disposable object used to cancel the scheduled action (best effort).""" scheduler = self seconds = self.to_relative(period) / 1000.0 if seconds == 0: return scheduler.schedule(action, state) def interval(): new_state = action(state) scheduler.schedule_periodic(period, action, new_state) handle = [self.loop.call_later(seconds, interval)] def dispose(): # nonlocal handle handle[0].cancel() return Disposable.create(dispose)
def schedule_periodic(self, period, action, state=None): """Schedules a periodic piece of work by dynamically discovering the schedulers capabilities. Keyword arguments: period -- Period for running the work periodically. action -- Action to be executed. state -- [Optional] Initial state passed to the action upon the first iteration. Returns the disposable object used to cancel the scheduled recurring action (best effort).""" scheduler = self seconds = self.to_relative(period)/1000.0 if not seconds: return scheduler.schedule(action, state) def interval(): new_state = action(scheduler, state) scheduler.schedule_periodic(period, action, new_state) log.debug("timeout: %s", seconds) timer = [eventlet.spawn_after(seconds, interval)] def dispose(): timer[0].kill() return Disposable.create(dispose)
def _qtimer_schedule(self, time, action, state, periodic=False): scheduler = self msecs = self.to_relative(time) disposable = SingleAssignmentDisposable() periodic_state = [state] def interval(): if periodic: periodic_state[0] = action(periodic_state[0]) else: disposable.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(disposable, Disposable.create(dispose))
def subscribe(observer): enum = iter(sources) is_disposed = [False] subscription = SerialDisposable() def action(action1, state=None): if is_disposed[0]: return try: current = next(enum) except StopIteration: observer.on_completed() except Exception as ex: observer.on_error(ex) else: d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe( observer.on_next, observer.on_error, lambda: action1() ) cancelable = immediate_scheduler.schedule_recursive(action) def dispose(): is_disposed[0] = True return CompositeDisposable(subscription, cancelable, Disposable.create(dispose))
def subscribe(observer): subscription = SerialDisposable() cancelable = SerialDisposable() enum = iter(sources) is_disposed = [] def action(action1, state=None): if is_disposed: return def on_completed(): cancelable.disposable = scheduler.schedule(action) try: current = next(enum) except StopIteration: observer.on_completed() except Exception as ex: observer.on_error(ex) else: d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe(observer.on_next, observer.on_error, on_completed) cancelable.disposable = scheduler.schedule(action) def dispose(): is_disposed.append(True) return CompositeDisposable(subscription, cancelable, Disposable.create(dispose))
def _wxtimer_schedule(self, time, action, state, periodic=False): scheduler = self msecs = self.to_relative(time) disposable = SingleAssignmentDisposable() periodic_state = [state] def interval(): if periodic: periodic_state[0] = action(periodic_state[0]) else: disposable.disposable = action(scheduler, state) log.debug("timeout: %s", msecs) 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(disposable, Disposable.create(dispose))
def _wxtimer_schedule(self, time, action, state, periodic=False): scheduler = self msecs = self.to_relative(time) disposable = SingleAssignmentDisposable() periodic_state = [state] def interval(): if periodic: periodic_state[0] = action(periodic_state[0]) else: disposable.disposable = action(scheduler, state) log.debug("timeout: %s", msecs) 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(disposable, Disposable.create(dispose))
def schedule_relative(self, duetime, action, state=None): """Schedules an action to be executed at 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_relative(duetime) / 1000.0 if seconds == 0: return scheduler.schedule(action, state) disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = self.invoke_action(action, state) handle = [self.loop.call_later(seconds, interval)] def dispose(): # nonlocal handle handle[0].cancel() return CompositeDisposable(disposable, Disposable.create(dispose))
def schedule_periodic(self, period, action, state=None): """Schedule a periodic piece of work.""" secs = self.to_relative(period) / 1000.0 disposed = [] s = [state] def run(): 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.create(dispose)
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_relative(duetime)/1000.0 if not seconds: return scheduler.schedule(action, state) disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = self.invoke_action(action, state) log.debug("timeout: %s", seconds) timer = [eventlet.spawn_after(seconds, interval)] def dispose(): # nonlocal timer timer[0].kill() return CompositeDisposable(disposable, Disposable.create(dispose))
def _subscribe_core(self, observer): clock = self.scheduler.to_relative(self.scheduler.now) self.subscriptions.append(Subscription(clock)) index = len(self.subscriptions) - 1 disposable = CompositeDisposable() def get_action(notification): def action(scheduler, state): notification.accept(observer) return Disposable.empty() return action for message in self.messages: notification = message.value # Don't make closures within a loop action = get_action(notification) disposable.add(self.scheduler.schedule_relative(message.time, action)) def dispose(): start = self.subscriptions[index].subscribe end = self.scheduler.to_relative(self.scheduler.now) self.subscriptions[index] = Subscription(start, end) disposable.dispose() return Disposable.create(dispose)
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_relative(duetime) / 1000.0 if not seconds: return scheduler.schedule(action, state) disposable = SingleAssignmentDisposable() def interval(): disposable.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(disposable, Disposable.create(dispose))
def schedule_relative(self, duetime, action, state=None): """Schedules an action to be executed at 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_relative(duetime)/1000.0 if seconds == 0: return scheduler.schedule(action, state) disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = self.invoke_action(action, state) handle = self.loop.call_later(seconds, interval) def dispose(): handle.cancel() return CompositeDisposable(disposable, Disposable.create(dispose))
def subscribe(self, observer: Observer = None, scheduler: Scheduler = None) -> Disposable: stream = Filter._(self.predicate, self.predicate_indexed).chain(observer, scheduler) stream.subscription = self.source.subscribe(stream, scheduler) return Disposable.create(stream.dispose)
def schedule_work(_, state3): action(state3, inner_action) if is_added: group.remove(d) else: is_done[0] = True return Disposable.empty()
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.create(subscriber) return subscriber
def unsafe_subscribe(self, observer: Observer, scheduler: SchedulerBase, subscribe_scheduler: SchedulerBase): """ Creates a new ConnectableSubscriber for each subscription, pushes the current buffer to the ConnectableSubscriber and connects it immediately """ def stream_on_done(buffer: Iterable, error_thrown: Exception = None) -> Disposable: class TObserver(Observer): def on_next(self, v): ack = observer.on_next(v) return ack def on_error(self, err): observer.on_error(err) def on_completed(self): if error_thrown is not None: observer.on_error(error_thrown) else: observer.on_completed() return IteratorAsObservable(iter(buffer)) \ .subscribe(TObserver(), scheduler, CurrentThreadScheduler()) state = self.state buffer = state.buffer if state.is_done: return stream_on_done(buffer, state.error_thrown) else: c = ConnectableSubscriber(observer, scheduler=scheduler) with self.lock: new_state = self.state.add_new_subscriber(c) self.state = new_state c.push_first_all(buffer) ack, disposable = c.connect() if isinstance(ack, Stop): self.remove_subscriber(c) elif not isinstance(ack, Continue): def on_next(v): if isinstance(v, Stop): self.remove_subscriber(c) ack.subscribe(on_next=on_next) def _(): try: self.remove_subscriber(c) finally: disposable.signal_stop() return Disposable.create(_)
def test_anonymousdisposable_dispose(): disposed = [False] def action(): disposed[0] = True d = Disposable.create(action) assert not disposed[0] d.dispose() assert disposed[0]
def disposable(self): """Returns a dependent disposable that when disposed decreases the refcount on the underlying disposable.""" with self.lock: if self.is_disposed: return Disposable.empty() self.count += 1 return self.InnerDisposable(self)
def disposable(self): """Returns a dependent disposable that when disposed decreases the refcount on the underlying disposable.""" with self.lock: if self.is_disposed: return Disposable.empty() else: self.count += 1 return self.InnerDisposable(self)
def __init__(self, enable_queue=True, scheduler=None): super(ControlledSubject, self).__init__(self._subscribe) self.subject = Subject() self.enable_queue = enable_queue self.queue = [] if enable_queue else None self.requested_count = 0 self.requested_disposable = Disposable.empty() self.error = None self.has_failed = False self.has_completed = False self.scheduler = scheduler or current_thread_scheduler
def test_mutabledisposable_replacebeforedispose(): disp1 = [False] disp2 = [False] m = SerialDisposable() def action1(): disp1[0] = True d1 = Disposable.create(action1) m.disposable = d1 assert d1 == m.disposable assert not disp1[0] def action2(): disp2[0] = True d2 = Disposable.create(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.create(action1) m.disposable = d1 assert m.disposable == None assert disp1[0] def action2(): disp2[0] = True d2 = Disposable.create(action2) m.disposable = d2 assert m.disposable == None assert disp2[0]
def schedule(self, action, state=None): """Schedules an action to be executed.""" disposable = SingleAssignmentDisposable() def interval(): disposable.disposable = self.invoke_action(action, state) handle = self.loop.call_soon(interval) def dispose(): handle.cancel() return CompositeDisposable(disposable, Disposable.create(dispose))
def subscribe(observer): disposable = Disposable.empty() try: resource = resource_factory() if resource: disposable = resource source = observable_factory(resource) except Exception as exception: d = Observable.throw_exception(exception).subscribe(observer) return CompositeDisposable(d, disposable) return CompositeDisposable(source.subscribe(observer), disposable)
def connect(self): """Connects the observable.""" if not self.has_subscription: self.has_subscription = True def dispose(): self.has_subscription = False disposable = self.source.subscribe(self.subject) self.subscription = CompositeDisposable(disposable, Disposable.create(dispose)) return self.subscription
def _subscribe_core(self, observer): observable = self self.observers.append(observer) self.subscriptions.append(Subscription(self.scheduler.clock)) index = len(self.subscriptions) - 1 def dispose_action(): observable.observers.remove(observer) start = observable.subscriptions[index].subscribe end = observable.scheduler.clock observable.subscriptions[index] = Subscription(start, end) return Disposable.create(dispose_action)
def test_groupdisposable_addafterdispose(): disp1 = [False] disp2 = [False] def action1(): disp1[0] = True d1 = Disposable.create(action1) def action2(): disp2[0] = True d2 = Disposable.create(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