From e444ea7ed1d1f79d933f6d0bceee8eaaf0ca91e5 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Wed, 14 Aug 2024 17:45:05 +0300 Subject: [PATCH] Add `default_error` parameter to `converters.maybe_to_result` (#1914) --- CHANGELOG.md | 2 ++ docs/pages/converters.rst | 7 ++++-- returns/converters.py | 24 +++++++++++++++++-- .../test_converters/test_maybe_to_result.yml | 9 +++++++ 4 files changed, 38 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4a51d203..b736bcd70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ See [0Ver](https://0ver.org/). - Improve inference of `ResultLike` objects when exception catching decorator is applied with explicit exception types - Add picky exceptions to `impure_safe` decorator like `safe` has. Issue #1543 +- Adds `default_error` parameter to `returns.converters.maybe_to_result`, + which provides a default error value for `Failure` ### Misc diff --git a/docs/pages/converters.rst b/docs/pages/converters.rst index 078d33a83..35e60cdb5 100644 --- a/docs/pages/converters.rst +++ b/docs/pages/converters.rst @@ -22,8 +22,8 @@ That's how they work: .. code:: python >>> from returns.converters import maybe_to_result, result_to_maybe - >>> from returns.maybe import Maybe, Some - >>> from returns.result import Result, Success + >>> from returns.maybe import Maybe, Some, Nothing + >>> from returns.result import Failure, Result, Success >>> result: Result[int, Exception] = Success(1) >>> maybe: Maybe[int] = result_to_maybe(result) @@ -32,6 +32,9 @@ That's how they work: >>> new_result: Result[int, None] = maybe_to_result(maybe) >>> assert new_result == Success(1) + >>> failure_with_default: Result[int, str] = maybe_to_result(Nothing, 'abc') + >>> assert failure_with_default == Failure('abc') + Take a note, that type changes. Also, take a note that ``Success(None)`` will be converted to ``Nothing``. diff --git a/returns/converters.py b/returns/converters.py index cddd8b37d..864fb9ca0 100644 --- a/returns/converters.py +++ b/returns/converters.py @@ -1,4 +1,4 @@ -from typing import TypeVar +from typing import TypeVar, Union, overload from returns.functions import identity from returns.interfaces.bindable import BindableN @@ -71,12 +71,30 @@ def result_to_maybe( return Nothing +@overload def maybe_to_result( maybe_container: Maybe[_FirstType], ) -> Result[_FirstType, None]: + """No default case.""" + + +@overload +def maybe_to_result( + maybe_container: Maybe[_FirstType], + default_error: _SecondType, +) -> Result[_FirstType, _SecondType]: + """Default value case.""" + + +def maybe_to_result( + maybe_container: Maybe[_FirstType], + default_error: Union[_SecondType, None] = None, +) -> Result[_FirstType, Union[_SecondType, None]]: """ Converts ``Maybe`` container to ``Result`` container. + With optional ``default_error`` to be used for ``Failure``'s error value. + .. code:: python >>> from returns.maybe import Some, Nothing @@ -86,7 +104,9 @@ def maybe_to_result( >>> assert maybe_to_result(Some(None)) == Success(None) >>> assert maybe_to_result(Nothing) == Failure(None) + >>> assert maybe_to_result(Nothing, 'error') == Failure('error') + """ if is_successful(maybe_container): return Success(maybe_container.unwrap()) - return Failure(None) + return Failure(default_error) diff --git a/typesafety/test_converters/test_maybe_to_result.yml b/typesafety/test_converters/test_maybe_to_result.yml index a74080ec9..6a99eebe9 100644 --- a/typesafety/test_converters/test_maybe_to_result.yml +++ b/typesafety/test_converters/test_maybe_to_result.yml @@ -5,3 +5,12 @@ from returns.maybe import Maybe reveal_type(maybe_to_result(Maybe.from_value(1))) # N: Revealed type is "returns.result.Result[builtins.int, None]" + + +- case: maybe_to_result_default_error + disable_cache: false + main: | + from returns.converters import maybe_to_result + from returns.maybe import Maybe + + reveal_type(maybe_to_result(Maybe.from_value(1), 'a')) # N: Revealed type is "returns.result.Result[builtins.int, builtins.str]"