Coverage for src/monadc/decorators.py: 100%

33 statements  

« prev     ^ index     » next       coverage.py v7.10.2, created at 2025-08-19 20:24 -0700

1""" 

2Decorators for automatic monad wrapping of function returns. 

3""" 

4from functools import wraps 

5from typing import Callable, TypeVar, Any, TYPE_CHECKING 

6from .option import Option 

7 

8if TYPE_CHECKING: 

9 from .try_ import Try 

10 from .result import Result 

11 

12T = TypeVar('T') 

13 

14 

15def option(func: Callable[..., T]) -> Callable[..., 'Option[T]']: 

16 """ 

17 Decorator that wraps function return values in Option. 

18 

19 - Returns Some(result) for non-None values 

20 - Returns Nil() for None values 

21 - Exceptions propagate normally (not caught) 

22 

23 Example: 

24 @option 

25 def find_user(user_id: str) -> User: 

26 return database.get(user_id) # Returns Option[User] 

27 """ 

28 @wraps(func) 

29 def wrapper(*args: Any, **kwargs: Any) -> 'Option[T]': 

30 result = func(*args, **kwargs) 

31 return Option(result) 

32 

33 return wrapper 

34 

35 

36def try_decorator(func: Callable[..., T]) -> Callable[..., 'Try[T]']: 

37 """ 

38 Decorator that wraps function return values in Try monad. 

39 

40 - Returns Success(result) for successful execution 

41 - Returns Failure(exception) if function raises any exception 

42 

43 Example: 

44 @try_decorator 

45 def parse_int(s: str) -> int: 

46 return int(s) # Returns Success(42) or Failure(ValueError) 

47 """ 

48 @wraps(func) 

49 def wrapper(*args: Any, **kwargs: Any) -> 'Try[T]': 

50 try: 

51 result = func(*args, **kwargs) 

52 from .try_ import Success 

53 return Success(result) 

54 except Exception as e: 

55 from .try_ import Failure 

56 return Failure(e) 

57 

58 return wrapper 

59 

60 

61# Alias for more natural usage 

62try_ = try_decorator 

63 

64 

65def result(func: Callable[..., T]) -> Callable[..., 'Result[T, Exception]']: 

66 """ 

67 Decorator that wraps function return values in Result monad. 

68 

69 - Returns Ok(result) for successful execution  

70 - Returns Err(exception) if function raises any exception 

71 

72 Example: 

73 @result 

74 def divide(a: float, b: float) -> float: 

75 return a / b # Returns Ok(2.0) or Err(ZeroDivisionError) 

76 """ 

77 @wraps(func) 

78 def wrapper(*args: Any, **kwargs: Any) -> 'Result[T, Exception]': 

79 try: 

80 result = func(*args, **kwargs) 

81 from .result import Ok 

82 return Ok(result) 

83 except Exception as e: 

84 from .result import Err 

85 return Err(e) 

86 

87 return wrapper