def test_timeout_schedule_action(self): scheduler = TimeoutScheduler() ran = False def action(scheduler, state): nonlocal ran ran = True scheduler.schedule(action) sleep(0.1) assert ran is True
def test_timeout_schedule_action_cancel(self): ran = False scheduler = TimeoutScheduler() def action(scheduler, state): nonlocal ran ran = True d = scheduler.schedule_relative(timedelta(milliseconds=1), action) d.dispose() sleep(0.1) assert ran is False
def test_timeout_schedule_action_due(self): scheduler = TimeoutScheduler() starttime = default_now() endtime = None def action(scheduler, state): nonlocal endtime endtime = default_now() scheduler.schedule_relative(timedelta(milliseconds=200), action) sleep(0.3) assert endtime is not None diff = endtime - starttime assert diff > timedelta(milliseconds=180)
def subscribe(observer, scheduler_=None): nonlocal duration _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) duration = _scheduler.to_timedelta(duration) q = [] def on_next(x): now = _scheduler.now q.append({"interval": now, "value": x}) while q and now - q[0]["interval"] >= duration: q.pop(0) def on_completed(): now = _scheduler.now while q: _next = q.pop(0) if now - _next["interval"] <= duration: observer.on_next(_next["value"]) observer.on_completed() return source.subscribe_(on_next, observer.on_error, on_completed, scheduler_)
def test_timeout_now_units(self): scheduler = TimeoutScheduler() diff = scheduler.now sleep(1.1) diff = scheduler.now - diff assert timedelta(milliseconds=1000) < diff < timedelta( milliseconds=1300)
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton() nonlocal duetime if not isinstance(duetime, datetime): duetime = _scheduler.now + _scheduler.to_timedelta(duetime) p = max(0.0, _scheduler.to_seconds(period)) mad = MultipleAssignmentDisposable() dt = duetime count = 0 def action(scheduler, state): nonlocal dt nonlocal count if p > 0.0: now = scheduler.now dt = dt + scheduler.to_timedelta(p) if dt <= now: dt = now + scheduler.to_timedelta(p) observer.on_next(count) count += 1 mad.disposable = scheduler.schedule_absolute(dt, action) mad.disposable = _scheduler.schedule_absolute(dt, action) return mad
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) duration = _scheduler.to_timedelta(window_duration or 0.0) if duration <= _scheduler.to_timedelta(0): raise ValueError( 'window_duration cannot be less or equal zero.') last_on_next = [0] def on_next(x): emit = False now = _scheduler.now with source.lock: if not last_on_next[0] or now - last_on_next[0] >= duration: last_on_next[0] = now emit = True if emit: observer.on_next(x) return source.subscribe_(on_next, observer.on_error, observer.on_completed, scheduler=_scheduler)
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 subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton() def action(scheduler, state): observer.on_next(0) observer.on_completed() return _scheduler.schedule_absolute(duetime, action)
def mapper_to_observable(value): def initializing_mapper(): sepal.drive.InitializeThread(credentials) return mapper(value) return of(True).pipe( delay(0.1, TimeoutScheduler()), flat_map(lambda _: from_callable(initializing_mapper, _drive_executions.scheduler)))
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) def action(count): observer.on_next(count) return count + 1 return _scheduler.schedule_periodic(period, action, state=0)
def test_timeout_singleton(self): scheduler = [TimeoutScheduler(), TimeoutScheduler.singleton()] assert scheduler[0] is scheduler[1] gate = [threading.Semaphore(0), threading.Semaphore(0)] scheduler = [None, None] def run(idx): scheduler[idx] = TimeoutScheduler() 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 scheduler[1]
def do_retry(source, tries, exception): if tries <= retries: logging.warning( 'retry_with_backoff(tries={}, retries={}, exception={}, description={})' .format(tries, retries, exception, description)) return of(None).pipe( delay(backoff(tries), TimeoutScheduler()), flat_map(source), catch(handler=lambda e, src: do_retry(src, tries + 1, e))) else: return throw(exception)
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) def action(scheduler, state): observer.on_completed() disp = _scheduler.schedule_relative(duration, action) return CompositeDisposable( disp, source.subscribe(observer, scheduler=scheduler_))
def test_timeout_extend(self): class MyScheduler(TimeoutScheduler): pass scheduler = [ MyScheduler(), MyScheduler.singleton(), TimeoutScheduler.singleton(), ] assert scheduler[0] is scheduler[1] assert scheduler[0] is not scheduler[2]
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton() d = _scheduler.to_seconds(duetime) def action(scheduler, state): observer.on_next(0) observer.on_completed() if d <= 0.0: return _scheduler.schedule(action) return _scheduler.schedule_relative(d, action)
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) if isinstance(duetime, datetime): scheduler_method = _scheduler.schedule_absolute else: scheduler_method = _scheduler.schedule_relative switched = [False] _id = [0] original = SingleAssignmentDisposable() subscription = SerialDisposable() timer = SerialDisposable() subscription.disposable = original def create_timer(): my_id = _id[0] def action(scheduler, state=None): switched[0] = (_id[0] == my_id) timer_wins = switched[0] if timer_wins: subscription.disposable = obs.subscribe( observer, scheduler=scheduler) timer.disposable = scheduler_method(duetime, action) create_timer() def on_next(value): send_wins = not switched[0] if send_wins: _id[0] += 1 observer.on_next(value) create_timer() def on_error(error): on_error_wins = not switched[0] if on_error_wins: _id[0] += 1 observer.on_error(error) def on_completed(): on_completed_wins = not switched[0] if on_completed_wins: _id[0] += 1 observer.on_completed() original.disposable = source.subscribe_(on_next, on_error, on_completed, scheduler_) return CompositeDisposable(subscription, timer)
def subscribe(observer, scheduler_): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) last = _scheduler.now def mapper(value): nonlocal last now = _scheduler.now span = now - last last = now return TimeInterval(value=value, interval=span) return source.pipe(ops.map(mapper)).subscribe(observer, scheduler_)
def subscribe(observer, scheduler_=None) -> Disposable: _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) cancelable = SerialDisposable() button_state = [None] press_time: List[float] = [0.] def set_state(state): button_state[0] = state observer.on_next(button_state[0]) set_state(ROOM['notPressed']) def on_next(x: Any) -> None: now = time.time() if button_state[0] == ROOM['notPressed']: set_state(ROOM['pressed']) press_time[0] = now elif button_state[0] == ROOM['pressed']: if now > press_time[0] + min_hold_sec: set_state(ROOM['held']) # should be pressed AND held elif button_state[0] == ROOM['held']: pass else: raise NotImplementedError(f'button_state={button_state}') d = SingleAssignmentDisposable() cancelable.disposable = d def action(scheduler, state=None) -> None: if button_state[0] != ROOM['notPressed']: set_state(ROOM['notPressed']) d.disposable = _scheduler.schedule_relative( release_after_sec, action) def on_error(exception: Exception) -> None: cancelable.dispose() observer.on_error(exception) def on_completed() -> None: raise NotImplementedError subscription = source.subscribe_(on_next, on_error, on_completed, scheduler=scheduler_) return CompositeDisposable(subscription, cancelable)
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) if isinstance(end_time, datetime): scheduler_method = _scheduler.schedule_absolute else: scheduler_method = _scheduler.schedule_relative def action(scheduler, state): observer.on_completed() task = scheduler_method(end_time, action) return CompositeDisposable( task, source.subscribe(observer, scheduler=scheduler_))
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) open = [False] def action(scheduler, state): open[0] = True t = _scheduler.schedule_relative(duration, action) def on_next(x): if open[0]: observer.on_next(x) d = source.subscribe_(on_next, observer.on_error, observer.on_completed, scheduler_) return CompositeDisposable(t, d)
def subscribe(observer, scheduler_=None): _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) open = [False] def on_next(x): if open[0]: observer.on_next(x) subscription = source.subscribe_(on_next, observer.on_error, observer.on_completed, scheduler_) def action(scheduler, state): open[0] = True disp = getattr(_scheduler, scheduler_method)(start_time, action) return CompositeDisposable(disp, subscription)
def subscribe(observer, scheduler_=None) -> Disposable: _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton( ) cancelable = SerialDisposable() has_value = [False] value = [None] _id = [0] def on_next(x: Any) -> None: has_value[0] = True value[0] = x _id[0] += 1 current_id = _id[0] d = SingleAssignmentDisposable() cancelable.disposable = d def action(scheduler, state=None) -> None: if has_value[0] and _id[0] == current_id: observer.on_next(value[0]) has_value[0] = False d.disposable = _scheduler.schedule_relative(duetime, action) def on_error(exception: Exception) -> None: cancelable.dispose() observer.on_error(exception) has_value[0] = False _id[0] += 1 def on_completed() -> None: cancelable.dispose() if has_value[0]: observer.on_next(value[0]) observer.on_completed() has_value[0] = False _id[0] += 1 subscription = source.subscribe_(on_next, on_error, on_completed, scheduler=scheduler_) return CompositeDisposable(subscription, cancelable)
def subscribe(observer, scheduler=None): scheduler = scheduler or TimeoutScheduler.singleton() mad = MultipleAssignmentDisposable() state = initial_state has_result = False result = None first = True time = None def action(scheduler, _): nonlocal state nonlocal has_result nonlocal result nonlocal first nonlocal time if has_result: observer.on_next(result) try: if first: first = False else: state = iterate(state) has_result = condition(state) if has_result: result = state time = time_mapper(state) except Exception as e: # pylint: disable=broad-except observer.on_error(e) return if has_result: mad.disposable = scheduler.schedule_relative(time, action) else: observer.on_completed() mad.disposable = scheduler.schedule_relative(0, action) return mad
def _to_async(func: Callable, scheduler: Optional[Scheduler] = None) -> Callable: """Converts the function into an asynchronous function. Each invocation of the resulting asynchronous function causes an invocation of the original synchronous function on the specified scheduler. Examples: res = rx.to_async(lambda x, y: x + y)(4, 3) res = rx.to_async(lambda x, y: x + y, Scheduler.timeout)(4, 3) res = rx.to_async(lambda x: log.debug(x), Scheduler.timeout)('hello') Args: func: Function to convert to an asynchronous function. scheduler: [Optional] Scheduler to run the function on. If not specified, defaults to Scheduler.timeout. Returns: Aynchronous function. """ _scheduler = scheduler or TimeoutScheduler.singleton() def wrapper(*args) -> Observable: subject = AsyncSubject() def action(scheduler, state): try: result = func(*args) except Exception as ex: # pylint: disable=broad-except subject.on_error(ex) return subject.on_next(result) subject.on_completed() _scheduler.schedule(action) return subject.pipe(ops.as_observable()) return wrapper
def test_timeout_now(self): scheduler = TimeoutScheduler() diff = scheduler.now - default_now() assert abs(diff) < timedelta(milliseconds=1)
def schedule(): credentials = get_credentials() return rx.interval(period, TimeoutScheduler()).pipe( do_action(lambda _: ee.InitializeThread(credentials)), )
def subscribe(observer, scheduler_=None): nonlocal duetime _scheduler = scheduler or scheduler_ or TimeoutScheduler.singleton() if isinstance(duetime, datetime): duetime = _scheduler.to_datetime(duetime) - _scheduler.now else: duetime = _scheduler.to_timedelta(duetime) cancelable = SerialDisposable() exception = [None] active = [False] running = [False] queue = [] def on_next(notification): should_run = False with source.lock: if notification.value.kind == 'E': del queue[:] queue.append(notification) exception[0] = notification.value.exception should_run = not running[0] else: queue.append( Timestamp(value=notification.value, timestamp=notification.timestamp + duetime)) should_run = not active[0] active[0] = True if should_run: if exception[0]: observer.on_error(exception[0]) else: mad = MultipleAssignmentDisposable() cancelable.disposable = mad def action(scheduler, state): if exception[0]: return with source.lock: running[0] = True while True: result = None if queue and queue[ 0].timestamp <= scheduler.now: result = queue.pop(0).value if result: result.accept(observer) if not result: break should_continue = False recurse_duetime = 0 if queue: should_continue = True diff = queue[0].timestamp - scheduler.now zero = DELTA_ZERO if isinstance( diff, timedelta) else 0 recurse_duetime = max(zero, diff) else: active[0] = False ex = exception[0] running[0] = False if ex: observer.on_error(ex) elif should_continue: mad.disposable = scheduler.schedule_relative( recurse_duetime, action) mad.disposable = _scheduler.schedule_relative( duetime, action) subscription = source.pipe(ops.materialize(), ops.timestamp()).subscribe_( on_next, scheduler=scheduler_) return CompositeDisposable(subscription, cancelable)
def run(idx): scheduler[idx] = TimeoutScheduler() gate[idx].release()
def schedule(): return rx.interval(period, TimeoutScheduler.singleton()).pipe( do_action(lambda _: ee.InitializeThread(credentials)), )