Source code for emlib.result
from __future__ import annotations
from typing import Generic, TypeVar
_T = TypeVar('_T')
__all__ = ('Result',)
[docs]
class Result(Generic[_T]):
r"""
A class to encapsulate the result of an operation
This is useful for operations which can either return a value
or an error message.
Args:
ok: True if ok, False if failed
value: the value returned by the operation
info: an error message if the operation failed
Example
-------
.. code::
from fractions import Fraction
def parsefraction(txt: str) -> Result[Fraction]:
match = re.match(r"([0-9]+)\/([1-9][0-9]*)", txt)
if not match:
return Result.Fail(f"Could not parse '{txt}' as fraction")
num = int(match.group(1))
den = int(match.group(2))
return Result.Ok(Fraction(num, den))
if fraction := parsefraction("4/5"):
print(f"Fraction ok: {fraction.value}) # prints 'Fraction(4, 5)'
Typing
------
To make typing analysis work better it is possible to indicate the kind of
value wrapped by the Result class. See the return type declared in ``parsefraction``
in the example above
"""
def __init__(self, ok: bool, value: _T | None = None, info: str = ''):
self.ok: bool = ok
self._value: _T | None = value
self.info: str = info
@property
def value(self) -> _T:
if not self.ok:
raise ValueError("Cannot access the value of a failed result")
assert self._value is not None
return self._value
def __bool__(self) -> bool:
return self.ok
@property
def failed(self) -> bool:
"""True if operation failed"""
return not self.ok
def __repr__(self):
if self.ok:
return f"Ok(value={self._value})"
else:
if self.info:
return f'Fail(info="{self.info}")'
return 'Fail()'
[docs]
@classmethod
def Fail(cls, info='') -> Result[_T]:
"""Create a Result object for a failed operation."""
if not isinstance(info, str):
raise TypeError(f"The info parameter should be a str, got {info}")
return cls(False, value=None, info=info)
[docs]
@classmethod
def Ok(cls, value: _T | None = None) -> Result[_T]:
"""Create a Result object for a successful operation."""
return cls(True, value=value)
def _test():
r = Result.Ok(42)
assert r.value == 42
assert not r.failed
assert r.ok
r = Result.Fail()