Skip to content

Commit 4bd2902

Browse files
committed
Add returns_result and unwrap_or_return to emulate question mark operator
1 parent 0b855e1 commit 4bd2902

File tree

3 files changed

+49
-1
lines changed

3 files changed

+49
-1
lines changed

src/result/__init__.py

+2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
UnwrapError,
77
as_async_result,
88
as_result,
9+
returns_result,
910
is_ok,
1011
is_err,
1112
do,
@@ -20,6 +21,7 @@
2021
"UnwrapError",
2122
"as_async_result",
2223
"as_result",
24+
"returns_result",
2325
"is_ok",
2426
"is_err",
2527
"do",

src/result/result.py

+30
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,12 @@ def unwrap_or_raise(self, e: object) -> T:
146146
"""
147147
return self._value
148148

149+
def unwrap_or_return(self) -> T:
150+
"""
151+
Return the value.
152+
"""
153+
return self._value
154+
149155
def map(self, op: Callable[[T], U]) -> Ok[U]:
150156
"""
151157
The contained result is `Ok`, so return `Ok` with original value mapped to
@@ -358,6 +364,12 @@ def unwrap_or_raise(self, e: Type[TBE]) -> NoReturn:
358364
"""
359365
raise e(self._value)
360366

367+
def unwrap_or_return(self) -> NoReturn:
368+
"""
369+
The contained result is ``Err``, raise DoException with self.
370+
"""
371+
raise DoException(self)
372+
361373
def map(self, op: object) -> Err[E]:
362374
"""
363375
Return `Err` with the same value
@@ -464,6 +476,24 @@ def result(self) -> Result[Any, Any]:
464476
return self._result
465477

466478

479+
def returns_result() -> Callable[[Callable[P, Result[R, E]]], Callable[P, Result[R, E]]]:
480+
"""
481+
Make a decorator to turn a function into one that allows using unwrap_or_return.
482+
"""
483+
def decorator(f: Callable[P, Result[R, E]]) -> Callable[P, Result[R, E]]:
484+
@functools.wraps(f)
485+
def wrapper(*args: P.args, **kwargs: P.kwargs) -> Result[R, E]:
486+
try:
487+
return f(*args, **kwargs)
488+
except DoException as e:
489+
out: Err[E] = e.err # type: ignore
490+
return out
491+
492+
return wrapper
493+
494+
return decorator
495+
496+
467497
def as_result(
468498
*exceptions: Type[TBE],
469499
) -> Callable[[Callable[P, R]], Callable[P, Result[R, TBE]]]:

tests/test_result.py

+17-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import pytest
66

7-
from result import Err, Ok, OkErr, Result, UnwrapError, as_async_result, as_result
7+
from result import Err, Ok, OkErr, Result, UnwrapError, as_async_result, as_result, returns_result
88

99

1010
def test_ok_factories() -> None:
@@ -158,6 +158,22 @@ def test_unwrap_or_raise() -> None:
158158
assert exc_info.value.args == ('nay',)
159159

160160

161+
def test_unwrap_or_return() -> None:
162+
@returns_result()
163+
def func(yay):
164+
if yay:
165+
o = Ok('yay')
166+
value = o.unwrap_or_return()
167+
return Ok(value)
168+
else:
169+
n = Err('nay')
170+
value = n.unwrap_or_return()
171+
assert False
172+
173+
assert func(True).ok() == 'yay'
174+
assert func(False).err() == 'nay'
175+
176+
161177
def test_map() -> None:
162178
o = Ok('yay')
163179
n = Err('nay')

0 commit comments

Comments
 (0)