Source code for stdlibx.result._result
1from __future__ import annotations
2
3from functools import wraps
4from typing import TYPE_CHECKING, Callable, Generic, Literal, TypeVar
5
6from typing_extensions import ParamSpec, TypeAlias, TypeGuard
7
8if TYPE_CHECKING:
9 from stdlibx.result._types import Operation
10
11T = TypeVar("T")
12E = TypeVar("E")
13U = TypeVar("U")
14P = ParamSpec("P")
15_AnyException = TypeVar("_AnyException", bound=Exception)
16
17Result: TypeAlias = "Ok[T, E] | Error[T, E]"
18
19
[docs]
20def is_ok(result: Result[T, E]) -> TypeGuard[Ok[T, E]]:
21 return result.is_ok()
22
23
[docs]
24def is_err(result: Result[T, E]) -> TypeGuard[Error[T, E]]:
25 return result.is_err()
26
27
[docs]
28def result_of(
29 func: Callable[P, T], *args: P.args, **kwargs: P.kwargs
30) -> Result[T, Exception]:
31 try:
32 return Ok(func(*args, **kwargs))
33 except Exception as e:
34 return Error(e)
35
36
[docs]
37def as_result(
38 func: Callable[P, T], exceptions: tuple[type[_AnyException], ...] = (Exception,)
39) -> Callable[P, Result[T, _AnyException]]:
40 @wraps(func)
41 def _wrapped(*args: P.args, **kwargs: P.kwargs) -> Result[T, _AnyException]:
42 try:
43 return Ok(func(*args, **kwargs))
44 except exceptions as e:
45 return Error(e)
46
47 return _wrapped
48
49
[docs]
50class Ok(Generic[T, E]):
51 __match_args__ = ("value",)
52 __slots__ = ("value",)
53
54 value: T
55
56 def __init__(self, value: T) -> None:
57 self.value = value
58
59 def __repr__(self) -> str:
60 return f"Ok({self.value!r})"
61
62 def __eq__(self, other: object) -> bool:
63 if isinstance(other, Ok):
64 return other.value == self.value
65 return False
66
[docs]
67 def is_ok(self) -> Literal[True]:
68 return True
69
[docs]
70 def is_err(self) -> Literal[False]:
71 return False
72
[docs]
73 def apply(self, operation: Operation[Result[T, E], U]) -> U:
74 return operation(self)
75
76
[docs]
77class Error(Generic[T, E]):
78 __match_args__ = ("error",)
79 __slots__ = ("error",)
80
81 error: E
82
83 def __init__(self, error: E) -> None:
84 self.error = error
85
86 def __repr__(self) -> str:
87 return f"Error({self.error!r})"
88
89 def __eq__(self, other: object) -> bool:
90 if isinstance(other, Error):
91 return other.error == self.error
92 return False
93
[docs]
94 def is_ok(self) -> Literal[False]:
95 return False
96
[docs]
97 def is_err(self) -> Literal[True]:
98 return True
99
[docs]
100 def apply(self, operation: Operation[Result[T, E], U]) -> U:
101 return operation(self)