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 Result
s 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 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
True
if 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
self
intoOption[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
self
intoOption[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_or
are 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]
toU
by 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
res
if 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
op
if the result isOk()
, otherwise returns theErr()
value ofself
.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 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
op
if 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 theself
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()
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)
-