Ejemplo n.º 1
0
    def subscribe(observer, scheduler=None):
        scheduler = scheduler or current_thread_scheduler

        subscription = SerialDisposable()
        cancelable = SerialDisposable()
        is_disposed = False

        def action(action1, state=None):
            nonlocal is_disposed
            if is_disposed:
                return

            def on_completed():
                cancelable.disposable = scheduler.schedule(action)

            try:
                current = next(sources_)
            except StopIteration:
                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, observer.on_error, on_completed, scheduler)

        cancelable.disposable = scheduler.schedule(action)

        def dispose():
            nonlocal is_disposed
            is_disposed = True

        return CompositeDisposable(subscription, cancelable, Disposable(dispose))
Ejemplo n.º 2
0
    def subscribe(observer, scheduler=None):
        scheduler = scheduler or current_thread_scheduler

        subscription = SerialDisposable()
        cancelable = SerialDisposable()
        last_exception = [None]
        is_disposed = []

        def action(action1, state=None):
            def on_error(exn):
                last_exception[0] = exn
                cancelable.disposable = scheduler.schedule(action)

            if is_disposed:
                return

            try:
                current = next(sources)
            except StopIteration:
                if last_exception[0]:
                    observer.on_error(last_exception[0])
                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():
            is_disposed.append(True)
        return CompositeDisposable(subscription, cancelable, Disposable(dispose))
Ejemplo n.º 3
0
    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)
Ejemplo n.º 4
0
        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)
Ejemplo n.º 5
0
        def run(self):
            self.subscription = SerialDisposable()
            self.timer = SerialDisposable()
            original = SingleAssignmentDisposable()

            self.subscription.disposable = original

            self.gate = RLock()
            self.currentId = 0
            self.switched = False

            self.createTimer()

            original.disposable = self.parent.source.subscribeSafe(self)

            return CompositeDisposable(self.subscription, self.timer)
    def test_return_disposed_after_next(self):
        scheduler = TestScheduler()
        d = SerialDisposable()
        xs = rx.return_value(42)
        results = scheduler.create_observer()

        def action(scheduler, state):
            def on_next(x):
                d.dispose()
                results.on_next(x)

            def on_error(e):
                results.on_error(e)

            def on_completed():
                results.on_completed()

            d.disposable = xs.subscribe(on_next,
                                        on_error,
                                        on_completed,
                                        scheduler=scheduler)
            return d.disposable

        scheduler.schedule_absolute(100, action)
        scheduler.start()
        assert results.messages == [on_next(100, 42)]
Ejemplo n.º 7
0
        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)
Ejemplo n.º 8
0
        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)
Ejemplo n.º 9
0
    def run(self, sources):
        self.isDisposed = False
        self.subscription = SerialDisposable()
        self.gate = AsyncLock()
        self.stack = []
        self.length = []

        self.stack.append(iter(sources))

        try:
            length = len(sources)
        except TypeError:
            self.length.append(-1)
        else:
            self.length.append(length)

        def scheduled(continuation):
            self.recurse = continuation
            self.gate.wait(self.moveNext)

        cancel = Scheduler.tailRecursion.scheduleRecursive(scheduled)

        return CompositeDisposable(
            self.subscription, cancel,
            Disposable.create(lambda: self.gate.wait(self.dispose)))
Ejemplo n.º 10
0
        def subscribe(observer, scheduler=None) -> Disposable:
            cancelable = SerialDisposable()
            has_value = [False]
            value = [None]
            _id = [0]

            def on_next(x):
                throttle = None
                try:
                    throttle = throttle_duration_mapper(x)
                except Exception as e:  # pylint: disable=broad-except
                    observer.on_error(e)
                    return

                has_value[0] = True
                value[0] = x
                _id[0] += 1
                current_id = _id[0]
                d = SingleAssignmentDisposable()
                cancelable.disposable = d

                def on_next(x: Any) -> None:
                    if has_value[0] and _id[0] == current_id:
                        observer.on_next(value[0])

                    has_value[0] = False
                    d.dispose()

                def on_completed() -> None:
                    if has_value[0] and _id[0] == current_id:
                        observer.on_next(value[0])

                    has_value[0] = False
                    d.dispose()

                d.disposable = throttle.subscribe_(on_next,
                                                   observer.on_error,
                                                   on_completed,
                                                   scheduler=scheduler)

            def on_error(e) -> None:
                cancelable.dispose()
                observer.on_error(e)
                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)
