Skip to content

Commit ce730f7

Browse files
committed
Refs #243
1 parent 1d33670 commit ce730f7

File tree

4 files changed

+232
-0
lines changed

4 files changed

+232
-0
lines changed

returns/context/requires_context_io_result.py

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -612,6 +612,52 @@ def lift_result(
612612
"""
613613
return lambda container: container.bind_result(function)
614614

615+
@classmethod
616+
def lift_ioresult(
617+
cls,
618+
function: Callable[[_ValueType], IOResult[_NewValueType, _ErrorType]],
619+
) -> Callable[
620+
['RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]'],
621+
'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]',
622+
]:
623+
"""
624+
Lifts function from ``IOResult`` for better composition.
625+
626+
In other words, it modifies the function's
627+
signature from: ``a -> IOResult[b, c]`` to:
628+
``RequiresContextIOResult[env, a, c]``
629+
-> ``RequiresContextIOResult[env, b, c]``
630+
631+
Similar to :meth:`~RequiresContextIOResult.lift`,
632+
but works with other type.
633+
634+
.. code:: python
635+
636+
>>> from returns.context import RequiresContextIOResult
637+
>>> from returns.io import IOSuccess, IOFailure, IOResult
638+
639+
>>> def function(arg: int) -> IOResult[str, int]:
640+
... if arg > 0:
641+
... return IOSuccess(str(arg) + '!')
642+
... return IOFailure(arg)
643+
...
644+
>>> deps = RequiresContextIOResult.empty
645+
646+
>>> assert RequiresContextIOResult.lift_ioresult(function)(
647+
... RequiresContextIOResult.from_success(1),
648+
... )(deps) == IOSuccess('1!')
649+
650+
>>> assert RequiresContextIOResult.lift_ioresult(function)(
651+
... RequiresContextIOResult.from_success(0),
652+
... )(deps) == IOFailure(0)
653+
654+
>>> assert RequiresContextIOResult.lift_ioresult(function)(
655+
... RequiresContextIOResult.from_failure('nope'),
656+
... )(deps) == IOFailure('nope')
657+
658+
"""
659+
return lambda container: container.bind_ioresult(function)
660+
615661
@classmethod
616662
def lift_context(
617663
cls,
@@ -654,6 +700,51 @@ def lift_context(
654700
"""
655701
return lambda container: container.bind_context(function)
656702

703+
@classmethod
704+
def lift_context_result(
705+
cls,
706+
function: Callable[
707+
[_ValueType],
708+
RequiresContextResult[_EnvType, _NewValueType, _ErrorType],
709+
],
710+
) -> Callable[
711+
['RequiresContextIOResult[_EnvType, _ValueType, _ErrorType]'],
712+
'RequiresContextIOResult[_EnvType, _NewValueType, _ErrorType]',
713+
]:
714+
"""
715+
Lifts function from ``RequiresContextResult`` for better composition.
716+
717+
In other words, it modifies the function's
718+
signature from: ``a -> RequiresContextResult[env, b, c]`` to:
719+
``RequiresContextIOResult[env, a, c]``
720+
-> ``RequiresContextIOResult[env, b, c]``
721+
722+
Similar to :meth:`~RequiresContextIOResult.lift`,
723+
but works with other type.
724+
725+
.. code:: python
726+
727+
>>> from returns.context import RequiresContextResult
728+
>>> from returns.io import IOSuccess, IOFailure
729+
>>> from returns.result import Success
730+
731+
>>> def function(arg: int) -> RequiresContextResult[str, int, str]:
732+
... return RequiresContextResult(
733+
... lambda deps: Success(len(deps) + arg),
734+
... )
735+
...
736+
737+
>>> assert RequiresContextIOResult.lift_context_result(function)(
738+
... RequiresContextIOResult.from_success(2),
739+
... )('abc') == IOSuccess(5)
740+
741+
>>> assert RequiresContextIOResult.lift_context_result(function)(
742+
... RequiresContextIOResult.from_failure(0),
743+
... )('abc') == IOFailure(0)
744+
745+
"""
746+
return lambda container: container.bind_context_result(function)
747+
657748
@classmethod
658749
def from_result(
659750
cls, inner_value: Result[_ValueType, _ErrorType],
@@ -815,6 +906,9 @@ def from_failure(
815906
"""
816907
return RequiresContextIOResult(lambda _: IOFailure(inner_value))
817908

909+
# TODO: support from_successful_result_context
910+
# TODO: support from_failed_result_context
911+
818912

819913
@final
820914
class ContextIOResult(Immutable, Generic[_EnvType]):
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
- case: context_result_io_ask1
2+
disable_cache: true
3+
main: |
4+
from returns.context import ContextIOResult
5+
6+
reveal_type(ContextIOResult.ask()) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[<nothing>, <nothing>, Any]'
7+
8+
9+
- case: context_result_io_ask2
10+
disable_cache: true
11+
main: |
12+
from returns.context import ContextIOResult
13+
14+
reveal_type(ContextIOResult[str].ask()) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[builtins.str*, builtins.str*, Any]'
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
- case: requires_context_io_result_lift
2+
disable_cache: true
3+
main: |
4+
from returns.context import RequiresContextIOResult
5+
6+
def test(arg: int) -> str:
7+
return str(arg)
8+
9+
reveal_type(RequiresContextIOResult.lift(test)) # N: Revealed type is 'def (returns.context.requires_context_io_result.RequiresContextIOResult[<nothing>, builtins.int*, <nothing>]) -> returns.context.requires_context_io_result.RequiresContextIOResult[<nothing>, builtins.str*, <nothing>]'
10+
11+
12+
- case: requires_context_io_result_lift_result
13+
disable_cache: true
14+
main: |
15+
from returns.context import RequiresContextIOResult
16+
from returns.result import Result, Success
17+
18+
def test(arg: int) -> Result[str, int]:
19+
return Success(str(arg))
20+
21+
reveal_type(RequiresContextIOResult.lift_result(test)) # N: Revealed type is 'def (returns.context.requires_context_io_result.RequiresContextIOResult[<nothing>, builtins.int*, builtins.int*]) -> returns.context.requires_context_io_result.RequiresContextIOResult[<nothing>, builtins.str*, builtins.int*]'
22+
23+
24+
- case: requires_context_io_result_lift_ioresult
25+
disable_cache: true
26+
main: |
27+
from returns.context import RequiresContextIOResult
28+
from returns.result import Result, Success
29+
from returns.io import IOResult, IOSuccess
30+
31+
def test(arg: int) -> IOResult[str, int]:
32+
return IOSuccess(str(arg))
33+
34+
reveal_type(RequiresContextIOResult.lift_ioresult(test)) # N: Revealed type is 'def (returns.context.requires_context_io_result.RequiresContextIOResult[<nothing>, builtins.int*, builtins.int*]) -> returns.context.requires_context_io_result.RequiresContextIOResult[<nothing>, builtins.str*, builtins.int*]'
35+
36+
37+
- case: requires_context_io_result_lift_context
38+
disable_cache: true
39+
main: |
40+
from returns.context import RequiresContextIOResult, RequiresContext
41+
42+
def test(arg: int) -> RequiresContext[int, str]:
43+
return RequiresContext(lambda deps: str(arg + deps))
44+
45+
reveal_type(RequiresContextIOResult.lift_context(test)) # N: Revealed type is 'def (returns.context.requires_context_io_result.RequiresContextIOResult[builtins.int*, builtins.int*, <nothing>]) -> returns.context.requires_context_io_result.RequiresContextIOResult[builtins.int*, builtins.str*, <nothing>]'
46+
47+
48+
- case: requires_context_io_result_lift_context_result
49+
disable_cache: true
50+
main: |
51+
from returns.context import RequiresContextIOResult, RequiresContextResult
52+
from returns.result import Success
53+
54+
def test(arg: int) -> RequiresContextResult[int, str, int]:
55+
return RequiresContextResult(lambda deps: Success(str(arg + deps)))
56+
57+
reveal_type(RequiresContextIOResult.lift_context_result(test)) # N: Revealed type is 'def (returns.context.requires_context_io_result.RequiresContextIOResult[builtins.int*, builtins.int*, builtins.int*]) -> returns.context.requires_context_io_result.RequiresContextIOResult[builtins.int*, builtins.str*, builtins.int*]'
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
- case: requires_context_result_success
2+
disable_cache: true
3+
main: |
4+
from returns.context import RequiresContextIOResult
5+
6+
reveal_type(RequiresContextIOResult.from_success(1)) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[Any, builtins.int*, Any]'
7+
8+
9+
- case: requires_context_result_failure
10+
disable_cache: true
11+
main: |
12+
from returns.context import RequiresContextIOResult
13+
14+
reveal_type(RequiresContextIOResult.from_failure(1)) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[Any, Any, builtins.int*]'
15+
16+
17+
- case: requires_context_result_result
18+
disable_cache: true
19+
main: |
20+
from returns.context import RequiresContextIOResult
21+
from returns.result import Result
22+
23+
r: Result[int, str]
24+
25+
reveal_type(RequiresContextIOResult.from_result(r)) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[Any, builtins.int*, builtins.str*]'
26+
27+
28+
- case: requires_context_result_ioresult
29+
disable_cache: true
30+
main: |
31+
from returns.context import RequiresContextIOResult
32+
from returns.io import IOResult
33+
34+
r: IOResult[int, str]
35+
36+
reveal_type(RequiresContextIOResult.from_ioresult(r)) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[Any, builtins.int*, builtins.str*]'
37+
38+
39+
- case: requires_context_result_typecast
40+
disable_cache: true
41+
main: |
42+
from returns.context import RequiresContextIOResult, RequiresContext
43+
from returns.io import IOResult
44+
45+
r: RequiresContext[float, IOResult[int, str]]
46+
47+
reveal_type(RequiresContextIOResult.from_typecast(r)) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[builtins.float*, builtins.int*, builtins.str*]'
48+
49+
50+
- case: requires_context_result_successful_context
51+
disable_cache: true
52+
main: |
53+
from returns.context import RequiresContextIOResult, RequiresContext
54+
55+
r: RequiresContext[float, str]
56+
57+
reveal_type(RequiresContextIOResult.from_successful_context(r)) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[builtins.float*, builtins.str*, Any]'
58+
59+
60+
- case: requires_context_result_failed_context
61+
disable_cache: true
62+
main: |
63+
from returns.context import RequiresContextIOResult, RequiresContext
64+
65+
r: RequiresContext[float, str]
66+
67+
reveal_type(RequiresContextIOResult.from_failed_context(r)) # N: Revealed type is 'returns.context.requires_context_io_result.RequiresContextIOResult[builtins.float*, Any, builtins.str*]'

0 commit comments

Comments
 (0)