Result

See the original Rust documentation here.


patina.result Error handling with the Result type.
Result Result is a type that represents either success (Ok()) or failure (Err()).
Ok(value)
Err(error)

Error handling with the Result type.

Result[T, E] is the type used for returning and propagating errors. It is an enum with the variants, Ok(T), representing success and containing a value, and Err(E), representing error and containing an error value.

Examples

A simple function returning Result might be defined and used like so:

>>> from enum import auto, Enum
>>>
>>> class Version(Enum):
...     version_1 = auto()
...     version_2 = auto()
...
>>> def parse_version(header: bytes) -> Result[Version, str]:
...     if len(header) == 0:
...         return Err("invalid header length")
...     elif header[0] == 1:
...         return Ok(Version.version_1)
...     elif header[0] == 2:
...         return Ok(Version.version_2)
...     else:
...         return Err("invalid version")
...
>>> version = parse_version(bytes([1, 2, 3, 4]))
>>> if version.is_ok():
...     print(f"working with version: {version.unwrap()}")
... else:
...     print(f"error parsing header: {version.unwrap_err()}")
...
working with version: Version.version_1

Pattern matching on Results is clear and straightforward for simple cases (in Rust), but Result comes with some convenience methods that make working with it more succinct.

>>> good_result: Result[int, int] = Ok(10)
>>> bad_result: Result[int, int] = Err(10)
>>>
>>> # The `is_ok` and `is_err` methods do what they say.
>>> good_result.is_ok() and not good_result.is_err()
True
>>> bad_result.is_err() and not bad_result.is_ok()
True
>>>
>>> # `map` consumes the `Result` and produces another.
>>> good_result: Result[int, int] = good_result.map(lambda i: i + 1)
>>> bad_result: Result[int, int] = bad_result.map(lambda i: i - 1)
>>>
>>> # Use `and_then` to continue their computation.
>>> good_result: Result[bool, int] = good_result.and_then(lambda i: Ok(i == 11))
>>>
>>> # Use `or_else` to handle the error.
>>> bad_result: Result[int, int] = bad_result.or_else(lambda i: Ok(i + 20))
>>>
>>> # Consume the result and return the contents with `unwrap`.
>>> final_awesome_result = good_result.unwrap()
>>> final_awesome_result
True

The Result Type

class patina.result.Result

Result is a type that represents either success (Ok()) or failure (Err()).

is_ok() → bool

Returns True if the result is Ok().

Basic usage:

>>> x: Result[int, str] = Ok(-3)
>>> x.is_ok()
True
>>>
>>> x: Result[int, str] = Err("Some error message")
>>> x.is_ok()
False
is_err() → bool

Returns True if the result is Err().

Basic usage:

>>> x: Result[int, str] = Ok(-3)
>>> x.is_err()
False
>>>
>>> x: Result[int, str] = Err("Some error message")
>>> x.is_err()
True
ok() → patina.option.Option[~T][T]

Converts from Result[T, E] to Option[T].

Converts self into Option[T], discarding the error, if any.

Basic usage:

>>> x: Result[int, str] = Ok(2)
>>> x.ok()
Some(2)
>>>
>>> x: Result[int, str] = Err("Nothing here")
>>> x.ok()
None_
err() → patina.option.Option[~E][E]

Converts from Result[T, E] to Option[E].

Converts self into Option[E], discarding the success value, if any.

Basic usage:

>>> x: Result[int, str] = Ok(2)
>>> x.err()
None_
>>>
>>> x: Result[int, str] = Err("Nothing here")
>>> x.err()
Some('Nothing here')
map(op: Callable[[T], U]) → patina.result.Result[~U, ~E][U, E]

Maps a Result[T, E] to Result[U, E] by applying a function to a contained Ok() value, leaving an Err() value untouched.

This function can be used to compose the results of two functions.

Printing the numbers on each line of a string multiplied by two:

>>> def try_parse(s: str) -> Result[int, ValueError]:
...     try:
...         return Ok(int(s))
...     except ValueError as e:
...         return Err(e)
...
>>> line = "1\n2\n3\n4\n5\n"
>>> for num in line.splitlines():
...     result = try_parse(num).map(lambda i: i * 2)
...     if result.is_ok():
...         print(result.unwrap())
2
4
6
8
10
map_or(default: U, f: Callable[[T], U]) → U

