Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
32 changes: 32 additions & 0 deletions tests/test_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,38 @@ async def test_err_unwraps() -> None:
)


@pytest.mark.parametrize("error", [ValueError("err"), KeyboardInterrupt()])
async def test_err_unwrap_preserves_underlying_exception(error: BaseException) -> None:
try:
raise error
except BaseException:
pass

underlying_traceback = error.__traceback__
assert underlying_traceback is not None

result = Err(error)

with pytest.raises(ErrUnwrapError, match="on err") as exc_info:
result.unwrap(on_err="on err")

assert exc_info.value.__cause__ is error
assert exc_info.value.__cause__.__traceback__ is underlying_traceback

with pytest.raises(ErrUnwrapError) as future_exc_info:
await FutureResult.from_(result).unwrap()

assert future_exc_info.value.__cause__ is error
assert future_exc_info.value.__cause__.__traceback__ is underlying_traceback


def test_err_unwrap_does_not_chain_non_exception_value() -> None:
with pytest.raises(ErrUnwrapError) as exc_info:
Err("err").unwrap()

assert exc_info.value.__cause__ is None


@pytest.mark.parametrize(
("result", "target"),
[
Expand Down
5 changes: 4 additions & 1 deletion wird/_result.py
Original file line number Diff line number Diff line change
Expand Up @@ -689,7 +689,10 @@ def unwrap[R](
def unwrap(self, *, on_err: str = "expected Ok, got Err") -> Any: ...

def unwrap(self, **kwargs) -> Any:
raise ErrUnwrapError(kwargs.get("on_err", "expected Ok, got Err"))
error = ErrUnwrapError(kwargs.get("on_err", "expected Ok, got Err"))
if isinstance(self.internal, BaseException):
raise error from self.internal
raise error

def unwrap_or[T](self, /, other: T) -> T:
return other
Expand Down