Skip to content

Commit

Permalink
Added early return implementation, easy to use do-style notation
Browse files Browse the repository at this point in the history
  • Loading branch information
danielSanchezQ committed Mar 28, 2024
1 parent fa8d8e2 commit 8fbeefc
Show file tree
Hide file tree
Showing 4 changed files with 90 additions and 2 deletions.
20 changes: 20 additions & 0 deletions examples/early_return.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
from rusty_results import Option, Some, Empty
from rusty_results import early_return


@early_return
def fail_on_operation() -> Option[int]:
value1 = Some(10)
value2 = Empty()
return Some(~value1 + ~value2)


def success_on_operation() -> Option[int]:
value1 = Some(10)
value2 = Some(10)
return Some(~value1 + ~value2)


if __name__ == "__main__":
print("Success so it return value: ", success_on_operation())
print("Fail so it return Empty: ", fail_on_operation())
2 changes: 1 addition & 1 deletion rusty_results/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
from .prelude import Option, Some, Empty, Result, Ok, Err
from .exceptions import UnwrapException
from .exceptions import UnwrapException, early_return
19 changes: 19 additions & 0 deletions rusty_results/exceptions.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,21 @@
from functools import wraps


class UnwrapException(Exception):
...


class EarlyReturnException[T](ValueError):
def __init__(self, value: T):
self.value = value
super().__init__(self.value)


def early_return(f):
@wraps(f)
def wrapper(*args, **kwargs):
try:
f(*args, **kwargs)
except EarlyReturnException as e:
return e.value
return wrapper
51 changes: 50 additions & 1 deletion rusty_results/prelude.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from abc import abstractmethod
from dataclasses import dataclass
from typing import cast, TypeVar, Union, Callable, Generic, Iterator, Tuple, Dict, Any
from rusty_results.exceptions import UnwrapException
from rusty_results.exceptions import UnwrapException, EarlyReturnException

try:
from pydantic.fields import ModelField
except ImportError: # pragma: no cover
Expand Down Expand Up @@ -250,6 +251,15 @@ def transpose(self) -> "Result[Option[T], E]":
"""
... # pragma: no cover

@abstractmethod
def early_return(self) -> T:
"""
Access hook for `early_return` wrapper style.
:return: Self if self is Some(T) otherwise
:raises: EarlyReturnException(Empty)
"""
...

@abstractmethod
def __bool__(self) -> bool:
... # pragma: no cover
Expand All @@ -260,6 +270,14 @@ def __contains__(self, item: T) -> bool:
def __iter__(self):
return self.iter()

def __invert__(self) -> T:
"""
Access hook for `early_return` wrapper style.
:return: Self if self is Some(T) otherwise
:raises: EarlyReturnException(Empty)
"""
return self.early_return()

@classmethod
def __get_validators__(cls):
yield cls.__validate
Expand Down Expand Up @@ -420,6 +438,10 @@ def transpose(self) -> "Result[Option[T], E]":
value: "ResultProtocol[T, E]" = self.Some
return value.map(Some)

def early_return(self) -> T:
# it is safe to unwrap here as we know we are Some
return self.unwrap()

def __bool__(self) -> bool:
return True

Expand Down Expand Up @@ -504,6 +526,10 @@ def flatten(self) -> "Option[T]":
def transpose(self) -> "Result[Option[T], E]":
return Ok(self)

def early_return(self) -> T:
# it is safe to unwrap here as we know we are some
raise EarlyReturnException(self)

def __bool__(self) -> bool:
return False

Expand Down Expand Up @@ -726,6 +752,23 @@ def transpose(self) -> Option["Result[T, E]"]:
"""
... # pragma: no cover

@abstractmethod
def early_return(self) -> T:
"""
Access hook for `early_return` wrapper style.
:return: T if self is Ok(T) otherwise
:raises: EarlyReturnException(Err(e))
"""
...

def __invert__(self) -> T:
"""
Access hook for `early_return` wrapper style.
:return: T if self is Ok(T) otherwise
:raises: EarlyReturnException(Err(e))
"""
return self.early_return()

@abstractmethod
def __bool__(self) -> bool:
... # pragma: no cover
Expand Down Expand Up @@ -898,6 +941,9 @@ def transpose(self) -> Option["Result[T, E]"]:
raise TypeError("Inner value is not of type Option")
return cast(Option, self.unwrap()).map(Ok)

def early_return(self) -> T:
return self.unwrap()

def __repr__(self):
return f"Ok({self.Ok})"

Expand Down Expand Up @@ -983,6 +1029,9 @@ def flatten(self) -> "Result[T, E]":
def transpose(self) -> Option["Result[T, E]"]:
return Some(self)

def early_return(self) -> T:
raise EarlyReturnException(self)

def __repr__(self):
return f"Err({self.Error})"

Expand Down

0 comments on commit 8fbeefc

Please sign in to comment.