Applies a function to the contained value (if Ok()), or returns the provided default (if Err()).

Arguments passed to map_or are eagerly evaluated; if you are passing the result of a function call, it is recommended to use map_or_else(), which is lazily evaluated.

>>> x: Result[str, str] = Ok("foo")
>>> x.map_or(42, lambda v: len(v))
3
>>>
>>> x: Result[str, str] = Err("bar")
>>> x.map_or(42, lambda v: len(v))
42
map_or_else(default: Callable[[E], U], f: Callable[[T], U]) → U

Maps a Result[T, E] to U by applying a function to a contained Ok() value, or a fallback function to a contained Err() value.

This function can be used to unpack a successful result while handling an error.

Basic usage:

>>> k = 21
>>>
>>> x: Result[str, str] = Ok("foo")
>>> x.map_or_else(lambda e: k * 2, lambda v: len(v))
3
>>>
>>> x: Result[str, str] = Err("foo")
>>> x.map_or_else(lambda e: k * 2, lambda v: len(v))
42
map_err(op: Callable[[E], F]) → patina.result.Result[~T, ~F][T, F]

Maps a Result[T, E] to Result[T, F] by applying a function to a contained Err() value, leaving an Ok() value untouched.

This function can be used to pass through a successful result while handling an error.

Basic usage:

>>> def stringify(x: int) -> str:
...     return f"error code: {x}"
...
>>> x: Result[int, int] = Ok(2)
>>> x.map_err(stringify)
Ok(2)
>>>
>>> x: Result[int, int] = Err(13)
>>> x.map_err(stringify)
Err('error code: 13')
iter() → Iterator[T]

Returns an iterator over the possibly contained value.

The iterator yields one value if the reusult is Ok(), otherwise none.

Basic usage:

>>> x: Result[int, str] = Ok(7)
>>> next(x.iter())
7
>>>
>>> x: Result[int, str] = Err("nothing!")
>>> next(x.iter())
Traceback (most recent call last):
    ...
StopIteration
__iter__() → Iterator[T]

Returns an iterator over the possibly contained value.

The iterator yields one value if the reusult is Ok(), otherwise none.

Basic usage:

>>> x: Result[int, str] = Ok(7)
>>> next(iter(x))
7
>>>
>>> x: Result[int, str] = Err("nothing!")
>>> next(iter(x))
Traceback (most recent call last):
    ...
StopIteration
and_(res: patina.result.Result[~U, ~E][U, E]) → patina.result.Result[~U, ~E][U, E]

Returns res if the result is Ok(), otherwise returns the Err() value of self.

Basic usage:

>>> x: Result[int, str] = Ok(2)
>>> y: Result[str, str] = Err("late error")
>>> x.and_(y)
Err('late error')
>>>
>>> x: Result[int, str] = Err("early error")
>>> y: Result[str, str] = Ok("foo")
>>> x.and_(y)
Err('early error')
>>>
>>> x: Result[int, str] = Err("not a 2")
>>> y: Result[str, str] = Err("late error")
>>> x.and_(y)
Err('not a 2')
>>>
>>> x: Result[int, str] = Ok(2)
>>> y: Result[str, str] = Ok("different result type")
>>> x.and_(y)
Ok('different result type')
and_then(op: Callable[[T], Result[U, E]]) → patina.result.Result[~U, ~E][U, E]

Calls op if the result is Ok(), otherwise returns the Err() value of self.

This function can be used for control flow based on Result values.

Basic usage:

>>> def sq(x: int) -> Result[int, int]: return Ok(x * x)
...
>>> def err(x: int) -> Result[int, int]: return Err(x)
...
>>> Ok[int, int](2).and_then(sq).and_then(sq)
Ok(16)
>>> Ok[int, int](2).and_then(sq).and_then(err)
Err(4)
>>> Ok[int, int](2).and_then(err).and_then(sq)
Err(2)
>>> Err[int, int](3).and_then(sq).and_then(sq)
Err(3)
or_(res: patina.result.Result[~T, ~F][T, F]) → patina.result.Result[~T, ~F][T, F]

