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¶ Resultis a type that represents either success (Ok()) or failure (Err()).-
is_ok() → bool¶ Returns
Trueif the result isOk().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
Trueif the result isErr().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]toOption[T].Converts
selfintoOption[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]toOption[E].Converts
selfintoOption[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]toResult[U, E]by applying a function to a containedOk()value, leaving anErr()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 (ifErr()).Arguments passed to
map_orare eagerly evaluated; if you are passing the result of a function call, it is recommended to usemap_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]toUby applying a function to a containedOk()value, or a fallback function to a containedErr()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]toResult[T, F]by applying a function to a containedErr()value, leaving anOk()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
resif the result isOk(), otherwise returns theErr()value ofself.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
opif the result isOk(), otherwise returns theErr()value ofself.This function can be used for control flow based on
Resultvalues.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
resif the result isErr(), otherwise returns theOk()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
opif the result isErr(), otherwise returns returns theOk()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 theErr.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 theselfvalue.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()orunwrap_or_else().Raises: AssertionError – Raised if the value is an Err(), with a message provided by theErr’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 theOk.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 theOk’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)
-