def time_interval(self, scheduler): """Records the time interval between consecutive values in an observable sequence. 1 - res = source.time_interval(); 2 - res = source.time_interval(Scheduler.timeout) Keyword arguments: scheduler -- [Optional] Scheduler used to compute time intervals. If not specified, the timeout scheduler is used. Return An observable sequence with time interval information on values. """ source = self scheduler = scheduler or timeout_scheduler def defer(): last = [scheduler.now] def selector(x): now = scheduler.now span = now - last[0] last[0] = now return TimeInterval(value=x, interval=span) return source.map(selector) return Observable.defer(defer)
def case(mapper, sources, default_source=None) -> ObservableBase: """Uses mapper to determine which source in sources to use. Example: 1 - res = rx.Observable.case(mapper, { '1': obs1, '2': obs2 }) 2 - res = rx.Observable.case(mapper, { '1': obs1, '2': obs2 }, obs0) Keyword arguments: mapper -- The function which extracts the value for to test in a case statement. sources -- An object which has keys which correspond to the case statement labels. default_source -- The observable sequence or Future that will be run if the sources are not matched. If this is not provided, it defaults to rx.Observabe.empty. Returns an observable sequence which is determined by a case statement. """ default_source = default_source or Observable.empty() def factory(_) -> ObservableBase: try: result = sources[mapper()] except KeyError: result = default_source result = Observable.from_future(result) if is_future( result) else result return result return Observable.defer(factory)
def if_then(condition: Callable[[], bool], then_source: ObservableBase, else_source: ObservableBase = None) -> ObservableBase: """Determines whether an observable collection contains values. Example: 1 - res = rx.Observable.if(condition, obs1) 2 - res = rx.Observable.if(condition, obs1, obs2) Keyword parameters: condition -- The condition which determines if the then_source or else_source will be run. then_source -- The observable sequence or Promise that will be run if the condition function returns true. else_source -- [Optional] The observable sequence or Promise that will be run if the condition function returns False. If this is not provided, it defaults to rx.Observable.empty Returns an observable sequence which is either the then_source or else_source. """ else_source = else_source or Observable.empty() then_source = Observable.from_future(then_source) if is_future( then_source) else then_source else_source = Observable.from_future(else_source) if is_future( else_source) else else_source def factory(_: abc.Scheduler): return then_source if condition() else else_source return Observable.defer(factory)
def observable_timer_timespan_and_period(duetime, period, scheduler): if duetime == period: def subscribe(observer): def action(count): observer.on_next(count) return count + 1 return scheduler.schedule_periodic(period, action, state=0) return AnonymousObservable(subscribe) def defer(): dt = scheduler.now + scheduler.to_timedelta(duetime) return observable_timer_date_and_period(dt, period, scheduler) return Observable.defer(defer)
def repeat(self, repeat_count=None): """Repeats the observable sequence a specified number of times. If the repeat count is not specified, the sequence repeats indefinitely. 1 - repeated = source.repeat() 2 - repeated = source.repeat(42) Keyword arguments: repeat_count -- Number of times to repeat the sequence. If not provided, repeats the sequence indefinitely. Returns the observable sequence producing the elements of the given sequence repeatedly.""" return Observable.defer(lambda: Observable.concat(Enumerable.repeat(self, repeat_count)))
def many_select(self, selector, scheduler=None): """Comonadic bind operator. Internally projects a new observable for each value, and it pushes each observable into the user-defined selector function that projects/queries each observable into some result. Keyword arguments: selector -- {Function} A transform function to apply to each element. scheduler -- {Object} [Optional] Scheduler used to execute the operation. If not specified, defaults to the ImmediateScheduler. Returns {Observable} An observable sequence which results from the comonadic bind operation. """ scheduler = scheduler or immediate_scheduler source = self def factory(): chain = [None] def mapper(x): curr = ChainObservable(x) chain[0] and chain[0].on_next(x) chain[0] = curr return curr def on_error(e): if chain[0]: chain[0].on_error(e) def on_completed(): if chain[0]: chain[0].on_completed() return source.map( mapper ).tap( noop, on_error, on_completed ).observe_on( scheduler ).map( selector ) return Observable.defer(factory)
def timestamp(source: ObservableBase) -> ObservableBase: """Records the timestamp for each value in an observable sequence. 1 - res = source.timestamp() # produces objects with attributes "value" and "timestamp", where value is the original value. Returns an observable sequence with timestamp information on values. """ def factory(scheduler=None): scheduler = scheduler or timeout_scheduler def mapper(value): return Timestamp(value=value, timestamp=scheduler.now) return source.map(mapper) return Observable.defer(factory)
def many_select(self, selector, scheduler=None): """Comonadic bind operator. Internally projects a new observable for each value, and it pushes each observable into the user-defined selector function that projects/queries each observable into some result. Keyword arguments: selector -- {Function} A transform function to apply to each element. scheduler -- {Object} [Optional] Scheduler used to execute the operation. If not specified, defaults to the ImmediateScheduler. Returns {Observable} An observable sequence which results from the comonadic bind operation. """ scheduler = scheduler or immediate_scheduler source = self def factory(): chain = [None] def mapper(x): curr = ChainObservable(x) chain[0] and chain[0].on_next(x) chain[0] = curr return curr def on_error(e): if chain[0]: chain[0].on_error(e) def on_completed(): if chain[0]: chain[0].on_completed() return source.map(mapper).tap( noop, on_error, on_completed).observe_on(scheduler).map(selector) return Observable.defer(factory)
def test_ref_count_notconnected(self): disconnected = [False] count = [0] def factory(scheduler): count[0] += 1 def create(obs): def func(): disconnected[0] = True return func return Observable.create(create) xs = Observable.defer(factory) subject = MySubject() conn = ConnectableObservable(xs, subject) refd = conn.ref_count() dis1 = refd.subscribe() self.assertEqual(1, count[0]) self.assertEqual(1, subject.subscribe_count) assert (not disconnected[0]) dis2 = refd.subscribe() self.assertEqual(1, count[0]) self.assertEqual(2, subject.subscribe_count) assert (not disconnected[0]) dis1.dispose() assert (not disconnected[0]) dis2.dispose() assert (disconnected[0]) disconnected[0] = False dis3 = refd.subscribe() self.assertEqual(2, count[0]) self.assertEqual(3, subject.subscribe_count) assert (not disconnected[0]) dis3.dispose() assert (disconnected[0])
def scan(source: ObservableBase, accumulator: Callable[[Any, Any], Any], seed: Any = None) -> ObservableBase: """Applies an accumulator function over an observable sequence and returns each intermediate result. The optional seed value is used as the initial accumulator value. For aggregation behavior with no intermediate results, see Observable.aggregate or Observable.reduce. 1 - scanned = source.scan(lambda acc, x: acc + x) 2 - scanned = source.scan(lambda acc, x: acc + x, 0) Keyword arguments: accumulator -- An accumulator function to be invoked on each element. seed -- [Optional] The initial accumulator value. Returns an observable sequence containing the accumulated values. """ has_seed = seed is not None def defer(scheduler): nonlocal source has_accumulation = [False] accumulation = [None] def projection(x): if has_accumulation[0]: accumulation[0] = accumulator(accumulation[0], x) else: accumulation[0] = accumulator(seed, x) if has_seed else x has_accumulation[0] = True return accumulation[0] return source.map(projection) return Observable.defer(defer)
def test_ref_count_notconnected(self): disconnected = [False] count = [0] def factory(): count[0] += 1 def create(obs): def func(): disconnected[0] = True return func return Observable.create(create) xs = Observable.defer(factory) subject = MySubject() conn = ConnectableObservable(xs, subject) refd = conn.ref_count() dis1 = refd.subscribe() self.assertEqual(1, count[0]) self.assertEqual(1, subject.subscribe_count) assert(not disconnected[0]) dis2 = refd.subscribe() self.assertEqual(1, count[0]) self.assertEqual(2, subject.subscribe_count) assert(not disconnected[0]) dis1.dispose() assert(not disconnected[0]) dis2.dispose() assert(disconnected[0]) disconnected[0] = False dis3 = refd.subscribe() self.assertEqual(2, count[0]) self.assertEqual(3, subject.subscribe_count) assert(not disconnected[0]) dis3.dispose() assert(disconnected[0])
def observable_delay_date(source, duetime, scheduler): def defer(): timespan = scheduler.to_datetime(duetime) - scheduler.now return observable_delay_timespan(source, timespan, scheduler) return Observable.defer(defer)