def test_safe_try() -> None: assert safe_try(int, 5) == Ok(5) assert safe_try(int, 5.0) == Ok(5) assert_same_error_type_with_same_message( safe_try(int, "abc"), Err(ValueError("invalid literal for int() with base 10: 'abc'")), ) def fail_if_5(val: int) -> int: if val == 5: raise (Exception("failed")) else: return val assert_same_error_type_with_same_message(safe_try(fail_if_5, 5), Err(Exception("failed")))
def test_maybe_to_result() -> None: @dataclass class SomeError: msg: str params: List[str] fail_message = SomeError("it failed", ["a", "b"]) assert maybe_to_result(fail_message, Just(5)) == Ok(5) assert maybe_to_result(fail_message, nothing) == Err(fail_message)
def test_safe_try_with_more_params() -> None: def divide_two(a: int, b: int) -> float: return a / b assert safe_try(divide_two, 4, 2) == Ok(2) assert_same_error_type_with_same_message( safe_try(divide_two, 4, 0), Err(ZeroDivisionError("division by zero"))) def fn3(a: float, b: float, c: float) -> float: return a / b / c assert safe_try(fn3, 4, 2, 1) == Ok(2.0) assert_same_error_type_with_same_message( safe_try(fn3, 4, 0, 2), Err(ZeroDivisionError("division by zero"))) def fn4(a: float, b: float, c: float, d: str) -> str: return f"{a / b / c}{d}" assert safe_try(fn4, 4, 2, 1, "F") == Ok("2.0F") assert_same_error_type_with_same_message( safe_try(fn4, 4, 0, 2, "bla"), Err(ZeroDivisionError("division by zero"))) def fn5(a: float, b: float, c: float, d: str, e: bool) -> str: assert e return f"{a / b / c}{d}" assert safe_try(fn5, 4, 2, 1, "F", True) == Ok("2.0F") assert_same_error_type_with_same_message( safe_try(fn5, 4, 0, 2, "bla", False), Err(AssertionError("assert False"))) def fn6(a: float, b: float, c: float, d: str, e: bool, f: bool) -> str: assert e and f return f"{a / b / c}{d}" assert safe_try(fn6, 4, 2, 1, "F", True, True) == Ok("2.0F") assert_same_error_type_with_same_message( safe_try(fn6, 4, 0, 2, "bla", False, True), Err(AssertionError("assert (False)")), )
def _safe_try( fn: Union[ Callable[[A], B], Callable[[A, B], C], Callable[[A, B, C], D], Callable[[A, B, C, D], E], Callable[[A, B, C, D, E], F], Callable[[A, B, C, D, E, F], G], ], v1: A, v2: Union[B, _Unset] = _unset, v3: Union[C, _Unset] = _unset, v4: Union[D, _Unset] = _unset, v5: Union[E, _Unset] = _unset, v6: Union[F, _Unset] = _unset, ) -> Union[ Result[B, Exception], Result[C, Exception], Result[D, Exception], Result[E, Exception], Result[F, Exception], Result[G, Exception], ]: if isinstance(v2, _Unset): try: return Ok(cast(Callable[[A], B], fn)(v1)) except Exception as e: return Err(e) elif isinstance(v3, _Unset): try: return Ok(cast(Callable[[A, B], C], fn)(v1, v2)) except Exception as e: return Err(e) elif isinstance(v4, _Unset): try: return Ok(cast(Callable[[A, B, C], D], fn)(v1, v2, v3)) except Exception as e: return Err(e) elif isinstance(v5, _Unset): try: return Ok(cast(Callable[[A, B, C, D], E], fn)(v1, v2, v3, v4)) except Exception as e: return Err(e) elif isinstance(v6, _Unset): try: return Ok(cast(Callable[[A, B, C, D, E], F], fn)(v1, v2, v3, v4, v5)) except Exception as e: return Err(e) else: try: return Ok(cast(Callable[[A, B, C, D, E, F], G], fn)(v1, v2, v3, v4, v5, v6)) except Exception as e: return Err(e)
def maybe_to_result(fail_message: FailT, orig: Maybe[A]) -> Result[A, FailT]: if isinstance(orig, Just): return Ok(orig.val) else: return Err(fail_message)
def test_result_to_maybe() -> None: assert result_to_maybe(Ok(3)) == Just(3) assert result_to_maybe(Err("something")) == nothing
def test_result() -> None: enforce_functor_one_val(Ok, "map") enforce_monad_unit(Ok) enforce_monad_flat_map(Ok, Err("something went wrong")) enforce_applicative_apply(Ok, Err("something went wrong"))