def _to_async_generator(source: Observable): def feeder(): nonlocal future if not notifications or future.done(): return notification = notifications.pop(0) if notification.kind == "E": future.set_exception(notification.exception) elif notification.kind == "C": future.set_result(sentinel) else: future.set_result(notification.value) def on_next(value): """Takes on_next values and appends them to the notification queue""" notifications.append(value) loop.call_soon(feeder) source.pipe(ops.materialize()).subscribe(on_next) @asyncio.coroutine def gen(): """Generator producing futures""" nonlocal future loop.call_soon(feeder) future = Future() return future return gen
async def to_agen(obs, loop, get_feedback_observer): queue = asyncio.Queue() index = 0 def on_next(i): nonlocal index queue.put_nowait(i) if isinstance(i, OnNext): index += 1 if index == 500: index = 0 obv = get_feedback_observer() if obv is not None: obv.on_next((i.value[0], queue.qsize())) # todo: mapper disposable = obs.pipe(ops.materialize()).subscribe( on_next=on_next, on_error=lambda e: print("to_agen error: {}".format(e)), scheduler=AsyncIOScheduler(loop=loop)) while True: try: i = queue.get_nowait() except asyncio.QueueEmpty: i = await queue.get() if isinstance(i, OnNext): yield i.value queue.task_done() elif isinstance(i, OnError): disposable.dispose() raise (Exception(i.exception)) else: disposable.dispose() break
async def observable_to_async_event_generator(observable: Observable): queue = asyncio.Queue() def on_next(i): queue.put_nowait(i) observable.pipe(materialize()).subscribe(on_next=on_next) while True: value = await queue.get() yield value queue.task_done()
def rmux_server(sources): tcp_listen = rx.just(tcp_server.Listen(host='127.0.0.1', port='8080')) beat = sources.tcp_server.response.pipe( ops.flat_map(lambda connection: connection.observable.pipe( ops.map(lambda i: i.data.decode('utf-8')), unframe, ops.map(lambda i: json.loads(i)), ops.flat_map(lambda subscription: create_observable[subscription[ 'name']]().pipe( ops.materialize(), ops.map(lambda i: materialize_repr(i, subscription['id'])), )), ops.map(lambda i: json.dumps(i)), frame, ops.map(lambda j: tcp_server.Write(id=connection.id, data=j.encode()))))) tcp_sink = rx.merge(tcp_listen, beat) return Sink(tcp_server=tcp_server.Sink(request=tcp_sink), )
async def observable_to_async_iterable(obs, loop): queue = asyncio.Queue() disposable = obs.pipe(ops.materialize()).subscribe( on_next=lambda x: loop.call_soon_threadsafe(queue.put_nowait, x), scheduler=AsyncIOScheduler(loop=loop), ) while True: x = await queue.get() if isinstance(x, OnNext): yield x.value queue.task_done() elif isinstance(x, OnError): disposable.dispose() raise Exception(f"Observable OnError: {x.value}") else: disposable.dispose() break
def subscribe(observer, scheduler_=None): nonlocal duetime _scheduler = scheduler or scheduler_ or timeout_scheduler 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 = timedelta(0) 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 response_stream(loop, req_desc): return rx.from_future(loop.create_task(perform_request(req_desc))).pipe(materialize())
def __init__(self): self.notifications = [] self.future = Future() source.pipe(ops.materialize()).subscribe(self.on_next)
op.first() op.ignore_elements() op.last() op.skip() op.skip_last() op.take() op.take_last() # ... """Error Handling""" op.catch() op.retry() """Utility""" op.delay() op.materialize() op.time_interval() op.timeout() op.timestamp() """Conditional and Boolean""" op.all() op.contains() op.default_if_empty() op.sequence_equal() op.skip_until() op.skip_while() op.take_until() op.take_while() """Connectable"""
def create(): return xs.pipe(_.materialize(), _.dematerialize())
def create(): return rx.never().pipe(_.materialize(), _.dematerialize())
import rx import rx.operators as ops numbers = rx.from_([1, 2, 3, 4]) numbers.pipe(ops.materialize()).subscribe( on_next=lambda i: print("on_next {}".format(i)), on_error=lambda e: print("on_error: {}".format(e)), on_completed=lambda: print("on_completed"))