Coverage for src/monadc/result/ok.py: 100%
79 statements
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-19 20:24 -0700
« prev ^ index » next coverage.py v7.10.2, created at 2025-08-19 20:24 -0700
1from typing import Callable, Union, Any, Optional, cast
2from .result import Result, T, E, U
5class Ok(Result[T, E]):
6 """
7 Represents a successful computation in a Result monad.
9 Ok contains the successful result value, following Rust conventions.
10 Ok is result-biased, meaning transformations (map, and_then) operate on Ok values
11 and pass through Err values unchanged.
12 """
14 __match_args__ = ("_value",)
16 def __new__(cls, value: T) -> 'Ok[T, E]':
17 """Create a new Ok instance directly, bypassing Result.__new__."""
18 return object.__new__(cls)
20 def __init__(self, value: Any = None, **kwargs: Any) -> None:
21 # If _value already exists, this is a second call from Python's object creation process
22 # We should ignore it since the object has already been properly initialized
23 if hasattr(self, '_value'):
24 return
26 # Handle factory construction: Result(ok_value=x) calls Ok.__init__(ok_obj, ok_value=x)
27 if 'ok_value' in kwargs:
28 self._value = kwargs['ok_value']
29 # Handle direct construction: Ok(value)
30 else:
31 self._value = value
33 def is_ok(self) -> bool:
34 return True
36 def is_err(self) -> bool:
37 return False
39 def __bool__(self) -> bool:
40 """Ok is truthy (following Rust conventions)."""
41 return True
43 def ok(self) -> Any: # Returns Some(value)
44 from ..option import Some
45 return Some(self._value)
47 def err(self) -> Any: # Returns Nil()
48 from ..option import Nil
49 return Nil()
51 def unwrap(self) -> T:
52 return self._value # type: ignore[no-any-return]
54 def unwrap_err(self) -> E:
55 raise ValueError("Called unwrap_err() on an Ok value")
57 def unwrap_or(self, default: T) -> T:
58 return self._value # type: ignore[no-any-return]
60 def unwrap_or_else(self, func: Callable[[E], T]) -> T:
61 return self._value # type: ignore[no-any-return]
63 def map(self, func: Callable[[T], U]) -> Result[U, E]:
64 result = func(self._value)
65 return Ok(result)
67 def map_err(self, func: Callable[[E], U]) -> Result[T, U]:
68 # Ok is unchanged by map_err
69 return cast(Result[T, U], self)
71 def and_then(self, func: Callable[[T], Result[U, E]]) -> Result[U, E]:
72 return func(self._value)
74 def or_else(self, func: Callable[[E], Result[T, U]]) -> Result[T, U]:
75 # Ok doesn't need alternative
76 return cast(Result[T, U], self)
78 def map_or(self, default: U, func: Callable[[T], U]) -> U:
79 # Apply func to Ok value
80 return func(self._value)
82 def map_or_else(self, default_func: Callable[[E], U], func: Callable[[T], U]) -> U:
83 # Apply func to Ok value (ignore default_func)
84 return func(self._value)
86 def flatten(self) -> 'Result[Any, E]':
87 # If the Ok value is itself a Result, unwrap it
88 if isinstance(self._value, Result):
89 return self._value # type: ignore[return-value]
90 # Otherwise return self unchanged
91 return self # type: ignore[return-value]
93 def transpose(self) -> 'Any': # Returns Option[Result[T, E]]
94 # If the Ok value is an Option, transpose Result[Option[T], E] to Option[Result[T, E]]
95 from ..option import Option, Some, Nil
96 if hasattr(self._value, 'is_empty') and callable(getattr(self._value, 'is_empty')): # Duck typing for Option
97 if self._value.is_empty():
98 return Nil()
99 else:
100 # Extract value from Some and wrap in Ok
101 return Some(Ok(self._value.unwrap()))
102 # If not an Option, wrap self in Some
103 return Some(self)
105 def and_(self, other: Result[U, E]) -> Result[U, E]:
106 return other
108 def or_(self, other: Result[T, U]) -> Result[T, U]:
109 return cast(Result[T, U], self)
111 def inspect(self, func: Callable[[T], Any]) -> Result[T, E]:
112 func(self._value)
113 return self
115 def inspect_err(self, func: Callable[[E], Any]) -> Result[T, E]:
116 # Ok has no error to inspect
117 return self
119 def to_option(self) -> Any: # Returns Option[T]
120 from ..option import Option
121 return Option(self._value)
123 def to_try(self) -> Any: # Returns Try[T]
124 from ..try_ import Success
125 return Success(self._value)
127 def __eq__(self, other: object) -> bool:
128 if isinstance(other, Ok):
129 return self._value == other._value # type: ignore[no-any-return]
130 return False
132 def __repr__(self) -> str:
133 return f"Ok({self._value!r})"
135 def __str__(self) -> str:
136 return self.__repr__()