def test_init(input_: Union[int, List[int]]) -> None: if isinstance(input_, int): with raises( TypeError, match="ChainedIterable expected an iterable, " "but 'int' object is not iterable", ): ChainedIterable(input_) # type: ignore else: assert isinstance(ChainedIterable(iter(input_)), ChainedIterable)
def test_sorted( ints: List[int], key: Optional[Callable[[int], Any]], reverse: bool, ) -> None: _assert_same_type_and_equal( ChainedIterable(iter(ints)).sorted(key=key, reverse=reverse), sorted(ints, key=key, reverse=reverse), )
def test_first_and_last(ints: List[int], method_name: str, index: int) -> None: method = getattr(ChainedIterable(iter(ints)), method_name) if ints: assert method() == ints[index] else: with raises(EmptyIterableError): method()
def test_max_and_min( data: Any, ints: List[int], func: Callable[..., int], default_kwargs: Dict[str, int], ) -> None: method = getattr(ChainedIterable(iter(ints)), func.__name__) key_kwargs_strategies = just({}) | fixed_dictionaries( {"key": _int_to_any_funcs()}, ) if VERSION in {Version.py36, Version.py37}: key_kwargs = data.draw(key_kwargs_strategies) elif VERSION is Version.py38: key_kwargs = data.draw(key_kwargs_strategies | just({"key": None})) else: raise UnsupportVersionError(VERSION) try: res = method(**key_kwargs, **default_kwargs) except ValueError: with raises( ValueError, match=escape(f"{func.__name__}() arg is an empty sequence"), ): func(ints, **key_kwargs, **default_kwargs) else: _assert_same_type_and_equal( res, func(ints, **key_kwargs, **default_kwargs), )
def test_range( start: int, stop: Union[int, Sentinel], step: Union[int, Sentinel], ) -> None: if step is sentinel: assume(stop is not sentinel) args, _ = drop_sentinel(stop, step) iterable = ChainedIterable.range(start, *args) assert isinstance(iterable, ChainedIterable) assert iterable == range(start, *args)
def test_one(ints: List[int]) -> None: iterable = ChainedIterable(iter(ints)) num_ints = len(ints) if num_ints == 0: with raises(EmptyIterableError): iterable.one() elif num_ints == 1: assert iterable.one() == ints[0] else: with raises(MultipleElementsError, match=f"{ints[0]}, {ints[1]}"): iterable.one()
def test_reduce( ints: List[int], func: Callable[[int, int], int], initial_args: Tuple[int, ...], ) -> None: try: res = ChainedIterable(iter(ints)).reduce(func, *initial_args) except EmptyIterableError: with raises( TypeError, match=escape(f"reduce() of empty sequence with no initial value"), ): reduce(func, ints, *initial_args) else: _assert_same_type_and_equal( res, reduce(func, ints, *initial_args), )
def test_get_item(ints: List[int], index: int) -> None: iterable = ChainedIterable(iter(ints)) num_ints = len(ints) if index < 0: with raises( IndexError, match=f"Expected a non-negative index; got {index}", ): iterable[index] elif 0 <= index < num_ints: _assert_same_type_and_equal(iterable[index], ints[index]) elif num_ints <= index <= maxsize: with raises(IndexError, match="ChainedIterable index out of range"): iterable[index] else: with raises( IndexError, match=f"Expected an index at most {maxsize}; got {index}", ): iterable[index]
def test_eq(ints: List[int], other: Union[int, List[int]]) -> None: _assert_same_type_and_equal( ChainedIterable(iter(ints)) == other, ints == other, )
def test_len(ints: List[int]) -> None: _assert_same_type_and_equal(ChainedIterable(iter(ints)).len(), len(ints))
def test_cache(ints: List[int]) -> None: iterable = ChainedIterable(iter(ints)).cache() assert isinstance(iterable, ChainedIterable) assert iterable == ints
def test_sum(ints: List[int], args: Tuple[int, ...]) -> None: _assert_same_type_and_equal( ChainedIterable(iter(ints)).sum(*args), sum(ints, *args), )
def test_zip(ints: List[int], iterables: List[List[int]]) -> None: iterable = ChainedIterable(iter(ints)).zip(*iterables) assert isinstance(iterable, ChainedIterable) assert iterable == zip(ints, *iterables)
def test_count(start: int, step: int, length: int) -> None: iterable = ChainedIterable.count(start=start, step=step) assert isinstance(iterable, ChainedIterable) assert iterable[:length] == islice(count(start=start, step=step), length)
def test_all(bools: List[bool]) -> None: _assert_same_type_and_equal(ChainedIterable(iter(bools)).all(), all(bools))
def test_repr(ints: List[int]) -> None: assert repr(ChainedIterable(ints)) == f"ChainedIterable({ints!r})"
def test_pipe(ints: List[int], n: int) -> None: iterable = ChainedIterable(iter(ints)).pipe(chunked, n) assert isinstance(iterable, ChainedIterable) assert iterable == chunked(ints, n)
def test_map(ints: List[int], func: Callable[[int], int]) -> None: iterable = ChainedIterable(iter(ints)).map(func) assert isinstance(iterable, ChainedIterable) assert iterable == map(func, ints)
def test_frozenset_and_list_and_set_and_tuple( ints: List[int], func: Callable[[Iterable[int]], Iterable[int]], ) -> None: _assert_same_type_and_equal( getattr(ChainedIterable(iter(ints)), func.__name__)(), func(ints), )
def test_filter(ints: List[int], func: Callable[[int], bool]) -> None: iterable = ChainedIterable(iter(ints)).filter(func) assert isinstance(iterable, ChainedIterable) assert iterable == filter(func, ints)
def test_enumerate(ints: List[int], start: int) -> None: iterable = ChainedIterable(iter(ints)).enumerate(start=start) assert isinstance(iterable, ChainedIterable) assert iterable == enumerate(ints, start=start)
def test_dict(mapping: Dict[int, int]) -> None: _assert_same_type_and_equal( ChainedIterable(mapping.items()).dict(), mapping, )
def test_reversed(ints: List[int]) -> None: iterable = ChainedIterable(ints).reversed() assert isinstance(iterable, ChainedIterable) assert iterable == reversed(ints)
def test_iter(ints: List[int]) -> None: assert list(ChainedIterable(iter(ints))) == ints
def test_unzip(iterables: List[List[int]]) -> None: iterable = ChainedIterable(iterables).unzip() assert isinstance(iterable, ChainedIterable) assert iterable == zip(*iterables)
def test_str(ints: List[int]) -> None: assert str(ChainedIterable(ints)) == f"ChainedIterable({ints})"