Ejemplo n.º 11
0
    def subscribe(observer, scheduler=None):
        d1 = SingleAssignmentDisposable()
        subscription = SerialDisposable()

        subscription.disposable = d1

        def on_error(exception):
            try:
                result = handler(exception, source)
            except Exception as ex:  # By design. pylint: disable=W0703
                observer.on_error(ex)
                return

            result = rx.from_future(result) if is_future(result) else result
            d = SingleAssignmentDisposable()
            subscription.disposable = d
            d.disposable = result.subscribe(observer, scheduler=scheduler)

        d1.disposable = source.subscribe_(
            observer.on_next,
            on_error,
            observer.on_completed,
            scheduler
        )
        return subscription
        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
Ejemplo n.º 13
0
    def test_starmap_dispose_inside_mapper(self):
        scheduler = TestScheduler()
        xs = scheduler.create_hot_observable(
            # 100 create
            on_next(110, (1, 10)),
            # 200 subscribe
            on_next(210, (2, 20)),
            on_next(310, (3, 30)),
            on_next(410, (4, 40)))

        results = scheduler.create_observer()
        d = SerialDisposable()
        invoked = [0]

        def mapper(x, y):
            invoked[0] += 1
            if scheduler.clock > 250:
                d.dispose()
            return x + y

        d.disposable = xs.pipe(ops.starmap(mapper)).subscribe(
            results, scheduler)

        def action(scheduler, state):
            return d.dispose()

        scheduler.schedule_absolute(ReactiveTest.disposed, action)
        scheduler.start()

        assert results.messages == [on_next(110, 11), on_next(210, 22)]

        assert xs.subscriptions == [ReactiveTest.subscribe(0, 310)]
        assert invoked[0] == 3
Ejemplo n.º 14
0
    def test_map_disposeinsidemapper(self):
        scheduler = TestScheduler()
        xs = scheduler.create_hot_observable(on_next(100, 1), on_next(200, 2),
                                             on_next(500, 3), on_next(600, 4))
        results = scheduler.create_observer()
        d = SerialDisposable()
        invoked = [0]

        def projection(x, *args, **kw):
            invoked[0] += 1

            if scheduler.clock > 400:
                d.dispose()
            return x

        d.disposable = xs.pipe(map(projection)).subscribe(results, scheduler)

        def action(scheduler, state):
            return d.dispose()

        scheduler.schedule_absolute(ReactiveTest.disposed, action)
        scheduler.start()

        assert results.messages == [on_next(100, 1), on_next(200, 2)]
        assert xs.subscriptions == [ReactiveTest.subscribe(0, 500)]

        assert invoked[0] == 3
Ejemplo n.º 15
0
    def test_map_with_index_dispose_inside_mapper(self):
        scheduler = TestScheduler()
        xs = scheduler.create_hot_observable(on_next(100, 4), on_next(200, 3),
                                             on_next(500, 2), on_next(600, 1))
        invoked = [0]
        results = scheduler.create_observer()
        d = SerialDisposable()

        def projection(x, index):
            invoked[0] += 1
            if scheduler.clock > 400:
                d.dispose()

            return x + index * 10

        d.disposable = xs.pipe(map_indexed(projection)).subscribe(results)

        def action(scheduler, state):
            return d.dispose()

        scheduler.schedule_absolute(disposed, action)
        scheduler.start()
        assert results.messages == [on_next(100, 4), on_next(200, 13)]
        assert xs.subscriptions == [subscribe(0, 500)]
        assert invoked[0] == 3
Ejemplo n.º 16
0
        def run(self):
            self.subscription = SerialDisposable()

            d = SingleAssignmentDisposable()
            self.subscription.disposable = d
            d.disposable = self.parent.source.subscribeSafe(self)

            return self.subscription
Ejemplo n.º 17
0
        def subscribe(observer, scheduler=None):
            scheduler = scheduler or immediate_scheduler

            queue = []
            m = SerialDisposable()
            d = CompositeDisposable(m)
            active_count = [0]
            is_acquired = [False]

            def ensure_active():
                is_owner = False
                if queue:
                    is_owner = not is_acquired[0]
                    is_acquired[0] = True

                def action(scheduler, state):
                    if queue:
                        work = queue.pop(0)
                    else:
                        is_acquired[0] = False
                        return

                    sad = SingleAssignmentDisposable()
                    d.add(sad)

                    def on_next(value):
                        observer.on_next(value)
                        result = None
                        try:
                            result = mapper(value)
                        except Exception as ex:
                            observer.on_error(ex)
                            return

                        queue.append(result)
                        active_count[0] += 1
                        ensure_active()

                    def on_complete():
                        d.remove(sad)
                        active_count[0] -= 1
                        if active_count[0] == 0:
                            observer.on_completed()

                    sad.disposable = work.subscribe_(on_next,
                                                     observer.on_error,
                                                     on_complete, scheduler)
                    m.disposable = scheduler.schedule(action)

                if is_owner:
                    m.disposable = scheduler.schedule(action)

            queue.append(source)
            active_count[0] += 1
            ensure_active()
            return d
