Example #1
0
    def _slice(source: AsyncObservable[TSource]) -> AsyncObservable[TSource]:
        nonlocal start

        if start is not None:
            if start < 0:
                source = pipe(source, take_last(abs(start)))
            else:
                source = pipe(source, skip(start))

        if stop is not None:
            if stop > 0:
                start = start or 0
                source = pipe(source, take(stop - start))
            else:
                source = pipe(source, skip_last(abs(stop)))

        if step is not None:
            if step > 1:
                mapper: Callable[[Any, int], bool] = lambda _, i: i % step == 0
                xs = pipe(source, filteri(mapper))
                source = xs
            elif step < 0:
                # Reversing streams is not supported
                raise TypeError("Negative step not supported.")

        return source
Example #2
0
async def main():
    xs = rx.from_iterable(range(10))

    # Split into odds and evens
    evens = pipe(xs, rx.filter(lambda x: x % 2 == 0))
    odds = pipe(xs, rx.filter(lambda x: x % 2 == 1))

    async def mysink(value: int):
        print(value)

    await odds.subscribe_async(rx.AsyncAnonymousObserver(mysink))
    await evens.subscribe_async(rx.AsyncAnonymousObserver(mysink))
Example #3
0
    def combine_latest(
            self,
            other: AsyncObservable[TOther]) -> AsyncRx[Tuple[TSource, TOther]]:
        from .combine import combine_latest

        xs = pipe(self, combine_latest(other))
        return AsyncRx.create(xs)
Example #4
0
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]
Example #5
0
def test_seq_take(xs: List[int], x: int):
    ys = seq.of_iterable(xs)
    try:
        zs = pipe(ys, seq.take(x))
        assert list(zs) == xs[:x]
    except ValueError:
        assert x > len(xs)
Example #6
0
    def take(self, count: int) -> Seq[TSource]:
        """Returns the first N elements of the sequence.

        Args:
            count: The number of items to take.
        """
        return Seq(pipe(self, take(count)))
Example #7
0
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
Example #8
0
async def test_merge_streams():
    xs: AsyncTestSubject[AsyncObservable[int]] = AsyncTestSubject()
    s1: AsyncTestSubject[int] = AsyncTestSubject()
    s2: AsyncTestSubject[int] = AsyncTestSubject()

    ys = pipe(xs, rx.merge_inner())

    obv = AsyncTestObserver()
    await ys.subscribe_async(obv)
    await xs.asend(s1)
    await xs.asend(s2)

    await s1.asend_at(1, 10)
    await s1.asend_at(2, 20)
    await s1.asend_at(4, 30)
    await s1.aclose_at(6)

    await s2.asend_at(0, 40)
    await s2.asend_at(3, 50)
    await s2.asend_at(5, 60)
    await s2.aclose_at(6)

    await xs.aclose()
    await obv

    assert obv.values == [
        (0, OnNext(40)),
        (1, OnNext(10)),
        (2, OnNext(20)),
        (3, OnNext(50)),
        (4, OnNext(30)),
        (5, OnNext(60)),
        (6, OnCompleted),
    ]
Example #9
0
async def test_merge_streams_concat():
    s1: AsyncTestSubject[int] = AsyncTestSubject()
    s2 = rx.from_iterable([1, 2, 3])

    xs = rx.from_iterable([s1, s2])

    ys = pipe(xs, rx.merge_inner(1))

    obv = AsyncTestObserver()
    await ys.subscribe_async(obv)

    await s1.asend_at(1, 10)
    await s1.asend_at(2, 20)
    await s1.asend_at(4, 30)
    await s1.aclose_at(6)

    await obv

    assert obv.values == [
        (1, OnNext(10)),
        (2, OnNext(20)),
        (4, OnNext(30)),
        (6, OnNext(1)),
        (6, OnNext(2)),
        (6, OnNext(3)),
        (6, OnCompleted),
    ]
Example #10
0
    def flat_map_async(
        self, selector: Callable[[TSource],
                                 Awaitable[AsyncObservable[TResult]]]
    ) -> AsyncRx[TResult]:
        from .transform import flat_map_async

        return AsyncRx.create(pipe(self, flat_map_async(selector)))
Example #11
0
def concat(sources: Iterable[FrozenList[TSource]]) -> FrozenList[TSource]:
    """Concatenate sequence of FrozenList's"""
    def reducer(t: FrozenList[TSource],
                s: FrozenList[TSource]) -> FrozenList[TSource]:
        return t.append(s)

    return pipe(sources, seq.fold(reducer, empty))
Example #12
0
    def skip(self, count: int) -> Seq[TSource]:
        """Returns a sequence that skips N elements of the underlying
        sequence and then yields the remaining elements of the sequence.

        Args:
            count: The number of items to skip.
        """
        return Seq(pipe(self, skip(count)))
Example #13
0
def test_seq_choose_option():
    xs: Iterable[Optional[int]] = seq.of(None, 42)

    chooser: seq.Projection[Optional[int],
                            int] = seq.choose(option.of_optional)
    ys = pipe(xs, chooser)

    assert list(ys) == [42]
Example #14
0
def test_list_filter(xs: List[int], limit: int):
    expected = filter(lambda x: x < limit, xs)

    ys: FrozenList[int] = frozenlist.of_seq(xs)
    predicate: Callable[[int], bool] = lambda x: x < limit
    result = pipe(ys, frozenlist.filter(predicate))

    assert list(result) == list(expected)
Example #15
0
    def __str__(self) -> str:
        def to_str(item: Tuple[Key, Value]) -> str:
            key, value = item
            if isinstance(key, str):
                return f'("{key}", {value})'
            return f"({key}, {value})"

        items = pipe(self.to_seq(), seq.map(to_str))
        return f"map [{'; '.join(items)}]"
