async def test_pipe_complex_pipe(): xs = rx.from_iterable([1, 2, 3]) result = [] def mapper(value: int) -> int: return value * 10 async def predicate(value: int) -> bool: await asyncio.sleep(0.1) return value > 1 def long_running(value: int) -> AsyncObservable[int]: return rx.from_iterable([value]) ys = pipe( xs, rx.filter_async(predicate), rx.map(mapper), rx.flat_map(long_running), rx.to_async_iterable, ) async for value in ys: result.append(value) assert result == [20, 30]
async def test_map_mapper_throws(): error = Exception("ex") exception = None xs = rx.from_iterable([1]) async def athrow(ex: Exception): nonlocal exception exception = ex def mapper(x: int): raise error ys = pipe(xs, rx.map(mapper)) obv = rx.AsyncAwaitableObserver(athrow=athrow) await ys.subscribe_async(obv) try: await obv except Exception as ex: assert exception == ex else: assert False
async def test_forward_pipe_map() -> None: xs = rx.from_iterable([1, 2, 3]) def mapper(value: int) -> int: return value * 10 ys = pipe(xs, rx.map(mapper)) obv: AsyncTestObserver[int] = AsyncTestObserver() await rx.run(ys, obv) assert obv.values == [(0, OnNext(10)), (0, OnNext(20)), (0, OnNext(30)), (0, OnCompleted)]
async def test_stream_cancel() -> None: xs: AsyncTestSubject[int] = AsyncTestSubject() subscription: Optional[AsyncDisposable] = None def mapper(value: int) -> int: return value * 10 ys = pipe(xs, rx.map(mapper)) obv = AsyncTestObserver() subscription = await ys.subscribe_async(obv) await xs.asend_later(1, 10) await subscription.dispose_async() await xs.asend_later(1, 20) assert obv.values == [(1, OnNext(100))]
async def test_map_works(): xs: AsyncObservable[int] = rx.from_iterable([1, 2, 3]) values = [] async def asend(value: int) -> None: values.append(value) def mapper(value: int) -> int: return value * 10 ys = pipe(xs, rx.map(mapper)) obv: AsyncObserver[int] = rx.AsyncAwaitableObserver(asend) async with await ys.subscribe_async(obv): result = await obv assert result == 30 assert values == [10, 20, 30]
async def test_stream_cancel(): xs: AsyncTestSingleSubject[int] = AsyncTestSingleSubject() sub = None def mapper(value: int) -> int: return value * 10 ys = pipe(xs, rx.map(mapper)) sink = AsyncTestObserver() sub = await ys.subscribe_async(sink) await xs.asend_later(1, 10) await sub.dispose_async() with pytest.raises(ObjectDisposedException): await xs.asend_later(1, 20) assert sink.values == [(1, OnNext(100))]
async def test_pipe_simple_pipe(): xs = rx.from_iterable([1, 2, 3]) def mapper(value: int) -> int: return value * 10 async def predicate(value: int) -> bool: await asyncio.sleep(0.1) return value > 1 ys = pipe(xs, rx.filter_async(predicate), rx.map(mapper)) obv: AsyncTestObserver[int] = AsyncTestObserver() await rx.run(ys, obv) assert obv.values == [ (approx(0.2), OnNext(20)), (approx(0.3), OnNext(30)), (approx(0.3), OnCompleted), ]
async def test_stream_cancel_asend() -> None: xs: AsyncTestSubject[int] = AsyncTestSubject() subscription: Optional[AsyncDisposable] = None async def asend(value: int) -> None: assert subscription is not None await subscription.dispose_async() await asyncio.sleep(0) def mapper(value: int) -> int: return value * 10 ys = pipe(xs, rx.map(mapper)) obv = AsyncTestObserver(asend) async with await ys.subscribe_async(obv) as sub: subscription = sub await xs.asend_later(1, 10) await xs.asend_later(1, 20) assert obv.values == [(1, OnNext(100))]
async def test_stream_cancel_mapper(): xs: AsyncTestSubject[int] = AsyncTestSubject() subscription: Optional[AsyncDisposable] = None def mapper(value: int) -> int: assert subscription is not None asyncio.ensure_future(subscription.dispose_async()) return value * 10 ys = pipe(xs, rx.map(mapper)) obv: AsyncTestObserver[int] = AsyncTestObserver() async with await ys.subscribe_async(obv) as subscription: await xs.asend_later(100, 10) await xs.asend_later(100, 20) await xs.asend_later(100, 30) await xs.asend_later(100, 40) await xs.asend_later(100, 50) await xs.asend_later(100, 60) assert obv.values == [(100, OnNext(100))]
async def websocket_handler(request: Request) -> WebSocketResponse: print("WebSocket opened") stream: rx.AsyncObservable[Msg] = rx.AsyncSubject() mapper: Callable[[Msg], str] = lambda x: x["term"] xs = pipe( stream, rx.map(mapper), rx.filter(lambda text: len(text) > 2), rx.debounce(0.5), rx.distinct_until_changed, rx.flat_map_async(search_wikipedia), ) ws = web.WebSocketResponse() await ws.prepare(request) async def asend(value: str) -> None: print("asend: ", value) await ws.send_str(value) async def athrow(ex: Exception) -> None: print(ex) await xs.subscribe_async(rx.AsyncAnonymousObserver(asend, athrow)) async for msg in ws: msg: WSMessage if msg.type == aiohttp.WSMsgType.TEXT: obj = json.loads(msg.data) await stream.asend(obj) elif msg.type == aiohttp.WSMsgType.ERROR: print("ws connection closed with exception %s" % ws.exception()) print("websocket connection closed") return ws
async def test_map_subscription_cancel(): xs: rx.AsyncSubject[int] = rx.AsyncSubject() sub: Optional[AsyncDisposable] = None result = [] def mapper(value: int) -> int: return value * 10 ys = pipe(xs, rx.map(mapper)) async def asend(value: int) -> None: result.append(value) assert sub is not None await sub.dispose_async() await asyncio.sleep(0) async with await ys.subscribe_async(rx.AsyncAnonymousObserver(asend) ) as sub: await xs.asend(10) await asyncio.sleep(0) await xs.asend(20) assert result == [100]
async def test_stream_cancel_asend(): xs: AsyncTestSingleSubject[int] = AsyncTestSingleSubject() sub: Optional[AsyncDisposable] = None async def asend(value: int) -> None: assert sub is not None await sub.dispose_async() await asyncio.sleep(0) def mapper(value: int) -> int: return value * 10 ys = pipe(xs, rx.map(mapper)) sink = AsyncTestObserver(asend) async with await ys.subscribe_async(sink) as sub: await xs.asend_later(1, 10) with pytest.raises(ObjectDisposedException): await xs.asend_later(1, 20) assert sink.values == [(1, OnNext(100))]