Ejemplo n.º 18
0
    def run(self):
      self.gate = RLock()
      self.value = None
      self.hasValue = False
      self.throttleDisposable = SerialDisposable()
      self.resourceId = 0

      subscription = self.parent.source.subscribeSafe(self)

      return CompositeDisposable(subscription, self.throttleDisposable)
Ejemplo n.º 19
0
        def subscribe(observer, _=None):
            m = SingleAssignmentDisposable()
            d = SerialDisposable()
            d.disposable = m

            def action(scheduler, state):
                d.disposable = ScheduledDisposable(scheduler,
                                                   source.subscribe(observer))

            m.disposable = scheduler.schedule(action)
            return d
Ejemplo n.º 20
0
    def __init__(self, scheduler: typing.Scheduler, single: Single) -> None:
        super().__init__()

        self.scheduler = scheduler
        self.single = single

        self.lock = threading.RLock()
        self.is_acquired = False
        self.has_faulted = False
        self.queue: List[typing.Action] = []
        self.disposable = SerialDisposable()
Ejemplo n.º 21
0
    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))
Ejemplo n.º 22
0
        def run(self):
            self.gate = RLock()
            self.list = []
            self.n = 0
            self.windowId = 0

            self.timerDisposable = SerialDisposable()
            self.createTimer(0)

            subscription = self.parent.source.subscribeSafe(self)

            return CompositeDisposable(self.timerDisposable, subscription)
Ejemplo n.º 23
0
    def __init__(self, scheduler: abc.Scheduler,
                 observer: abc.Observer) -> None:
        super().__init__()

        self.scheduler = scheduler
        self.observer = observer

        self.lock = threading.RLock()
        self.is_acquired = False
        self.has_faulted = False
        self.queue: List[Action] = []
        self.disposable = SerialDisposable()
Ejemplo n.º 24
0
        def run(self):
            self.gate = RLock()
            self.innerSubscription = SerialDisposable()
            self.isStopped = False
            self.latest = 0
            self.hasLatest = False

            self.subscription = SingleAssignmentDisposable()
            self.subscription.disposable = self.parent.sources.subscribeSafe(
                self)

            return CompositeDisposable(self.subscription,
                                       self.innerSubscription)
Ejemplo n.º 25
0
        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)
Ejemplo n.º 26
0
        def subscribe(observer, scheduler=None):
            inner_subscription = SerialDisposable()
            has_latest = [False]
            is_stopped = [False]
            latest = [0]

            def on_next(inner_source: Union[Observable, Future]):
                nonlocal source

                d = SingleAssignmentDisposable()
                with source.lock:
                    latest[0] += 1
                    _id = latest[0]
                has_latest[0] = True
                inner_subscription.disposable = d

                # Check if Future or Observable
                if is_future(inner_source):
                    obs = from_future(cast(Future, inner_source))
                else:
                    obs = cast(Observable, inner_source)

                def on_next(x: Any) -> None:
                    if latest[0] == _id:
                        observer.on_next(x)

                def on_error(e: Exception) -> None:
                    if latest[0] == _id:
                        observer.on_error(e)

                def on_completed() -> None:
                    if latest[0] == _id:
                        has_latest[0] = False
                        if is_stopped[0]:
                            observer.on_completed()

                d.disposable = obs.subscribe_(on_next,
                                              on_error,
                                              on_completed,
                                              scheduler=scheduler)

            def on_completed() -> None:
                is_stopped[0] = True
                if not has_latest[0]:
                    observer.on_completed()

            subscription = source.subscribe_(on_next,
                                             observer.on_error,
                                             on_completed,
                                             scheduler=scheduler)
            return CompositeDisposable(subscription, inner_subscription)
Ejemplo n.º 27
0
  def __init__(self, scheduler, observer):
    super(ScheduledObserver, self).__init__()
    self.scheduler = scheduler
    self.observer = observer
    self.state = Atomic(ScheduledObserver.STOPPED, self.lock)
    self.disposable = SerialDisposable()

    self.failed = False
    self.exception = None
    self.completed = False

    self.queue = Queue()
    self.dispatcherJob = None
    self.dispatcherEvent = Semaphore(0)
Ejemplo n.º 28
0
        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)
Ejemplo n.º 29
0
        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)
Ejemplo n.º 30
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