Skip to content

Commit 7baf8a6

Browse files
committed
Adds .rescue method, refs #274
1 parent 367a6a2 commit 7baf8a6

File tree

8 files changed

+188
-2
lines changed

8 files changed

+188
-2
lines changed

returns/_generated/pointfree/rescue.pyi

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
from typing import Callable, TypeVar, overload
22

3-
from returns.context import RequiresContextIOResult, RequiresContextResult
3+
from returns.context import (
4+
RequiresContextFutureResult,
5+
RequiresContextIOResult,
6+
RequiresContextResult,
7+
)
48
from returns.future import FutureResult
59
from returns.io import IOResult
610
from returns.result import Result
@@ -60,6 +64,19 @@ def _rescue(
6064
...
6165

6266

67+
@overload
68+
def _rescue(
69+
function: Callable[
70+
[_ErrorType],
71+
RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType],
72+
],
73+
) -> Callable[
74+
[RequiresContextFutureResult[_EnvType, _ValueType, _ErrorType]],
75+
RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType],
76+
]:
77+
...
78+
79+
6380
@overload
6481
def _rescue(
6582
function: Callable[[_ErrorType], FutureResult[_ValueType, _NewErrorType]],

returns/context/requires_context_future_result.py

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,60 @@ def bind(
166166
),
167167
)
168168

169+
def rescue(
170+
self,
171+
function: Callable[
172+
[_ErrorType],
173+
'RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType]',
174+
],
175+
) -> 'RequiresContextFutureResult[_EnvType, _ValueType, _NewErrorType]':
176+
"""
177+
Composes this container with a function returning the same type.
178+
179+
.. code:: python
180+
181+
>>> import anyio
182+
>>> from returns.context import RequiresContextFutureResult
183+
>>> from returns.future import FutureResult
184+
>>> from returns.io import IOSuccess, IOFailure
185+
186+
>>> def rescuable(
187+
... arg: str,
188+
... ) -> RequiresContextFutureResult[str, str, str]:
189+
... return RequiresContextFutureResult(
190+
... lambda deps: FutureResult.from_value(
191+
... deps + arg,
192+
... ) if len(arg) > 1 else FutureResult.from_failure(
193+
... arg + deps,
194+
... ),
195+
... )
196+
197+
>>> assert anyio.run(
198+
... RequiresContextFutureResult.from_value('a').rescue(rescuable),
199+
... 'c',
200+
... ) == IOSuccess('a')
201+
202+
>>> assert anyio.run(
203+
... RequiresContextFutureResult.from_failure('a').rescue(
204+
... rescuable,
205+
... ),
206+
... 'c',
207+
... ) == IOFailure('ac')
208+
209+
>>> assert anyio.run(
210+
... RequiresContextFutureResult.from_failure('aa').rescue(
211+
... rescuable,
212+
... ),
213+
... 'b',
214+
... ) == IOSuccess('baa')
215+
216+
"""
217+
return RequiresContextFutureResult(
218+
lambda deps: self(deps).rescue(
219+
lambda inner: function(inner)(deps), # type: ignore
220+
),
221+
)
222+
169223
def value_or( # noqa: WPS234
170224
self, default_value: _FirstType,
171225
) -> Callable[

typesafety/test_context/test_requires_context_future_result/test_requires_context_future_result.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,19 @@
2121
reveal_type(x.bind(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.bool*, builtins.float]'
2222
2323
24+
- case: requires_context_future_result_rescue
25+
disable_cache: true
26+
main: |
27+
from returns.context import RequiresContextFutureResult
28+
29+
x: RequiresContextFutureResult[str, int, float]
30+
31+
def test(param: float) -> RequiresContextFutureResult[str, int, bool]:
32+
...
33+
34+
reveal_type(x.rescue(test)) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.int, builtins.bool*]'
35+
36+
2437
- case: requires_context_future_result_value_or
2538
disable_cache: true
2639
main: |
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
- case: requires_context_future_result_success_cast
2+
disable_cache: true
3+
main: |
4+
from returns.context import RequiresContextFutureResult
5+
6+
first: RequiresContextFutureResult[str, object, Exception] = RequiresContextFutureResult.from_value(1)
7+
reveal_type(first) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.object, builtins.Exception]'
8+
9+
10+
- case: requires_context_future_result_failure_cast
11+
disable_cache: true
12+
main: |
13+
from returns.context import RequiresContextFutureResult
14+
15+
first: RequiresContextFutureResult[str, object, Exception] = RequiresContextFutureResult.from_failure(TypeError())
16+
reveal_type(first) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.object, builtins.Exception]'
17+
18+
19+
- case: requires_context_future_result_env_cast
20+
disable_cache: true
21+
main: |
22+
from returns.context import RequiresContextFutureResult
23+
24+
first: RequiresContextFutureResult[object, object, Exception]
25+
second: RequiresContextFutureResult[str, object, Exception] = first
26+
27+
reveal_type(second) # N: Revealed type is 'returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.str, builtins.object, builtins.Exception]'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
- case: requires_context_ioresult_success_cast
2+
disable_cache: true
3+
main: |
4+
from returns.context import RequiresContextIOResult
5+
6+
first: RequiresContextIOResult[str, object, Exception] = RequiresContextIOResult.from_value(1)
7+
reveal_type(first) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.object, builtins.Exception]'
8+
9+
10+
- case: requires_context_ioresult_failure_cast
11+
disable_cache: true
12+
main: |
13+
from returns.context import RequiresContextIOResult
14+
15+
first: RequiresContextIOResult[str, object, Exception] = RequiresContextIOResult.from_failure(TypeError())
16+
reveal_type(first) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.object, builtins.Exception]'
17+
18+
19+
- case: requires_context_ioresult_env_cast
20+
disable_cache: true
21+
main: |
22+
from returns.context import RequiresContextIOResult
23+
24+
first: RequiresContextIOResult[object, object, Exception]
25+
second: RequiresContextIOResult[str, object, Exception] = first
26+
27+
reveal_type(second) # N: Revealed type is 'returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.str, builtins.object, builtins.Exception]'
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
- case: requires_context_result_success_cast
2+
disable_cache: true
3+
main: |
4+
from returns.context import RequiresContextResult
5+
6+
first: RequiresContextResult[str, object, Exception] = RequiresContextResult.from_value(1)
7+
reveal_type(first) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.object, builtins.Exception]'
8+
9+
10+
- case: requires_context_result_failure_cast
11+
disable_cache: true
12+
main: |
13+
from returns.context import RequiresContextResult
14+
15+
first: RequiresContextResult[str, object, Exception] = RequiresContextResult.from_failure(TypeError())
16+
reveal_type(first) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.object, builtins.Exception]'
17+
18+
19+
- case: requires_context_result_env_cast
20+
disable_cache: true
21+
main: |
22+
from returns.context import RequiresContextResult
23+
24+
first: RequiresContextResult[object, object, Exception]
25+
second: RequiresContextResult[str, object, Exception] = first
26+
27+
reveal_type(second) # N: Revealed type is 'returns.context.requires_context_result.RequiresContextResult[builtins.str, builtins.object, builtins.Exception]'

