Coverage for utils/custom_exception.py: 94.12%

51 statements  

« prev     ^ index     » next       coverage.py v7.15.2, created at 2026-09-03 15:30 +0000

1import logging 

2from typing import Any 

3 

4logger = logging.getLogger("exception") 

5 

6 

7class BaseServiceException(Exception): 

8 def __init__( 

9 self, 

10 message: str, 

11 error_code: str = None, 

12 details: dict[str, Any] | None = None, 

13 status_code: int = None, 

14 log_level: str = None, 

15 ): 

16 self.message = message 

17 self.error_code = error_code 

18 self.details = details or {} 

19 self.log_level = log_level 

20 if status_code is not None: 

21 self.status_code = status_code 

22 

23 if self.log_level == "error": 

24 logger.error(self.message) 

25 elif self.log_level == "warning": 

26 logger.warning(self.message) 

27 elif self.log_level == "info": 

28 logger.info(self.message) 

29 

30 super().__init__(self.message) 

31 

32 

33class ServerException(BaseServiceException): 

34 """Server exception""" 

35 

36 def __init__( 

37 self, message: str = "Server error", status_code: int = 500, details: dict[str, Any] = None 

38 ): 

39 super().__init__( 

40 message=message, 

41 error_code="SERVER_ERROR", 

42 details=details, 

43 status_code=status_code, 

44 log_level="error", 

45 ) 

46 

47 

48class AuthenticationException(BaseServiceException): 

49 """Authentication related exceptions""" 

50 

51 def __init__(self, message: str = "Authentication failed", details: dict[str, Any] = None): 

52 super().__init__(message=message, error_code="AUTH_ERROR", details=details, status_code=401) 

53 

54 

55class PasswordResetRequiredException(BaseServiceException): 

56 """Password reset required exception""" 

57 

58 def __init__(self, message: str = "Password reset required", details: dict[str, Any] = None): 

59 super().__init__( 

60 message=message, error_code="PASSWORD_RESET_REQUIRED", details=details, status_code=202 

61 ) 

62 

63 

64class EmailVerificationRequiredException(BaseServiceException): 

65 """Email verification required exception""" 

66 

67 def __init__( 

68 self, message: str = "Email verification required", details: dict[str, Any] = None 

69 ): 

70 super().__init__( 

71 message=message, 

72 error_code="EMAIL_VERIFICATION_REQUIRED", 

73 details=details, 

74 status_code=202, 

75 ) 

76 

77 

78class AuthorizationException(BaseServiceException): 

79 """Authorization related exceptions""" 

80 

81 def __init__(self, message: str = "Permission denied", details: dict[str, Any] = None): 

82 super().__init__( 

83 message=message, error_code="PERMISSION_ERROR", details=details, status_code=403 

84 ) 

85 

86 

87class ValidationException(BaseServiceException): 

88 """Validation related exceptions""" 

89 

90 def __init__(self, message: str = "Validation failed", details: dict[str, Any] = None): 

91 super().__init__( 

92 message=message, error_code="VALIDATION_ERROR", details=details, status_code=400 

93 ) 

94 

95 

96class NotFoundException(BaseServiceException): 

97 """Resource not found exceptions""" 

98 

99 def __init__(self, message: str = "Resource not found", details: dict[str, Any] = None): 

100 super().__init__(message=message, error_code="NOT_FOUND", details=details, status_code=404) 

101 

102 

103class ConflictException(BaseServiceException): 

104 """Resource conflict exceptions""" 

105 

106 def __init__(self, message: str = "Resource conflict", details: dict[str, Any] = None): 

107 super().__init__(message=message, error_code="CONFLICT", details=details, status_code=409) 

108 

109 

110class TokenException(BaseServiceException): 

111 """Token related exceptions""" 

112 

113 def __init__(self, message: str = "Token error", details: dict[str, Any] = None): 

114 super().__init__( 

115 message=message, error_code="TOKEN_ERROR", details=details, status_code=401 

116 ) 

117 

118 

119class SMTPNotConfiguredException(BaseServiceException): 

120 """SMTP configuration related exceptions""" 

121 

122 def __init__(self, message: str = "SMTP is not configured", details: dict[str, Any] = None): 

123 super().__init__( 

124 message=message, error_code="SMTP_NOT_CONFIGURED", details=details, status_code=503 

125 ) 

126 

127 

128class RegistrationDisabledException(BaseServiceException): 

129 """Registration disabled exception""" 

130 

131 def __init__(self, message: str = "Registration is disabled", details: dict[str, Any] = None): 

132 super().__init__( 

133 message=message, error_code="REGISTRATION_DISABLED", details=details, status_code=503 

134 )