diff --git a/CHANGELOG.md b/CHANGELOG.md index 4e81def09..ec60379b6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,13 @@ See [0Ver](https://0ver.org/). which provides a default error value for `Failure` +## 0.24.1 + +### Bugfixes + +- Add pickling support for `UnwrapFailedError` exception + + ## 0.23.0 ### Features diff --git a/returns/primitives/exceptions.py b/returns/primitives/exceptions.py index b5e4a3795..21a65d013 100644 --- a/returns/primitives/exceptions.py +++ b/returns/primitives/exceptions.py @@ -21,6 +21,16 @@ def __init__(self, container: Unwrappable) -> None: super().__init__() self.halted_container = container + def __reduce__(self): # noqa: WPS603 + """Custom reduce method for pickle protocol. + + This helps properly reconstruct the exception during unpickling. + """ + return ( + self.__class__, # callable + (self.halted_container,), # args to callable + ) + class ImmutableStateError(AttributeError): """ diff --git a/tests/test_primitives/test_exceptions/test_pickle_unwrap_failed_error.py b/tests/test_primitives/test_exceptions/test_pickle_unwrap_failed_error.py new file mode 100644 index 000000000..6dda4b9a3 --- /dev/null +++ b/tests/test_primitives/test_exceptions/test_pickle_unwrap_failed_error.py @@ -0,0 +1,29 @@ +import pickle # noqa: S403 + +from returns.maybe import Nothing +from returns.primitives.exceptions import UnwrapFailedError +from returns.result import Failure + + +def test_pickle_unwrap_failed_error_from_maybe(): + """Ensures that UnwrapFailedError with Maybe can be pickled.""" + serialized = None + try: + Nothing.unwrap() # This will raise UnwrapFailedError + except UnwrapFailedError as error: + serialized = pickle.dumps(error) + + deserialized_error = pickle.loads(serialized) # noqa: S301 + assert deserialized_error.halted_container == Nothing + + +def test_pickle_unwrap_failed_error_from_result(): + """Ensures that UnwrapFailedError with Result can be pickled.""" + serialized = None + try: + Failure('error').unwrap() # This will raise UnwrapFailedError + except UnwrapFailedError as error: + serialized = pickle.dumps(error) + + deserialized_error = pickle.loads(serialized) # noqa: S301 + assert deserialized_error.halted_container == Failure('error')