Package: resultify
ResultifyThis is an opinionated, simplified fork ofdbrgn/result.Result is a simple, type annotated Result type for Python 3.6+ inspired byRust.The idea is that a result value can be eitherOk(value)orErr(error), with a way to differentiate between the two.OkandErrare both classes wrapping an arbitrary value.Result[T, E]is a generic type alias fortyping.Union[Ok[T], Err[E]].Requires Python 3.6 or higher!CaveatsNot allmethodshave been implemented, only the ones that make sense in the Python context. For example, themapmethods have been omitted, because they don't quite make sense without Rust's pattern matching.Since Rust's Optional type does not meaningfully translate to Python in a way type checkers are able to understand,ok()corresponds tounwrap()anderr()corresponds tounwrap_err(). On the other side, you don't have to return semantically unclear tuples anymore.By using.is_ok()andis_err()to check forOkorErryou get type safe access to the contained value. All of this in a package allowing easier handling of values that can be OK or not, without resorting to custom exceptions.APICreating an instance:>>> from resultify import Ok, Err
>>> ok = Ok('yay')
>>> res2 = Err('nay')Type safe checking whether a result isOkorErr.>>> res = Ok('yay')
>>> res.is_ok()
True
>>> res.is_err()
FalseUnwrap aResult, or raise if trying to extract a result from an error from a result or vice-versa:>>> ok = Ok('yay')
>>> err = Err('nay')
>>> ok.ok()
'yay'
>>> ok.err()
resultify.UnwrapError: Cannot unwrap error from Ok: Ok('yay')
>>> err.err()
'nay'
>>> err.ok()
resultify.UnwrapError: Cannot unwrap value from Err: Err('nay')For your convenience, and to appease the type checkers, simply creating anOkresult without value is the same as usingTrue:>>> ok = Ok()
>>> ok.ok()
TrueTo easily convert a function to returnResult, you can useresultify():>>> from resultify import resultify
>>> @resultify()
... def a():
...     return "value"
...
>>> a()
Ok('value')You can similarly auto-capture exceptions usingresultify(...). Please note that you can provide multiple exceptions, or none if you don't want to catch the exception! This is primarily useful when modeling code paths with a single good branch and multiple earlyraises, where one does not have to concern oneself with annoyingtry ... catch ...statements.>>> @resultify(TypeError)
... def foo():
...     raise TypeError()
...
>>> foo()
Err(TypeError())You canretrya function that returns aResulttype with a constant backoff.>>> from resultify import resultify, retry
... @retry(retries=2, delay=2, initial_delay=1):
... @resultify(Exception)
... def foo():
...     # do something that needs retrying hereThis example waits 1 second before executing the initial call, then attempts the initial call, then executes two retries, spaces out two seconds from the previous call. If any execution was a success, theOkvalue will be returned. If the retries were exhausted and noOkwas returned, we return theErrvalue.For those running Python 3.10, you can make use of Python'sstructural patternmatching like this:>>> from resultify import Ok, Err
>>> ok = Ok("ok!")
>>> match ok:
...     case Ok(foo): print(f"Yay {foo}")
...     case Err(foo): print(f"Nay {foo}")
...
Yay ok!
>>> no = Err("nope!")
>>> match no:
...     case Ok(foo): print(f"Yay {foo}")
...     case Err(foo): print(f"Nay {foo}")
...
Nay nope!Since documentation always lies, please refer to the unit tests for examples of usage.LicenseMIT License