def test_io_bind(): """Ensures that IO container supports ``.bind()`` method.""" io: IO[int] = IO('1').bind( lambda number: IO(int(number)), ) assert io == IO(1)
def test_io_map(): """Ensures that IO container supports ``.map()`` method.""" io: IO[float] = IO(1).map( lambda number: number / 2, ) assert io == IO(0.5)
def __call__(self, user_id: int) -> IO[Result[float, Exception]]: """Fetches `UserProfile` TypedDict from foreign API.""" return flow( user_id, self._make_request, IO.lift(bind(self._parse_json)), )
async def test_inner_value(subtests): """Ensure that coroutine correct value is preserved for all units.""" containers = [ # We have to define these values inside the test, because # otherwise `anyio` will `await` reused coroutines. # And they have to be fresh. That's why we use subtests for it. FutureResult.from_value(1), FutureResult.from_failure(1), FutureResult.from_io(IO(1)), FutureResult.from_failed_io(IO(1)), FutureResult.from_ioresult(IOSuccess(1)), FutureResult.from_ioresult(IOFailure(1)), FutureResult.from_result(Success(1)), FutureResult.from_result(Failure(1)), FutureResult.from_future(Future.from_value(1)), FutureResult.from_failed_future(Future.from_value(1)), FutureResult.from_typecast(Future.from_value(Success(1))), ] for container in containers: with subtests.test(container=container): result_inst = await container assert result_inst._inner_value._inner_value == 1 # noqa: WPS437
async def test_inner_value(subtests): """Ensure that coroutine correct value is preserved for all units.""" containers: List[Awaitable[Any]] = [ # We have to define these values inside the test, because # otherwise `anyio` will `await` reused coroutines. # And they have to be fresh. That's why we use subtests for it. Future.from_value(1), Future.from_io(IO(1)), Future.from_future_result(FutureResult.from_value(1)), Future.from_future_result(FutureResult.from_failure(1)), ] for container in containers: with subtests.test(container=container): assert isinstance(await container, IO)
async def failure(self) -> IO[_ErrorType]: """ Get failed value or raise exception. .. code:: pycon >>> import anyio >>> from returns.future import FutureResult >>> from returns.io import IO >>> assert anyio.run(FutureResult.from_failure(1).failure) == IO(1) >>> anyio.run(FutureResult.from_value(1).failure) Traceback (most recent call last): ... returns.primitives.exceptions.UnwrapFailedError """ return IO((await self._inner_value).failure())
def _squash_io(*args): """ Unwraps ``IO`` values, merges them into tuple, and wraps back. .. code:: python >>> from returns.io import IO >>> from returns.converters import squash_io >>> assert squash_io(IO('a'), IO('b')) == IO(('a', 'b')) Why this only exists for ``IO`` and ``RequiresContext``? Because these types represent real values, that do not possibly fail. How would you, for example, squash two ``Result`` values? ``Success(1)`` and ``Failure(2)`` would not give you a tuple when squashed. """ return IO( tuple(container._inner_value # noqa: WPS437 for container in args))
async def awaitable(self) -> IO[_ValueType]: """ Transforms ``Future[a]`` to ``Awaitable[IO[a]]``. Use this method when you need a real coroutine. Like for ``asyncio.run`` calls. Note, that returned value will be wrapped in :class:`returns.io.IO` container. .. code:: python >>> import anyio >>> from returns.future import Future >>> from returns.io import IO >>> assert anyio.run(Future.from_value(1).awaitable) == IO(1) """ return IO(await self._inner_value)
async def value_or( self, default_value: _NewValueType, ) -> IO[Union[_ValueType, _NewValueType]]: """ Get value or default value. .. code:: python >>> import anyio >>> from returns.future import FutureResult >>> from returns.io import IO >>> async def main(): ... first = await FutureResult.from_value(1).value_or(2) ... second = await FutureResult.from_failure(3).value_or(4) ... return first, second >>> assert anyio.run(main) == (IO(1), IO(4)) """ return IO((await self._inner_value).value_or(default_value))
async def async_value_or( container: 'FutureResult[_ValueType, _ErrorType]', default_value: _NewValueType, ) -> IO[Union[_ValueType, _NewValueType]]: """Return async value or default value.""" return IO((await container._inner_value).value_or(default_value))
def test_fold_loop_recursion_limit(): """Ensures that ``.loop`` method is recurion safe.""" limit = sys.getrecursionlimit() + 1 iterable = (IO(1) for _ in range(limit)) assert Fold.loop(iterable, IO(0), _sum_two) == IO(limit)
def test_bind_with_io(): """Ensures that functions can be composed and return type is correct.""" binded = bind(_io_function) assert binded(IO(1)) == IO('2')
def _io_function(argument: int) -> IO[str]: return IO(str(argument + 1))
def test_pipe_user_profile(): """Ensures that example from the readme works.""" assert _UserProfile()(200) == IO(Success(1.0))
def test_unsafe_perform_io(): """Ensures that unsafe_perform_io returns the object itself.""" id_object = object() assert unsafe_perform_io(IO(id_object)) is id_object
def test_io_pickle_restore(): """Ensures that object can be restored.""" container = IO(2) container.__setstate__(1) # noqa: WPS609 assert container == IO(1)
def test_impure(): """Ensures that impure returns IO container.""" impure_result = impure(_fake_impure_function)(1) assert isinstance(impure_result, IO) assert impure_result == IO(1)
def test_failure_iofailure(): """Ensures that failure works for IOFailure container.""" assert IOFailure(5).failure() == IO(5)
from returns.context import ( RequiresContext, RequiresContextIOResult, RequiresContextResult, ) from returns.converters import flatten from returns.io import IO, IOFailure, IOSuccess from returns.maybe import Nothing, Some from returns.result import Failure, Success @pytest.mark.parametrize( ('container', 'merged'), [ # Flattens: (IO(IO(1)), IO(1)), (Success(Success({})), Success({})), (IOSuccess(IOSuccess(1)), IOSuccess(1)), (Some(Some(None)), Nothing), (Some(Some([])), Some([])), # Nope: (Failure(Failure('a')), Failure(Failure('a'))), (IOFailure(IOFailure('a')), IOFailure(IOFailure('a'))), ]) def test_flatten(container, merged): """Ensures that `flatten` is always returning the correct type.""" assert flatten(container) == merged @pytest.mark.parametrize(('container', 'merged'), [
def test_return_true_with_io_container(): """Ensures `is_io` function will return True for IO.""" assert is_io(IO(1.0)) is True
from returns.future import Future, FutureFailure, FutureResult, FutureSuccess from returns.io import IO, IOFailure, IOSuccess from returns.iterables import Fold from returns.maybe import Nothing, Some from returns.result import Failure, Success def _sum_two(first): return lambda second: first + second @pytest.mark.parametrize( ('iterable', 'sequence'), [ # Regular types: ([], IO(10)), ([IO(1)], IO(11)), ([IO(1), IO(2)], IO(13)), # Can fail: ([], Success(10)), ([Success(1)], Success(11)), ([Success(1), Success(2)], Success(13)), ( [Failure('a'), Success(1), Success(2)], Failure('a'), ), ([Success(1), Failure('a')], Failure('a')), ([Failure('a'), Failure('b')], Failure('a')), ([], Some(10)), ([Some(1)], Some(11)),
async def async_unwrap( container: 'FutureResult[_ValueType, _ErrorType]', ) -> IO[_ValueType]: """Async unwrap a container.""" return IO((await container._inner_value).unwrap())
async def async_failure( container: 'FutureResult[_ValueType, _ErrorType]', ) -> IO[_ErrorType]: """Async unwrap an error from container.""" return IO((await container._inner_value).failure())
def test_io_pickle(): """Tests how pickle protocol works for containers.""" assert IO(1).__getstate__() == 1 # noqa: WPS609
def test_unwrap_iosuccess(): """Ensures that unwrap works for IOSuccess container.""" assert IOSuccess(5).unwrap() == IO(5)
ReaderFutureResult, ReaderIOResult, ReaderResult, ) from returns.contrib.pytest import ReturnsAsserts from returns.future import Future, FutureResult from returns.io import IO, IOResult from returns.maybe import Maybe from returns.primitives.asserts import assert_equal from returns.primitives.container import BaseContainer from returns.result import Result _containers: Sequence[BaseContainer] = ( Result.from_failure(1), Result.from_value(1), IO(1), IOResult.from_failure(1), IOResult.from_value(1), Maybe.from_value(1), Maybe.from_value(None), Maybe.from_optional(None), Future.from_value(1), FutureResult.from_value(1), FutureResult.from_failure(1), Reader.from_value(1), ReaderResult.from_value(1), ReaderResult.from_failure(1), ReaderIOResult.from_value(1), ReaderIOResult.from_failure(1), ReaderFutureResult.from_value(1), ReaderFutureResult.from_failure(1),
def test_ioresult_value_or(): """Ensures that ``value_or`` works correctly.""" assert IOSuccess(1).value_or(0) == IO(1) assert IOFailure(1).value_or(0) == IO(0)
ReaderFutureResult, ReaderIOResult, ReaderResult, ) from returns.future import Future, FutureFailure, FutureResult, FutureSuccess from returns.io import IO, IOFailure, IOSuccess from returns.iterables import Fold from returns.maybe import Nothing, Some from returns.result import Failure, Success @pytest.mark.parametrize( ('iterable', 'sequence'), [ # Regular types: ([], IO(())), ([IO(1)], IO((1, ))), ([IO(1), IO(2)], IO((1, 2))), # Can fail: ([], Success(())), ([Success(1)], Success((1, ))), ([Success(1), Success(2)], Success((1, 2))), ( [Failure('a'), Success(1), Success(2)], Failure('a'), ), ([Success(1), Failure('a')], Failure('a')), ([Failure('a'), Failure('b')], Failure('a')), ([], Some(())), ([Some(1)], Some((1, ))),
async def test_impure_async(): """Ensures that impure returns IO container for async.""" impure_result = await impure(_fake_impure_coroutine)(1) assert isinstance(impure_result, IO) assert impure_result == IO(1)
def test_fold_collect_recursion_limit(): """Ensures that ``.collect`` method is recurion safe.""" limit = sys.getrecursionlimit() + 1 iterable = (IO(1) for _ in range(limit)) expected = IO((1, ) * limit) assert Fold.collect(iterable, IO(())) == expected