def test_currentthread_schedule(self): scheduler = CurrentThreadScheduler() ran = False def action(scheduler, state=None): nonlocal ran ran = True scheduler.schedule(action) assert ran is True
def test_currentthread_schedule_error(self): scheduler = CurrentThreadScheduler() class MyException(Exception): pass def action(scheduler, state=None): raise MyException() with pytest.raises(MyException): scheduler.schedule(action)
def test_currentthread_schedule_block(self): scheduler = CurrentThreadScheduler() ran = False def action(scheduler, state=None): nonlocal ran ran = True t = scheduler.now scheduler.schedule_relative(0.2, action) t = scheduler.now - t assert ran is True assert t >= timedelta(seconds=0.2)
def test_currentthread_schedule_nested(self): scheduler = CurrentThreadScheduler() ran = False def action(scheduler, state=None): def inner_action(scheduler, state=None): nonlocal ran ran = True return scheduler.schedule(inner_action) scheduler.schedule(action) assert ran is True
def outer(scheduler, state=None): def action1(scheduler, state=None): tests.append(1) def action2(scheduler, state=None): tests.append(2) CurrentThreadScheduler().schedule(action2) CurrentThreadScheduler().schedule(action1) def action3(scheduler, state=None): tests.append(3) CurrentThreadScheduler().schedule(action3)
def test_currentthread_now_units(self): scheduler = CurrentThreadScheduler() diff = scheduler.now sleep(1.1) diff = scheduler.now - diff assert timedelta(milliseconds=1000) < diff < timedelta( milliseconds=1300)
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)
def subscribe(observer, scheduler=None): scheduler = scheduler or CurrentThreadScheduler.singleton() 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): scheduler = scheduler or CurrentThreadScheduler.singleton() first = True state = initial_state mad = MultipleAssignmentDisposable() def action(scheduler, state1=None): nonlocal first nonlocal state has_result = False result = None try: if first: first = False else: state = iterate(state) has_result = condition(state) if has_result: result = state except Exception as exception: # pylint: disable=broad-except observer.on_error(exception) return if has_result: observer.on_next(result) mad.disposable = scheduler.schedule(action) else: observer.on_completed() mad.disposable = scheduler.schedule(action) return mad
def test_currentthread_singleton(self): scheduler = [CurrentThreadScheduler(), CurrentThreadScheduler()] assert scheduler[0] is scheduler[1] gate = [threading.Semaphore(0), threading.Semaphore(0)] scheduler = [None, None] def run(idx): scheduler[idx] = CurrentThreadScheduler() 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 not scheduler[1]
def on_subscribe(observer, scheduler): nonlocal sink_observer nonlocal sink_scheduler sink_observer = observer sink_scheduler = scheduler or CurrentThreadScheduler() def dispose(): nonlocal sink_observer sink_observer = None return dispose
def test_currentthread_ensuretrampoline_nested(self): scheduler = CurrentThreadScheduler() ran1, ran2 = False, False def outer_action(scheduler, state): def inner_action1(scheduler, state): nonlocal ran1 ran1 = True scheduler.schedule(inner_action1) def inner_action2(scheduler, state): nonlocal ran2 ran2 = True return scheduler.schedule(inner_action2) scheduler.ensure_trampoline(outer_action) assert ran1 is True assert ran2 is True
def test_currentthread_ensuretrampoline_and_cancel(self): scheduler = CurrentThreadScheduler() ran1, ran2 = False, False def outer_action(scheduler, state): def inner_action1(scheduler, state): nonlocal ran1 ran1 = True def inner_action2(scheduler, state): nonlocal ran2 ran2 = True d = scheduler.schedule(inner_action2) d.dispose() return scheduler.schedule(inner_action1) scheduler.ensure_trampoline(outer_action) assert ran1 is True assert ran2 is False
def subscribe( observer: typing.Observer, scheduler_: Optional[typing.Scheduler] = None ) -> typing.Disposable: _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton( ) def action(scheduler: typing.Scheduler, state: Any = None): observer.on_next(value) observer.on_completed() return _scheduler.schedule(action)
def test_currentthread_extend(self): class MyScheduler(CurrentThreadScheduler): pass scheduler = [ MyScheduler(), MyScheduler.singleton(), MyScheduler.singleton(), CurrentThreadScheduler.singleton(), ] assert scheduler[0] is not scheduler[1] assert scheduler[1] is scheduler[2] assert scheduler[1] is not scheduler[3]
def test_currentthread_schedule_nested_order(self): scheduler = CurrentThreadScheduler() tests = [] def outer(scheduler, state=None): def action1(scheduler, state=None): tests.append(1) def action2(scheduler, state=None): tests.append(2) CurrentThreadScheduler().schedule(action2) CurrentThreadScheduler().schedule(action1) def action3(scheduler, state=None): tests.append(3) CurrentThreadScheduler().schedule(action3) scheduler.ensure_trampoline(outer) assert tests == [1, 2, 3]
def subscribe(observer: typing.Observer, scheduler_: typing.Scheduler = None): _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton( ) def action(_: Scheduler, __: Any = None): nonlocal observer try: observer.on_next(supplier()) observer.on_completed() except Exception as e: # pylint: disable=broad-except observer.on_error(e) return _scheduler.schedule(action)
def subscribe(observer, scheduler_: typing.Scheduler = None): nonlocal range_t _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton( ) sd = MultipleAssignmentDisposable() def action(scheduler, iterator): try: observer.on_next(next(iterator)) sd.disposable = _scheduler.schedule(action, state=iterator) except StopIteration: observer.on_completed() sd.disposable = _scheduler.schedule(action, iter(range_t)) return sd
def subscribe(observer, scheduler): scheduler = scheduler or CurrentThreadScheduler.singleton() def action(scheduler, state): self.task() def dispose() -> None: import traceback traceback.print_stack() print("--------> dispose called <----------------") # nonlocal disposed # disposed = True # scheduler.schedule(action) return CompositeDisposable(scheduler.schedule(action), Disposable(dispose))
def test_route_error(self): actual_sequence = [] def on_chain_item(i): nonlocal actual_sequence actual_sequence.append(i) sink, route_error = make_error_router() origin = rx.from_([rx.just(1), rx.throw(-1)]).pipe( route_error(error_map=lambda e: e.args[0] * 100), ) result = rx.merge(origin, sink) disposable = result.subscribe(on_chain_item, scheduler=CurrentThreadScheduler()) disposable.dispose() expected_sequence = [1, -100] self.assertEqual(actual_sequence, expected_sequence)
def subscribe(observer: ObserverType, scheduler: Optional[SchedulerType] = None) -> DisposableType: # _scheduler = scheduler or scheduler_ or CurrentThreadScheduler.singleton() scheduler = scheduler or CurrentThreadScheduler.singleton() # iterator = iter(iterable) disposed = False def action(_: SchedulerType, __: Any = None) -> None: nonlocal disposed print("logoutTask/subscribe", threading.currentThread()) print("a") observer.on_next("Started") print("b") observer.on_next("Started 2") print("c") print("calling on_next") time.sleep(0.2) if disposed: pass print("d") observer.on_next("Logging out...") time.sleep(1) print("e") observer.on_next("Almost done") time.sleep(1) # raise Exception("Gnit happened") observer.on_completed() def dispose() -> None: import traceback traceback.print_stack() print("--------> dispose called <----------------") nonlocal disposed disposed = True disp = Disposable(dispose) return CompositeDisposable(scheduler.schedule(action), disp)
def __init__(self, buffer_size: int = None, window: typing.RelativeTime = None, scheduler: Optional[typing.Scheduler] = None ) -> None: """Initializes a new instance of the ReplaySubject class with the specified buffer size, window and scheduler. Args: buffer_size: [Optional] Maximum element count of the replay buffer. window [Optional]: Maximum time length of the replay buffer. scheduler: [Optional] Scheduler the observers are invoked on. """ super().__init__() self.buffer_size = sys.maxsize if buffer_size is None else buffer_size self.scheduler = scheduler or CurrentThreadScheduler.singleton() self.window = timedelta.max if window is None else self.scheduler.to_timedelta(window) self.queue: List[QueueItem] = []
def subscribe(observer, scheduler_=None): _scheduler = scheduler_ or CurrentThreadScheduler.singleton() subscription = SerialDisposable() cancelable = SerialDisposable() last_exception = None is_disposed = False def action(action1, state=None): def on_error(exn): nonlocal last_exception last_exception = exn cancelable.disposable = _scheduler.schedule(action) if is_disposed: return try: current = next(sources_) except StopIteration: if last_exception: observer.on_error(last_exception) else: observer.on_completed() except Exception as ex: # pylint: disable=broad-except observer.on_error(ex) else: d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe_(observer.on_next, on_error, observer.on_completed, scheduler_) cancelable.disposable = _scheduler.schedule(action) def dispose(): nonlocal is_disposed is_disposed = True return CompositeDisposable(subscription, cancelable, Disposable(dispose))
def on_subscribe(observer, scheduler_): disposed = False _scheduler = scheduler_ or CurrentThreadScheduler.singleton() def _action(_, __): nonlocal disposed def read_data(f): nonlocal disposed if size is None: data = f.read(size) observer.on_next(data) else: data = f.read(size) while not disposed and len(data) > 0: observer.on_next(data) data = f.read(size) try: if type(file) is str: with open(file, mode, encoding=encoding) as f: read_data(f) else: read_data(file) observer.on_completed() except Exception as e: observer.on_error(e) def _dispose(): nonlocal disposed disposed = True disp = Disposable(_dispose) return CompositeDisposable(_scheduler.schedule(_action), disp)
def run(idx): scheduler[idx] = CurrentThreadScheduler.singleton() gate[idx].release()
def subscribe_( self, on_next: Optional[typing.OnNext] = None, on_error: Optional[typing.OnError] = None, on_completed: Optional[typing.OnCompleted] = None, scheduler: Optional[typing.Scheduler] = None) -> typing.Disposable: """Subscribe callbacks to the observable sequence. Examples: >>> source.subscribe_(on_next) >>> source.subscribe_(on_next, on_error) >>> source.subscribe_(on_next, on_error, on_completed) Args: on_next: [Optional] Action to invoke for each element in the observable sequence. on_error: [Optional] Action to invoke upon exceptional termination of the observable sequence. on_completed: [Optional] Action to invoke upon graceful termination of the observable sequence. scheduler: [Optional] The scheduler to use for this subscription. Returns: Disposable object representing an observer's subscription to the observable sequence. """ auto_detach_observer = AutoDetachObserver(on_next, on_error, on_completed) 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 def set_disposable(_: abc.Scheduler = None, __: Any = None): try: subscriber = self._subscribe_core(auto_detach_observer, scheduler) except Exception as ex: # By design. pylint: disable=W0703 if not auto_detach_observer.fail(ex): raise else: auto_detach_observer.subscription = fix_subscriber(subscriber) # Subscribe needs to set up the trampoline before for subscribing. # Actually, the first call to Subscribe creates the trampoline so # that it may assign its disposable before any observer executes # OnNext over the CurrentThreadScheduler. This enables single- # threaded cancellation # https://social.msdn.microsoft.com/Forums/en-US/eb82f593-9684-4e27- # 97b9-8b8886da5c33/whats-the-rationale-behind-how-currentthreadsche # dulerschedulerequired-behaves?forum=rx current_thread_scheduler = CurrentThreadScheduler.singleton() if current_thread_scheduler.schedule_required(): current_thread_scheduler.schedule(set_disposable) else: set_disposable() # Hide the identity of the auto detach observer return Disposable(auto_detach_observer.dispose)
def test_currentthread_now(self): scheduler = CurrentThreadScheduler() diff = scheduler.now - default_now() assert abs(diff) < timedelta(milliseconds=1)