def test_result_bind_piped(x: int, y: int): xs: Result[int, str] = Ok(x) mapper: Callable[[int], Result[int, str]] = lambda x: Ok(x + y) ys = xs.pipe(result.bind(mapper)) res = ys.match(Ok, lambda ok: ok.value, Error, lambda error: throw(error.error)) assert Ok(res) == mapper(x)
def test_pipeline_works(): fn: Callable[[int], Result[int, Exception]] = lambda x: Ok(x * 10) gn: Callable[[int], Result[int, Exception]] = lambda x: Ok(x + 10) hn = pipeline( fn, gn, ) assert hn(42) == Ok(430)
def test_result_bind_piped(x: int, y: int): xs: Result[int, str] = Ok(x) mapper: Callable[[int], Result[int, str]] = lambda x: Ok(x + y) ys = xs.pipe(result.bind(mapper)) for value in ys.match(Ok[int, str]): assert Ok(value) == mapper(x) break else: assert False
def test_result_traverse_ok(xs: List[int]): ys: List[Result[int, str]] = [Ok(x) for x in xs] zs = sequence(ys) res = zs.match(Ok, lambda ok: sum(ok.value), Error, lambda error: throw(error.error)) assert res == sum(xs)
def test_result_traverse_ok(xs: List[int]): ys: List[Result[int, str]] = [Ok(x) for x in xs] zs = sequence(ys) for value in zs.match(Ok[List[int], str]): assert sum(value) == sum(xs) break else: assert False
def test_result_map_ok_fluent(x: int, y: int): xs: Result[int, Exception] = Ok(x) mapper: Callable[[int], int] = lambda x: x + y ys = xs.map(mapper) res = match(ys, Ok, lambda ok: ok.value, Error, lambda error: throw(error.error)) assert res == mapper(x)
def test_result_match_ok(): xs: Result[int, str] = Ok(42) with match(xs) as case: for x in case(Ok[int, str]): assert x == 42 break else: assert False
def test_result_ok_chained_map(x: int, y: int): xs: Result[int, Exception] = Ok(x) mapper1: Callable[[int], int] = lambda x: x + y mapper2: Callable[[int], int] = lambda x: x * 10 ys = xs.map(mapper1).map(mapper2) res = match(ys, Ok, lambda ok: ok.value, Error, lambda error: throw(error.error)) assert res == mapper2(mapper1(x))
def test_catch_with_effect_ok(): @catch(exception=TypeError) @effect.result def fn(a: int) -> Generator[int, int, int]: b = yield from Ok(42) return a + b result = fn(1) assert result == Ok(43)
def test_result_traverse_error(xs: List[int]): error = "Do'h" ys: List[Result[int, str]] = [ Ok(x) if i == 3 else Error(error) for x, i in enumerate(xs) ] zs = sequence(ys) for err in zs.match(Error[int, str]): assert err == error
def wrapper(*args: Any, **kwargs: Any) -> Result[_TSource, _TError]: try: out = fn(*args, **kwargs) except exception as exn: return Error(cast(_TError, exn)) else: if isinstance(out, Result): return cast(Result[_TSource, _TError], out) return Ok(out)
def test_result_map_piped(x: int, y: int): xs: Result[int, Exception] = Ok(x) mapper: Callable[[int], int] = lambda x: x + y ys = xs.pipe(result.map(mapper)) # NOTE: shows type error for mypy for value in ys.match(Ok[int, Exception]): assert value == mapper(x) break else: assert False
def test_result_traverse_error(xs: List[int]): error = "Do'h" ys: List[Result[int, str]] = [ Ok(x) if i == 3 else Error(error) for x, i in enumerate(xs) ] zs = sequence(ys) res = zs.match(Ok, lambda ok: "", Error, lambda error: error.error) assert res == error
def test_result_map_ok_fluent(x: int, y: int): xs: Result[int, Exception] = Ok(x) mapper: Callable[[int], int] = lambda x: x + y ys = xs.map(mapper) for value in ys.match(Ok[int, Exception]): assert value == mapper(x) break else: assert False
def test_pipeline_error(): error: Result[int, str] = Error("failed") fn: Callable[[int], Result[int, str]] = lambda x: Ok(x * 10) gn: Callable[[int], Result[int, str]] = lambda x: error hn = pipeline( fn, gn, ) assert hn(42) == error
def test_result_ok_chained_map(x: int, y: int): xs: Result[int, Exception] = Ok(x) mapper1: Callable[[int], int] = lambda x: x + y mapper2: Callable[[int], int] = lambda x: x * 10 ys = xs.map(mapper1).map(mapper2) for value in ys.match(Ok[int, Exception]): assert value == mapper2(mapper1(x)) break else: assert False
def test_result_ok(): xs: Result[int, str] = Ok(42) assert isinstance(xs, Result) assert xs.is_ok() assert not xs.is_error() assert str(xs) == "Ok 42" for x in xs: assert x == 42 break else: assert False
def traverse(fn: Callable[[TSource], Result[TResult, TError]], lst: List[TSource]) -> Result[List[TResult], TError]: """Traverses a list of items. Threads an applicative computation though a list of items. """ # flake8: noqa: T484 @effect.result def folder( head: TSource, tail: Result[List[TResult], TError] ) -> Generator[TResult, TResult, List[TResult]]: """Same as: >>> fn(head).bind(lambda head: tail.bind(lambda tail: Ok([head] + tail))) """ h = yield from fn(head) t = yield from tail return [h] + t state: Result[List[TSource], TError] = Ok([]) return pipe(state, seq.fold_back(folder, lst))
def return_(self, x: _TSource) -> Result[_TSource, _TError]: return Ok(x)
def test_catch_wraps_ok(): @catch(exception=ValueError) def add(a: int, b: int) -> int: return a + b assert add(3, 4) == Ok(7)
def fn(a: int) -> Generator[str, str, int]: b = yield from Ok("hello") return a + b # type: ignore
def test_pipeline_none(): hn = pipeline() assert hn(42) == Ok(42)
def fn(a: int) -> Generator[int, int, int]: b = yield from Ok(42) return a + b
def return_(self, x: TSource) -> Result[TSource, TError]: return Ok(x)
async def finish_early(ctx: Context[TNext]) -> HttpFuncResult[TResult, TError]: return Ok(ctx)
def test_result_ok_not_equals_error(x: int): assert not Ok(x) == Error(x) assert not Error(x) == Ok(x)
def test_result_ok_equals_ok(x: int, y: int): xs: Result[int, Exception] = Ok(x) ys: Result[int, Exception] = Ok(y) assert xs == ys if x == y else xs != ys
def test_result_ok_iterate(): for x in Ok(42): assert x == 42
def fn() -> Generator[int, int, int]: x = yield 42 y = yield from Ok(43) return x + y
def fn() -> Generator[int, int, int]: x = yield from Ok(42) return x + 1