Coverage for src / pyfplib / result.py: 40%
86 statements
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-04 23:48 +0300
« prev ^ index » next coverage.py v7.13.2, created at 2026-02-04 23:48 +0300
1""" """
3__author__ = "Comet11x <>"
4__copyright__ = "Copyright 2026, Comet11x"
5__license__ = "MIT"
6__version__ = "0.1.0"
8from typing import Callable, Generic, Optional, TypeVar, Union, cast
10from pyfplib.errors import ExpectedError, UnwrapError
11from pyfplib.option import Nothing, Option, Some
13T = TypeVar("T")
14E = TypeVar("E")
15R = TypeVar("R")
16U = TypeVar("U")
19class Result(Generic[T, E]):
20 __match_args__ = ("value",)
22 def __init__(self, *, value: Optional[T] = None, error: Optional[E] = None):
23 if error is None: 23 ↛ 27line 23 didn't jump to line 27 because the condition on line 23 was always true
24 self.__value = value
25 self.__is_ok = True
26 else:
27 self.__value = error
28 self.__is_ok = False
30 @property
31 def value(self) -> Union[T, E]:
32 """Returns a raw value."""
33 return self.__value
35 def is_ok(self) -> bool:
36 """Returns True if the option is Ok[T]."""
37 return self.__is_ok
39 def is_err(self) -> bool:
40 """Returns True if the option is Err[T]."""
41 return not self.__is_ok
43 def if_ok(self, fn: Callable[[T], None]) -> "Result[T, E]":
44 """\
45 Calls fn function and returns itself.
46 The fn function will be called if this option is Ok[T].
47 """
48 if self.is_ok():
49 fn(self.__value)
50 return self
52 def if_err(self, fn: Callable[[E], None]) -> "Result[T, E]":
53 """\
54 Calls fn function and returns itself.
55 The fn function will be called if this option is Err[E].
56 """
57 if self.is_err():
58 fn(self.__value)
59 return self
61 def ok(self) -> Option[T]:
62 """\
63 Returns Some[T] if this option is Ok[T],
64 otherwise it returns Nothing[T].
65 """
66 return Some(self.__value) if self.is_ok() else Nothing()
68 def err(self) -> Option[E]:
69 """\
70 Returns Some[Exception] if this option is Err[E],
71 otherwise it returns Nothing[Exception].
72 """
73 option: Option[Exception]
74 if self.is_err():
75 option = Some[Exception](cast(Exception, self.__value))
76 else:
77 option = Nothing[Exception]()
78 return option
80 def unwrap(self) -> T:
81 """
82 Extracts the contained value, raising UnwrapError if Err.
84 Raises:
85 UnwrapError: When attempting to unwrap Err
86 """
87 if self.is_err():
88 msg = "called `Result.unwrap()` on a `Err` value"
89 raise UnwrapError(msg)
90 return self.__value
92 def unwrap_err(self) -> E:
93 """
94 Extracts the contained error, raising UnwrapError if Ok.
96 Raises:
97 UnwrapError: When attempting to unwrap Ok
98 """
99 if self.is_ok():
100 msg = "called `Result.unwrap_err()` on a `Ok` value"
101 raise UnwrapError(msg)
102 return self.__value
104 def expect(self, message: str) -> T:
105 """Returns contained value or raises ExpectedError"""
106 if self.is_err():
107 raise ExpectedError(message)
108 return self.__value
110 def expect_err(self, message: str) -> E:
111 """Returns contained value or raises ExpectedError"""
112 if self.is_ok():
113 raise ExpectedError(message)
114 return self.__value
116 def unwrap_or(self, value: T) -> T:
117 """Returns contained value or provided default if Err."""
118 return self.__value if self.is_ok() is None else value
120 def unwrap_err_or(self, value: E) -> E:
121 """Returns contained value or provided default if Ok."""
122 return self.__value if self.is_err() is None else value
124 def map(self, fn: Callable[[T], U]) -> "Result[U, E]":
125 """Maps an Result[T, E] to Result[U, E]"""
126 result: Result[U, E]
127 if self.is_ok():
128 result = Ok[U, E](fn(cast(T, self.__value)))
129 else:
130 result = Err[U, E](cast(E, self.__value))
131 return result
133 def map_or(self, default: T, fn: Callable[[T], U]) -> "Result[U]":
134 """Maps an Result[T] to Result[U]"""
135 result: Result[U]
136 if self.is_ok():
137 result = fn(self.__value)
138 else:
139 result = fn(default)
140 return result
142 @staticmethod
143 def try_call(fn: Callable[..., R], *args, **kwargs) -> "Result[R, E]":
144 """Tries to call fn function and returns a result of the execution."""
145 try:
146 ret: R = fn(*args, **kwargs)
147 return Ok[R, E](ret)
148 except Exception as err:
149 return Err[R, E](err)
152class Ok(Result[T, E]):
153 """Result constructor."""
155 def __init__(self, value: T):
156 super().__init__(value=value)
159class Err(Result[T, E]):
160 """Result constructor."""
162 def __init__(self, error: E):
163 super().__init__(error=error)