Returns res if the result is Err(), otherwise returns the Ok() result of self.

Arguments passed to or are eagerly evaluated; if you are passing the result of a function call, it is recommended to use or_else(), which is lazily evaluated.

Basic usage:

>>> x: Result[int, str] = Ok(2)
>>> y: Result[int, str] = Err("late error")
>>> x.or_(y)
Ok(2)
>>>
>>> x: Result[int, str] = Err("early error")
>>> y: Result[int, str] = Ok(2)
>>> x.or_(y)
Ok(2)
>>>
>>> x: Result[int, str] = Err("not a 2")
>>> y: Result[int, str] = Err("late error")
>>> x.or_(y)
Err('late error')
>>>
>>> x: Result[int, str] = Ok(2)
>>> y: Result[int, str] = Ok(100)
>>> x.or_(y)
Ok(2)
or_else(op: Callable[[E], Result[T, F]]) → patina.result.Result[~T, ~F][T, F]

Calls op if the result is Err(), otherwise returns returns the Ok() value from self.

This function can be used for control flow based on result values.

Basic usage:

>>> def sq(x: int) -> Result[int, int]: return Ok(x * x)
...
>>> def err(x: int) -> Result[int, int]: return Err(x)
...
>>> Ok[int, int](2).or_else(sq).or_else(sq)
Ok(2)
>>> Ok[int, int](2).or_else(err).or_else(sq)
Ok(2)
>>> Err[int, int](3).or_else(sq).or_else(err)
Ok(9)
>>> Err[int, int](3).or_else(err).or_else(err)
Err(3)
unwrap_or(default: T) → T

Returns the contained Ok() value or a provided default.

Arguments passed to unwrap_or are eagerly evaluated; if you are passing the result of a function call, it is recommended to use unwrap_or_else(), which is lazily evaluated.

Basic usage:

>>> default = 2
>>> x: Result[int, str] = Ok(9)
>>> x.unwrap_or(default)
9
>>>
>>> x: Result[int, str] = Err("error")
>>> x.unwrap_or(default)
2
unwrap_or_else(op: Callable[[E], T]) → T

Returns the contained Ok() value or computes it from a closure.

Basic usage:

>>> def count(x: str) -> int: return len(x)
...
>>> Ok[int, str](2).unwrap_or_else(count)
2
>>> Err[int, str]("foo").unwrap_or_else(count)
3
expect(msg: str) → T

Returns the contained Ok() value.

Raises:AssertionError – Raised if the value is an Err(), with a message including the passed message and the content of the Err.

Basic usage:

>>> x: Result[int, str] = Err("emergency failure")
>>> x.expect("Testing expect")
Traceback (most recent call last):
    ...
AssertionError: Testing expect: 'emergency failure'
unwrap() → T

Returns the contained Ok() value, consuming the self value.

Because this function may panic, its use is generally discouraged. Instead, prefer to use pattern matching and handle the Err case explicitly, or call unwrap_or() or unwrap_or_else().

Raises:AssertionError – Raised if the value is an Err(), with a message provided by the Err’s value.

Basic usage:

>>> x: Result[int, str] = Ok(2)
>>> x.unwrap()
2
>>>
>>> x: Result[int, str] = Err("emergency failure")
>>> x.unwrap()
Traceback (most recent call last):
    ...
AssertionError: emergency failure
expect_err(msg: str) → E

Returns the contained Err() value.

Raises:AssertionError – Raised if the value is an Ok(), with a message including the passed message and the content of the Ok.

Basic usage:

>>> x: Result[int, str] = Ok(10)
>>> x.expect_err("Testing expect_err")
Traceback (most recent call last):
    ...
AssertionError: Testing expect_err: 10
unwrap_err() → E

Returns the contained Err() value.

Raises:AssertionError – Raised if the value is an Ok(), with a custom message provided by the Ok’s value.
>>> x: Result[int, str] = Ok(2)
>>> x.unwrap_err()
Traceback (most recent call last):
    ...
AssertionError: 2
>>>
>>> x: Result[int, str] = Err("emergency failure")
>>> x.unwrap_err()
'emergency failure'
__weakref__

list of weak references to the object (if defined)