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

1from typing import Callable, Union, Any, Optional, cast 

2from .result import Result, T, E, U 

3 

4 

5class Ok(Result[T, E]): 

6 """ 

7 Represents a successful computation in a Result monad. 

8 

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 """ 

13 

14 __match_args__ = ("_value",) 

15 

16 def __new__(cls, value: T) -> 'Ok[T, E]': 

17 """Create a new Ok instance directly, bypassing Result.__new__.""" 

18 return object.__new__(cls) 

19 

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 

25 

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 

32 

33 def is_ok(self) -> bool: 

34 return True 

35 

36 def is_err(self) -> bool: 

37 return False 

38 

39 def __bool__(self) -> bool: 

40 """Ok is truthy (following Rust conventions).""" 

41 return True 

42 

43 def ok(self) -> Any: # Returns Some(value) 

44 from ..option import Some 

45 return Some(self._value) 

46 

47 def err(self) -> Any: # Returns Nil() 

48 from ..option import Nil 

49 return Nil() 

50 

51 def unwrap(self) -> T: 

52 return self._value # type: ignore[no-any-return] 

53 

54 def unwrap_err(self) -> E: 

55 raise ValueError("Called unwrap_err() on an Ok value") 

56 

57 def unwrap_or(self, default: T) -> T: 

58 return self._value # type: ignore[no-any-return] 

59 

60 def unwrap_or_else(self, func: Callable[[E], T]) -> T: 

61 return self._value # type: ignore[no-any-return] 

62 

63 def map(self, func: Callable[[T], U]) -> Result[U, E]: 

64 result = func(self._value) 

65 return Ok(result) 

66 

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) 

70 

71 def and_then(self, func: Callable[[T], Result[U, E]]) -> Result[U, E]: 

72 return func(self._value) 

73 

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) 

77 

78 def map_or(self, default: U, func: Callable[[T], U]) -> U: 

79 # Apply func to Ok value 

80 return func(self._value) 

81 

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) 

85 

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] 

92 

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) 

104 

105 def and_(self, other: Result[U, E]) -> Result[U, E]: 

106 return other 

107 

108 def or_(self, other: Result[T, U]) -> Result[T, U]: 

109 return cast(Result[T, U], self) 

110 

111 def inspect(self, func: Callable[[T], Any]) -> Result[T, E]: 

112 func(self._value) 

113 return self 

114 

115 def inspect_err(self, func: Callable[[E], Any]) -> Result[T, E]: 

116 # Ok has no error to inspect 

117 return self 

118 

119 def to_option(self) -> Any: # Returns Option[T] 

120 from ..option import Option 

121 return Option(self._value) 

122 

123 def to_try(self) -> Any: # Returns Try[T] 

124 from ..try_ import Success 

125 return Success(self._value) 

126 

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 

131 

132 def __repr__(self) -> str: 

133 return f"Ok({self._value!r})" 

134 

135 def __str__(self) -> str: 

136 return self.__repr__()