def run(self): self.delays = CompositeDisposable() self.gate = RLock() self.atEnd = False self.subscription = SerialDisposable() if self.parent.subscriptionDelay == None: self.start() else: self.subscription.disposable = self.parent.subscriptionDelay.subscribeSafe( self.Sigma(self)) return CompositeDisposable(self.subscription, self.delays)
def subscribe(observer, scheduler=None): disp = Disposable() try: resource = resource_factory() if resource is not None: disp = resource source = observable_factory(resource) except Exception as exception: # pylint: disable=broad-except d = rx.throw(exception).subscribe(observer, scheduler=scheduler) return CompositeDisposable(d, disp) return CompositeDisposable(source.subscribe(observer, scheduler=scheduler), disp)
def subscribe(observer, scheduler=None): delays = CompositeDisposable() at_end = [False] def done(): if (at_end[0] and delays.length == 0): observer.on_completed() subscription = SerialDisposable() def start(): def on_next(x): try: delay = mapper(x) except Exception as error: observer.on_error(error) return d = SingleAssignmentDisposable() delays.add(d) def on_next(_): observer.on_next(x) delays.remove(d) done() def on_completed(): observer.on_next(x) delays.remove(d) done() d.disposable = delay.subscribe_(on_next, observer.on_error, on_completed, scheduler) def on_completed(): at_end[0] = True subscription.dispose() done() subscription.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) if not sub_delay: start() else: subscription.disposable(sub_delay.subscribe_( lambda _: start(), observer.on_error, start)) return CompositeDisposable(subscription, delays)
def run(self): source = None disposable = Disposable.empty() try: resource = self.parent.resourceFactory() if resource != None: disposable = resource source = self.parent.observableFactory(resource) except Exception as e: return CompositeDisposable( Observable.throw(e).subscribeSafe(self), disposable) return CompositeDisposable(source.subscribeSafe(self), disposable)
def on_subscribe(observer, scheduler): def on_next(i): if type(i) is rs.OnNextMux: observer.on_next(i._replace(key=i.key[1])) elif type(i) is rs.OnErrorMux: observer.on_error(i.error) ''' elif type(i) is rs.OnCreateMux: observer.on_next(rs.OnCreateMux(i.key[1])) elif type(i) is rs.OnCompletedMux: observer.on_next(rs.OnCompletedMux(i.key[1])) else: observer.on_next(TypeError("flatten_aggregate: unknow item type: {}".format(type(i)))) ''' def on_next_outer(i): observer.on_next(i) disposable = CompositeDisposable() disposable.add( outer_group.subscribe( on_next=on_next_outer, scheduler=scheduler, )) disposable.add( source.subscribe( on_next=on_next, on_completed=observer.on_completed, on_error=observer.on_error, scheduler=scheduler, )) return disposable
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton() n = [0] s = [None] timer_d = SerialDisposable() window_id = [0] group_disposable = CompositeDisposable(timer_d) ref_count_disposable = RefCountDisposable(group_disposable) def create_timer(_id): m = SingleAssignmentDisposable() timer_d.disposable = m def action(scheduler, state): if _id != window_id[0]: return n[0] = 0 window_id[0] += 1 new_id = window_id[0] s[0].on_completed() s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) create_timer(new_id) m.disposable = _scheduler.schedule_relative(timespan, action) s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) create_timer(0) def on_next(x): new_window = False new_id = 0 s[0].on_next(x) n[0] += 1 if n[0] == count: new_window = True n[0] = 0 window_id[0] += 1 new_id = window_id[0] s[0].on_completed() s[0] = Subject() observer.on_next(add_ref(s[0], ref_count_disposable)) if new_window: create_timer(new_id) def on_error(e): s[0].on_error(e) observer.on_error(e) def on_completed(): s[0].on_completed() observer.on_completed() group_disposable.add(source.subscribe_(on_next, on_error, on_completed, scheduler_)) return ref_count_disposable
def run(self): self.scheduler = self.parent.scheduler self.cancelTimer = SerialDisposable() self.gate = RLock() self.active = False # as soon as a value arrived self.running = False # on relative: True, on absolute: True after absolute time self.queue = deque() self.hasCompleted = False self.completeAt = 0 self.hasFailed = False self.exception = None self.delay = 0 self.startTime = self.scheduler.now() if self.parent.isAbsolute: self.ready = False self.cancelTimer.disposable = self.scheduler.scheduleWithAbsolute( self.parent.dueTime, self.start) else: self.ready = True self.delay = Scheduler.normalize(self.parent.dueTime) self.sourceSubscription = SingleAssignmentDisposable() self.sourceSubscription.disposable = self.parent.source.subscribeSafe( self) return CompositeDisposable(self.sourceSubscription, self.cancelTimer)
def subscribe(self, single: Single) -> rx.typing.Disposable: @dataclass class ReduceZipSinlge(Single): acc: List[Any] counter: List[int] func: Callable[[Any, Any], Any] lock: threading.RLock def on_next(self, elem): with self.lock: self.acc[0] = self.func(self.acc[0], elem) counter = self.counter[0] self.counter[0] = counter - 1 if counter == 1: single.on_next(self.acc[0]) def gen_disposables(): for source in self.sources: yield source.subscribe( ReduceZipSinlge( lock=self.lock, func=self.func, acc=self.acc, counter=self.counter, )) return CompositeDisposable(list(gen_disposables()))
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))
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))
def subscribe(observer, scheduler=None): scheduler = scheduler or current_thread_scheduler subscription = SerialDisposable() cancelable = SerialDisposable() def action(scheduler, state=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 = rx.from_future(source) if is_future(source) else source d = SingleAssignmentDisposable() subscription.disposable = d def on_resume(state=None): scheduler.schedule(action, state) d.disposable = current.subscribe_(observer.on_next, on_resume, on_resume, scheduler) cancelable.disposable = scheduler.schedule(action) return CompositeDisposable(subscription, cancelable)
def subscribe(observer, scheduler=None): was_invoked = [False] def on_completed(): observer.on_completed() try: if not was_invoked[0]: finally_action() was_invoked[0] = True except Exception as err: # pylint: disable=broad-except observer.on_error(err) def on_error(exception): observer.on_error(exception) try: if not was_invoked[0]: finally_action() was_invoked[0] = True except Exception as err: # pylint: disable=broad-except observer.on_error(err) composite_disposable = CompositeDisposable() composite_disposable.add(OnDispose(was_invoked)) subscription = source.subscribe_(observer.on_next, on_error, on_completed, scheduler) composite_disposable.add(subscription) return composite_disposable
def run(self): srcs = list(self.parent.sources) N = len(srcs) self.queues = [None] * N self.isDone = [False] * N self.subscriptions = [None] * N self.gate = RLock() for i in range(0, N): self.queues[i] = deque() # Loop twice because subscribing could already yield # a value before all queues are initialized for i in range(0, N): d = SingleAssignmentDisposable() self.subscriptions[i] = d o = self.O(self, i) d.disposable = srcs[i].subscribeSafe(o) c = CompositeDisposable(self.subscriptions) def dispose(): for q in self.queues: q.clear() c.add(Disposable.create(dispose)) return c
def subscribe(observer, scheduler=None): composite_disposable = CompositeDisposable() composite_disposable.add(OnDispose()) subscription = source.subscribe_(observer.on_next, observer.on_error, observer.on_completed, scheduler) composite_disposable.add(subscription) return composite_disposable
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))
def run(self): self.scheduler = self.parent.scheduler self.cancelTimer = SerialDisposable() self.gate = RLock() self.evt = Semaphore(0) self.stopped = False self.stop = Event() self.queue = deque() self.hasCompleted = False self.completeAt = 0 self.hasFailed = False self.exception = None self.delay = 0 self.startTime = self.scheduler.now() if self.parent.isAbsolute: self.cancelTimer.disposable = self.scheduler.scheduleAbsolute( self.parent.dueTime, self.start) else: self.delay = Scheduler.normalize(self.parent.dueTime) self.scheduleDrain() self.sourceSubscription = SingleAssignmentDisposable() self.sourceSubscription.disposable = self.parent.source.subscribeSafe( self) return CompositeDisposable(self.sourceSubscription, self.cancelTimer)
def from_marbles(string: str, timespan: RelativeTime = 0.1, lookup: Dict = None, error: Optional[Exception] = None, scheduler: Optional[Scheduler] = None) -> Observable: disp = CompositeDisposable() messages = parse(string, timespan=timespan, lookup=lookup, error=error, raise_stopped=True) def schedule_msg(message, observer, scheduler): timespan, notification = message def action(scheduler, state=None): notification.accept(observer) disp.add(scheduler.schedule_relative(timespan, action)) def subscribe(observer, scheduler_): _scheduler = scheduler or scheduler_ or new_thread_scheduler for message in messages: # Don't make closures within a loop schedule_msg(message, observer, _scheduler) return disp return Observable(subscribe)
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))
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))
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))
def setUp(self) -> None: self.source = TestFlowable() self.scheduler = TScheduler() self.composite_disposable = CompositeDisposable() self.sink1 = TObserver() self.sink2 = TObserver() self.sink3 = TObserver()
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))
def subscribe(observer, scheduler=None): def subscribe_all(parent, *children): values = [NO_VALUE for _ in children] def subscribe_child(i, child): subscription = SingleAssignmentDisposable() def on_next(value): with parent.lock: values[i] = value subscription.disposable = child.subscribe_(on_next, observer.on_error, scheduler=scheduler) return subscription parent_subscription = SingleAssignmentDisposable() def on_next(value): with parent.lock: if NO_VALUE not in values: result = (value,) + tuple(values) observer.on_next(result) disp = parent.subscribe_(on_next, observer.on_error, observer.on_completed, scheduler) parent_subscription.disposable = disp children_subscription = [subscribe_child(i, child) for i, child in enumerate(children)] return [parent_subscription] + children_subscription return CompositeDisposable(subscribe_all(parent, *sources))
def subscribe(observer, scheduler=None): group = CompositeDisposable() is_stopped = [False] m = SingleAssignmentDisposable() group.add(m) def on_next(inner_source): inner_subscription = SingleAssignmentDisposable() group.add(inner_subscription) inner_source = from_future(inner_source) if is_future( inner_source) else inner_source @synchronized(source.lock) def on_completed(): group.remove(inner_subscription) if is_stopped[0] and len(group) == 1: observer.on_completed() on_next = synchronized(source.lock)(observer.on_next) on_error = synchronized(source.lock)(observer.on_error) subscription = inner_source.subscribe_(on_next, on_error, on_completed, scheduler) inner_subscription.disposable = subscription def on_completed(): is_stopped[0] = True if len(group) == 1: observer.on_completed() m.disposable = source.subscribe_(on_next, observer.on_error, on_completed, scheduler) return group
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))
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))
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)
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))
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 subscribe(observer, scheduler=None): window_subject = Subject() d = CompositeDisposable() r = RefCountDisposable(d) observer.on_next(add_ref(window_subject, r)) def on_next_window(x): window_subject.on_next(x) def on_error(err): window_subject.on_error(err) observer.on_error(err) def on_completed(): window_subject.on_completed() observer.on_completed() d.add( source.subscribe_(on_next_window, on_error, on_completed, scheduler)) def on_next_observer(w): nonlocal window_subject window_subject.on_completed() window_subject = Subject() observer.on_next(add_ref(window_subject, r)) d.add( boundaries.subscribe_(on_next_observer, on_error, on_completed, scheduler)) return r