Example #16
0
def merge_seq(
        sources: Iterable[AsyncObservable[TSource]]
) -> AsyncObservable[TSource]:
    from .create import of_seq

    return pipe(
        of_seq(sources),
        merge_inner(),
    )
Example #17
0
async def test_distinct_until_changed_different():
    xs = rx.from_iterable([1, 2, 3])

    obv: AsyncTestObserver[int] = AsyncTestObserver()
    ys = pipe(xs, rx.distinct_until_changed)

    await rx.run(ys, obv)
    assert obv.values == [(0, OnNext(1)), (0, OnNext(2)), (0, OnNext(3)),
                          (0, OnCompleted)]
Example #18
0
def test_list_unfold(x: int):
    def unfolder(state: int) -> Option[Tuple[int, int]]:
        if state < x:
            return Some((state, state + 1))
        return Nothing

    result = pipe(0, seq.unfold(unfolder))

    assert list(result) == list(range(x))
Example #19
0
def concat_seq(
        sources: Iterable[AsyncObservable[TSource]]
) -> AsyncObservable[TSource]:
    """Returns an observable sequence that contains the elements of each
    given sequences, in sequential order."""

    return pipe(
        of_seq(sources),
        merge_inner(1),
    )
Example #20
0
def test_list_fold(xs: List[int]):
    def folder(x: int, y: int) -> int:
        return x + y

    expected: int = functools.reduce(folder, xs, 0)

    ys: FrozenList[int] = frozenlist.of_seq(xs)
    result = pipe(ys, frozenlist.fold(folder, 0))

    assert result == expected
Example #21
0
    def starmap(self, mapper: Callable[...,
                                       TResult]) -> AsyncObservable[TResult]:
        """Map and spread the arguments to the mapper.

        Returns:
            An observable sequence whose elements are the result of
            invoking the mapper function on each element of the source.
        """

        return AsyncRx(pipe(self, starmap(mapper)))
Example #22
0
async def test_take_zero() -> None:
    xs = rx.from_iterable([1, 2, 3, 4, 5])

    ys = pipe(xs, rx.take(0))

    obv: AsyncTestObserver[int] = AsyncTestObserver()
    with pytest.raises(CancelledError):
        await rx.run(ys, obv)

    assert obv.values == [(0, OnCompleted)]
Example #23
0
async def test_take_empty() -> None:
    xs: AsyncObservable[int] = rx.empty()

    ys = pipe(xs, rx.take(42))

    obv: AsyncTestObserver[int] = AsyncTestObserver()
    with pytest.raises(CancelledError):
        await rx.run(ys, obv)

    assert obv.values == [(0, OnCompleted)]
Example #24
0
async def test_flat_map_monad():
    m = rx.single(42)

    def mapper(x: int) -> AsyncObservable[int]:
        return rx.single(x * 10)

    a = await rx.run(pipe(m, rx.flat_map(mapper)))
    b = await rx.run(rx.single(420))

    assert a == b
Example #25
0
async def test_take_normal() -> None:
    xs = rx.from_iterable([1, 2, 3, 4, 5])

    ys = pipe(xs, rx.take(2))

    obv: AsyncTestObserver[int] = AsyncTestObserver()
    result = await rx.run(ys, obv)

    assert result == 2
    assert obv.values == [(0, OnNext(1)), (0, OnNext(2)), (0, OnCompleted)]
Example #26
0
def test_map_remove(xs: Dict[str, int]):
    items: ItemsView[str, int] = xs.items()
    m = Map.of_seq(items)

    keys = xs.keys()
    count = len(m)
    for key in keys:
        m = pipe(m, map.remove(key))
        count -= 1
    assert len(m) == count == 0
Example #27
0
    def starfilter(self: AsyncObservable[Iterable[Any]],
                   predicate: Callable[..., bool]) -> AsyncRx[Iterable[Any]]:
        """Filter and spread the arguments to the predicate.

        Filters the elements of an observable sequence based on a predicate.
        Returns:
            An observable sequence that contains elements from the input
            sequence that satisfy the condition.
        """
        xs = pipe(self, starfilter(predicate))
        return AsyncRx.create(xs)
Example #28
0
async def test_flat_map_monad_law_associativity():
    # (m >>= f) >>= g is just like doing m >>= (\x -> f x >>= g)

    m = rx.single(42)

    def f(x: int) -> AsyncObservable[int]:
        return rx.single(x + 1000)

    def g(y: int) -> AsyncObservable[int]:
        return rx.single(y * 333)

    def h(x: int) -> AsyncObservable[int]:
        return pipe(f(x), rx.flat_map(g))

    zs = pipe(m, rx.flat_map(f))
    a = await rx.run(pipe(zs, rx.flat_map(g)))

    b = await rx.run(pipe(m, rx.flat_map(h)))

    assert a == b
Example #29
0
async def test_withlatestfrom_never_empty():
    xs: AsyncObservable[int] = rx.empty()
    ys: AsyncObservable[int] = rx.never()

    zs = pipe(xs, rx.with_latest_from(ys))

    obv: AsyncTestObserver[Tuple[int, int]] = AsyncTestObserver()
    with pytest.raises(CancelledError):
        await rx.run(zs, obv)

    assert obv.values == [(0, OnCompleted)]
Example #30
0
def to_seq(s: MapTree[Key, Value]) -> Iterable[Tuple[Key, Value]]:
    it = mk_iterator(s)

    def folder(it: Iterator[Tuple[Key, Value]]):
        try:
            current = next(it)
        except StopIteration:
            return Nothing
        else:
            return Some((current, it))

    return pipe(it, seq.unfold(folder))