def pairwise(self): """Returns a new observable that triggers on the second and subsequent triggerings of the input observable. The Nth triggering of the input observable passes the arguments from the N-1th and Nth triggering as a pair. The argument passed to the N-1th triggering is held in hidden internal state until the Nth triggering occurs. Returns an observable {Observable} that triggers on successive pairs of observations from the input observable as an array. """ source = self def subscribe(observer): has_previous = [False] previous = [None] def on_next(x): pair = None with self.lock: if has_previous[0]: pair = (previous[0], x) else: has_previous[0] = True previous[0] = x if pair: observer.on_next(pair) return source.subscribe(on_next, observer.on_error, observer.on_completed) return AnonymousObservable(subscribe)
def dump(self, name="test"): """Debug method for inspecting an observable sequence Keyword parameters: name -- [Optional] A name to make it easier to match the debug output if you insert multiple dumps into the same observable sequence. Return an unmodified observable sequence """ def subscribe(observer): def on_next(value): print("{%s}-->{%s}" % (name, value)) observer.on_next(value) def on_error(ex): print("{%s} error -->{%s}" % (name, ex)) observer.on_error(ex) def on_completed(): print("{%s} completed" % name) observer.on_completed() return self.subscribe(on_next, on_error, on_completed) return AnonymousObservable(subscribe)
def combine_latest_source(source, subject, result_selector): def subscribe(observer): has_value = [False, False] has_value_all = [False] values = [None, None] is_done = [False] def next(x, i): has_value[i] = True values[i] = x has_value_all[0] = has_value_all[0] or all(has_value) if has_value_all[0]: try: res = result_selector(*values) except Exception as ex: observer.on_error(ex) return observer.on_next(res) elif is_done[0]: observer.on_completed() def on_next(x): next(x, 0) def on_completed(): is_done[0] = True observer.on_completed() return CompositeDisposable( source.subscribe(on_next, observer.on_error, on_completed), subject.subscribe(lambda x: next(x, 1), observer.on_error) ) return AnonymousObservable(subscribe)
def subscribe_on(self, scheduler): """Wraps the source sequence in order to run its subscription and unsubscription logic on the specified scheduler. This operation is not commonly used; see the remarks section for more information on the distinction between subscribe_on and observe_on. Keyword arguments: scheduler -- Scheduler to perform subscription and unsubscription actions on. Returns the source sequence whose subscriptions and unsubscriptions happen on the specified scheduler. This only performs the side-effects of subscription and unsubscription on the specified scheduler. In order to invoke observer callbacks on a scheduler, use observe_on. """ source = self def subscribe(observer): 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 return AnonymousObservable(subscribe)
def take_with_time(self, duration, scheduler=None): """Takes elements for the specified duration from the start of the observable source sequence, using the specified scheduler to run timers. Example: res = source.take_with_time(5000, [optional scheduler]) Description: This operator accumulates a queue with a length enough to store elements received during the initial duration window. As more elements are received, elements older than the specified duration are taken from the queue and produced on the result sequence. This causes elements to be delayed with duration. Keyword arguments: duration -- {Number} Duration for taking elements from the start of the sequence. scheduler -- {Scheduler} Scheduler to run the timer on. If not specified, defaults to rx.Scheduler.timeout. Returns {Observable} An observable sequence with the elements taken during the specified duration from the start of the source sequence. """ source = self scheduler = scheduler or timeout_scheduler def subscribe(observer): def action(scheduler, state): observer.on_completed() disposable = scheduler.schedule_relative(duration, action) return CompositeDisposable(disposable, source.subscribe(observer)) return AnonymousObservable(subscribe)
def _to_dict(source, map_type, key_selector, element_selector): def subscribe(observer): m = map_type() def on_next(x): try: key = key_selector(x) except Exception as ex: observer.on_error(ex) return element = x if element_selector: try: element = element_selector(x) except Exception as ex: observer.on_error(ex) return m[key] = element def on_completed(): observer.on_next(m) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed) return AnonymousObservable(subscribe)
def auto_connect(self, subscriber_count=1): """Returns an observable sequence that stays connected to the source indefinitely to the observable sequence. Providing a subscriber_count will cause it to connect() after that many subscriptions occur. A subscriber_count of 0 will result in emissions firing immediately without waiting for subscribers. """ connectable_subscription = [None] count = [0] source = self is_connected = [False] if subscriber_count == 0: connectable_subscription[0] = source.connect() is_connected[0] = True def subscribe(observer): count[0] += 1 should_connect = count[ 0] == subscriber_count and not is_connected[0] subscription = source.subscribe(observer) if should_connect: connectable_subscription[0] = source.connect() is_connected[0] = True def dispose(): subscription.dispose() count[0] -= 1 is_connected[0] = False return Disposable.create(dispose) return AnonymousObservable(subscribe)
def default_if_empty(self, default_value=None): """Returns the elements of the specified sequence or the specified value in a singleton sequence if the sequence is empty. res = obs = xs.defaultIfEmpty() obs = xs.defaultIfEmpty(False Keyword arguments: default_value -- The value to return if the sequence is empty. If not provided, this defaults to None. Returns an observable {Observable} sequence that contains the specified default value if the source is empty otherwise, the elements of the source itself.""" source = self def subscribe(observer): found = [False] def on_next(x): found[0] = True observer.on_next(x) def on_completed(): if not found[0]: observer.on_next(default_value) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed) return AnonymousObservable(subscribe)
def finally_action(self, action): """Invokes a specified action after the source observable sequence terminates gracefully or exceptionally. Example: res = observable.finally(lambda: print('sequence ended') Keyword arguments: action -- {Function} Action to invoke after the source observable sequence terminates. Returns {Observable} Source sequence with the action-invoking termination behavior applied. """ source = self def subscribe(observer): try: subscription = source.subscribe(observer) except Exception as ex: action() raise def dispose(): try: subscription.dispose() finally: action() return Disposable(dispose) return AnonymousObservable(subscribe)
def ref_count(self): """Returns an observable sequence that stays connected to the source as long as there is at least one subscription to the observable sequence. """ connectable_subscription = [None] count = [0] source = self def subscribe(observer): count[0] += 1 should_connect = count[0] == 1 subscription = source.subscribe(observer) if should_connect: connectable_subscription[0] = source.connect() def dispose(): subscription.dispose() count[0] -= 1 if not count[0]: connectable_subscription[0].dispose() return Disposable.create(dispose) return AnonymousObservable(subscribe)
def observable_window_with_bounaries(self, window_boundaries): source = self def subscribe(observer): window = Subject() d = CompositeDisposable() r = RefCountDisposable(d) observer.on_next(add_ref(window, r)) def on_next_window(x): window.on_next(x) def on_error(err): window.on_error(err) observer.on_error(err) def on_completed(): window.on_completed() observer.on_completed() d.add(source.subscribe(on_next_window, on_error, on_completed)) def on_next_observer(w): window.on_completed() window = Subject() observer.on_next(add_ref(window, r)) d.add(window_boundaries.subscribe(on_next_observer, on_error, on_copleted)) return r return AnonymousObservable(subscribe)
def _element_at_or_default(source, index, has_default=False, default_value=None): if index < 0: raise ArgumentOutOfRangeException() def subscribe(observer): i = [index] def on_next(x): found = False with source.lock: if i[0]: i[0] -= 1 else: found = True if found: observer.on_next(x) observer.on_completed() def on_completed(): if not has_default: observer.on_error(ArgumentOutOfRangeException()) else: observer.on_next(default_value) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed) return AnonymousObservable(subscribe)
def select(self, selector): """Projects each element of an observable sequence into a new form by incorporating the element's index. 1 - source.map(lambda value: value * value) 2 - source.map(lambda value, index: value * value + index) Keyword arguments: :param Callable[[Any, Any], Any] selector: A transform function to apply to each source element; the second parameter of the function represents the index of the source element. :rtype: Observable Returns an observable sequence whose elements are the result of invoking the transform function on each element of source. """ selector = adapt_call(selector) def subscribe(observer): count = [0] def on_next(value): try: result = selector(value, count[0]) except Exception as err: observer.on_error(err) else: count[0] += 1 observer.on_next(result) return self.subscribe(on_next, observer.on_error, observer.on_completed) return AnonymousObservable(subscribe)
def some(self, predicate=None): """Determines whether some element of an observable sequence satisfies a condition if present, else if some items are in the sequence. Example: result = source.some() result = source.some(lambda x: x > 3) predicate -- A function to test each element for a condition. Returns {Observable} an observable sequence containing a single element determining whether some elements in the source sequence pass the test in the specified predicate if given, else if some items are in the sequence.""" source = self def subscribe(observer): def on_next(_): observer.on_next(True) observer.on_completed() def on_error(): observer.on_next(False) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_error) return source.filter( predicate).some() if predicate else AnonymousObservable(subscribe)
def skip_last(self, count): """Bypasses a specified number of elements at the end of an observable sequence. Description: This operator accumulates a queue with a length enough to store the first `count` elements. As more elements are received, elements are taken from the front of the queue and produced on the result sequence. This causes elements to be delayed. Keyword arguments count -- Number of elements to bypass at the end of the source sequence. Returns an observable {Observable} sequence containing the source sequence elements except for the bypassed ones at the end.""" source = self def subscribe(observer): q = [] def on_next(x): front = None with self.lock: q.append(x) if len(q) > count: front = q.pop(0) if front: observer.on_next(front) return source.subscribe(on_next, observer.on_error, observer.on_completed) return AnonymousObservable(subscribe)
def skip(self, count): """Bypasses a specified number of elements in an observable sequence and then returns the remaining elements. Keyword arguments: count -- The number of elements to skip before returning the remaining elements. Returns an observable sequence that contains the elements that occur after the specified index in the input sequence. """ if count < 0: raise ArgumentOutOfRangeException() observable = self def subscribe(observer): remaining = [count] def on_next(value): if remaining[0] <= 0: observer.on_next(value) else: remaining[0] -= 1 return observable.subscribe(on_next, observer.on_error, observer.on_completed) return AnonymousObservable(subscribe)
def http_parse(self): source = self def subscribe(observer): m = SingleAssignmentDisposable() ref_count_disposable = RefCountDisposable(m) parser = HttpParser(observer, ref_count_disposable) m.disposable = source.subscribe(parser) return ref_count_disposable return AnonymousObservable(subscribe)
def to_set(source, set_type): def subscribe(observer): s = set_type() def on_completed(): observer.on_next(s) observer.on_completed() return source.subscribe(s.add, observer.on_error, on_completed) return AnonymousObservable(subscribe)
def driver(sink): def subscribe_response(observer): def on_request_item(i): if type(i) is Walk: content = walk(i.top, i.recursive) observer.on_next( WalkResponse(top=i.top, id=i.id, content=content)) sink.request.subscribe(on_request_item) return Source(response=AnonymousObservable(subscribe_response))
def when_complete(self): source = self def subscribe(observer): def on_completed(): observer.on_next() observer.on_completed() return source.subscribe(on_completed=on_completed, on_error=observer.on_error) return AnonymousObservable(subscribe)
def as_observable(self): """Hides the identity of an observable sequence. Returns an observable {Observable} sequence that hides the identity of the source sequence.""" source = self def subscribe(observer): return source.subscribe(observer) return AnonymousObservable(subscribe)
def fake_extensionmethod(self): print('[custom-extensionmethod] Observer: {}'.format(self)) source = self def subscribe(observer): def on_next(x): pass return source.subscribe(on_next, observer.on_error, observer.on_completed) return AnonymousObservable(subscribe)
def ignore_elements(self): """Ignores all elements in an observable sequence leaving only the termination messages. Returns an empty observable {Observable} sequence that signals termination, successful or exceptional, of the source sequence.""" source = self def subscribe(observer): return source.subscribe(noop, observer.on_error, observer.on_completed) return AnonymousObservable(subscribe)
def asyncgen_to_observable(asyncgen, loop=None): def emit(observer): task = ensure_future(iterate_asyncgen(asyncgen, observer), loop=loop) def dispose(): async def await_task(): await task task.cancel() ensure_future(await_task(), loop=loop) return dispose return AnonymousObservable(emit)
def take_last_with_time(self, duration, scheduler=None): """Returns elements within the specified duration from the end of the observable source sequence, using the specified schedulers to run timers and to drain the collected elements. Example: res = source.take_last_with_time(5000, scheduler) Description: This operator accumulates a queue with a length enough to store elements received during the initial duration window. As more elements are received, elements older than the specified duration are taken from the queue and produced on the result sequence. This causes elements to be delayed with duration. Keyword arguments: duration -- {Number} Duration for taking elements from the end of the sequence. scheduler -- {Scheduler} [Optional] Scheduler to run the timer on. If not specified, defaults to rx.Scheduler.timeout. Returns {Observable} An observable sequence with the elements taken during the specified duration from the end of the source sequence. """ source = self scheduler = scheduler or timeout_scheduler duration = scheduler.to_timedelta(duration) def subscribe(observer): q = [] def on_next(x): now = scheduler.now q.append({"interval": now, "value": x}) while len(q) and now - q[0]["interval"] >= duration: q.pop(0) def on_completed(): now = scheduler.now while len(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) return AnonymousObservable(subscribe)
def combine_latest_source(source, subject, result_selector): def subscribe(observer): has_value = [False, False] has_value_all = [False] values = [None, None] is_done = [False] err = [None] def next(x, i): has_value[i] = True values[i] = x has_value_all[0] = has_value_all[0] or all(has_value) if has_value_all[0]: if err[0]: observer.on_error(err[0]) return try: res = result_selector(*values) except Exception as ex: observer.on_error(ex) return observer.on_next(res) if is_done[0] and values[1]: observer.on_completed() def on_error_source(e): if values[1]: observer.on_error(e) else: err[0] = e def on_completed_source(): is_done[0] = True if values[1]: observer.on_completed() def on_completed_subject(): is_done[0] = True next(True, 1) return CompositeDisposable( source.subscribe(lambda x: next(x, 0), on_error_source, on_completed_source), subject.subscribe(lambda x: next(x, 1), observer.on_error, on_completed_subject)) return AnonymousObservable(subscribe)
def first_or_default_async(source, has_default=False, default_value=None): def subscribe(observer): def on_next(x): observer.on_next(x) observer.on_completed() def on_completed(): if not has_default: observer.on_error(SequenceContainsNoElementsError()) else: observer.on_next(default_value) observer.on_completed() return source.subscribe(on_next, observer.on_error, on_completed) return AnonymousObservable(subscribe)
def observable_window_with_closing_selector(self, window_closing_selector): source = self def subscribe(observer): m = SerialDisposable() d = CompositeDisposable(m) r = RefCountDisposable(d) window = [Subject()] observer.on_next(add_ref(window[0], r)) def on_next(x): window[0].on_next(x) def on_error(ex): window[0].on_error(ex) observer.on_error(ex) def on_completed(): window[0].on_completed() observer.on_completed() d.add(source.subscribe(on_next, on_error, on_completed)) def create_window_close(): try: window_close = window_closing_selector() except Exception as exception: log.error("*** Exception: %s" % exception) observer.on_error(exception) return def on_completed(): window[0].on_completed() window[0] = Subject() observer.on_next(add_ref(window[0], r)) create_window_close() m1 = SingleAssignmentDisposable() m.disposable = m1 m1.disposable = window_close.take(1).subscribe( noop, on_error, on_completed) create_window_close() return r return AnonymousObservable(subscribe)
def concat(cls, *args): """Concatenates all the observable sequences. 1 - res = Observable.concat(xs, ys, zs) 2 - res = Observable.concat([xs, ys, zs]) Returns an observable sequence that contains the elements of each given sequence, in sequential order. """ if isinstance(args[0], list) or isinstance(args[0], Enumerable): sources = args[0] else: sources = list(args) def subscribe(observer): enum = iter(sources) is_disposed = [False] subscription = SerialDisposable() def action(action1, state=None): current = None if is_disposed[0]: return try: current = six.next(enum) except StopIteration: observer.on_completed() except Exception as ex: observer.on_error(ex) else: d = SingleAssignmentDisposable() subscription.disposable = d d.disposable = current.subscribe(observer.on_next, observer.on_error, lambda: action1()) cancelable = immediate_scheduler.schedule_recursive(action) def dispose(): is_disposed[0] = True return CompositeDisposable(subscription, cancelable, Disposable(dispose)) return AnonymousObservable(subscribe)
def when(cls, *args): """Joins together the results from several patterns. :param Observable cls: Observable class. :param list[Plan] args: A series of plans (specified as a list of as a series of arguments) created by use of the Then operator on patterns. :returns: Observable sequence with the results form matching several patterns. :rtype: Observable """ plans = args[0] if len(args) and isinstance(args[0], list) else list(args) def subscribe(observer): active_plans = [] external_subscriptions = {} def on_error(err): for v in external_subscriptions.values(): v.on_error(err) observer.on_error(err) out_observer = AnonymousObserver(observer.on_next, on_error, observer.on_completed) def deactivate(active_plan): active_plans.remove(active_plan) if not len(active_plans): observer.on_completed() try: for plan in plans: active_plans.append( plan.activate(external_subscriptions, out_observer, deactivate)) except Exception as ex: Observable.throw(ex).subscribe(observer) group = CompositeDisposable() for join_observer in external_subscriptions.values(): join_observer.subscribe() group.add(join_observer) return group return AnonymousObservable(subscribe)