typesafety/test_pointfree/test_rescue.yml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,18 @@
4646
reveal_type(rescue(test)) # N: Revealed type is 'def (returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.float*, builtins.float*]) -> returns.context.requires_context_ioresult.RequiresContextIOResult[builtins.int*, builtins.float*, builtins.str*]'
4747
4848
49+
- case: rescue_context_future_result
50+
disable_cache: true
51+
main: |
52+
from returns.pointfree import rescue
53+
from returns.context import RequiresContextFutureResult
54+
55+
def test(arg: float) -> RequiresContextFutureResult[int, float, str]:
56+
...
57+
58+
reveal_type(rescue(test)) # N: Revealed type is 'def (returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.float*, builtins.float*]) -> returns.context.requires_context_future_result.RequiresContextFutureResult[builtins.int*, builtins.float*, builtins.str*]'
59+
60+
4961
- case: rescue_future_result
5062
disable_cache: true
5163
main: |

typesafety/test_result/test_result_type_cast.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
- case: result_success_cast
1+
- case: result_success_cast1
22
disable_cache: true
33
main: |
44
from returns.result import Result, Success
@@ -7,6 +7,15 @@
77
reveal_type(first) # N: Revealed type is 'returns.result.Result[builtins.int, builtins.Exception]'
88
99
10+
- case: result_success_cast2
11+
disable_cache: true
12+
main: |
13+
from returns.result import Result, Success
14+
15+
first: Result[object, Exception] = Success(1)
16+
reveal_type(first) # N: Revealed type is 'returns.result.Result[builtins.object, builtins.Exception]'
17+
18+
1019
- case: result_failure_cast1
1120
disable_cache: true
1221
main: |

0 commit comments

Comments
 (0)