Coverage for src / ezpl / types / enums / log_level.py: 100.00%

56 statements  

« prev     ^ index     » next       coverage.py v7.13.4, created at 2026-03-13 19:35 +0000

1# /////////////////////////////////////////////////////////////// 

2# EZPL - LogLevel enumeration 

3# Project: ezpl 

4# /////////////////////////////////////////////////////////////// 

5 

6""" 

7LogLevel enumeration for Ezpl logging framework. 

8 

9This module defines the logging levels with their associated colors and properties. 

10""" 

11 

12from __future__ import annotations 

13 

14# /////////////////////////////////////////////////////////////// 

15# IMPORTS 

16# /////////////////////////////////////////////////////////////// 

17# Standard library imports 

18from enum import Enum 

19from typing import Any, cast 

20 

21# Local imports 

22from ...core.exceptions import ValidationError 

23 

24# /////////////////////////////////////////////////////////////// 

25# CLASSES 

26# /////////////////////////////////////////////////////////////// 

27 

28 

29class LogLevel(Enum): 

30 """ 

31 LogLevel is an enumeration representing different logging levels with associated names, 

32 numeric levels, and colorimetric configurations. 

33 

34 **Attributes:** 

35 * `label`: Human-readable name of the log level 

36 * `no`: Numeric level for comparison 

37 * `fg`: Foreground color code 

38 * `bg`: Background color code 

39 

40 **Levels:** 

41 * `DEBUG`: Debugging messages (lowest priority) 

42 * `INFO`: Informational messages 

43 * `SUCCESS`: Success messages 

44 * `WARNING`: Warning messages 

45 * `ERROR`: Error messages 

46 * `CRITICAL`: Critical messages (highest priority) 

47 """ 

48 

49 # Numeric levels match loguru standard levels (stable constants, no runtime lookup) 

50 DEBUG = ("DEBUG", 10, "e", "K") # cyan / black 

51 INFO = ("INFO", 20, "w", "K") # white / black 

52 SUCCESS = ("SUCCESS", 25, "w", "G") # white / green 

53 WARNING = ("WARNING", 30, "y", "K") # yellow / black 

54 ERROR = ("ERROR", 40, "r", "K") # red / black 

55 CRITICAL = ("CRITICAL", 50, "w", "M") # white / magenta 

56 

57 # /////////////////////////////////////////////////////////////// 

58 # INIT 

59 # /////////////////////////////////////////////////////////////// 

60 

61 label: str 

62 no: int 

63 fg: str 

64 bg: str 

65 

66 def __init__(self, label: str, no: int, fg: str, bg: str) -> None: 

67 """ 

68 Initialize a LogLevel instance. 

69 

70 Args: 

71 label: Human-readable name of the log level 

72 no: Numeric level for comparison 

73 fg: Foreground color code 

74 bg: Background color code 

75 """ 

76 self.label = label 

77 self.no = no 

78 self.fg = fg 

79 self.bg = bg 

80 

81 # /////////////////////////////////////////////////////////////// 

82 # CLASS METHODS 

83 # /////////////////////////////////////////////////////////////// 

84 

85 @classmethod 

86 def get_attribute(cls, level: str, attribute: str) -> Any: 

87 """ 

88 Returns the specified attribute (label, no, fg, bg) for a given logging level. 

89 

90 Args: 

91 level: The logging level name 

92 attribute: The attribute to retrieve ('label', 'no', 'fg', 'bg') 

93 

94 Returns: 

95 The requested attribute value 

96 

97 Raises: 

98 ValueError: If the level or attribute is not found 

99 """ 

100 try: 

101 lvl = cls[level.upper()] 

102 return getattr(lvl, attribute) 

103 except KeyError as e: 

104 raise ValidationError(f"Unknown level '{level}'", "level", level) from e 

105 except AttributeError as e: 

106 raise ValidationError( 

107 f"Invalid attribute '{attribute}'", "attribute", attribute 

108 ) from e 

109 

110 @classmethod 

111 def get_label(cls, level: str) -> str: 

112 """ 

113 Get the label for a given log level. 

114 

115 Args: 

116 level: The logging level name 

117 

118 Returns: 

119 The label for the log level 

120 """ 

121 return cast(str, cls.get_attribute(level, "label")) 

122 

123 @classmethod 

124 def get_no(cls, level: str) -> int: 

125 """ 

126 Get the numeric level for a given log level. 

127 

128 Args: 

129 level: The logging level name 

130 

131 Returns: 

132 The numeric level 

133 """ 

134 return cast(int, cls.get_attribute(level, "no")) 

135 

136 @classmethod 

137 def get_fgcolor(cls, level: str) -> str: 

138 """ 

139 Get the foreground color for a given log level. 

140 

141 Args: 

142 level: The logging level name 

143 

144 Returns: 

145 The foreground color code 

146 """ 

147 return cast(str, cls.get_attribute(level, "fg")) 

148 

149 @classmethod 

150 def get_bgcolor(cls, level: str) -> str: 

151 """ 

152 Get the background color for a given log level. 

153 

154 Args: 

155 level: The logging level name 

156 

157 Returns: 

158 The background color code 

159 """ 

160 return cast(str, cls.get_attribute(level, "bg")) 

161 

162 @classmethod 

163 def is_valid_level(cls, level: str) -> bool: 

164 """ 

165 Check if a given level is valid. 

166 

167 Args: 

168 level: The logging level name to check 

169 

170 Returns: 

171 True if the level is valid, False otherwise 

172 """ 

173 try: 

174 cls[level.upper()] 

175 return True 

176 except KeyError: 

177 return False 

178 

179 @classmethod 

180 def get_all_levels(cls) -> list[str]: 

181 """ 

182 Get all available log levels. 

183 

184 Returns: 

185 List of all available log level names 

186 """ 

187 return [level.name for level in cls] 

188 

189 # /////////////////////////////////////////////////////////////// 

190 # REPRESENTATION METHODS 

191 # /////////////////////////////////////////////////////////////// 

192 

193 def __str__(self) -> str: 

194 """String representation of the log level.""" 

195 return f"LogLevel.{self.name}({self.label})" 

196 

197 def __repr__(self) -> str: 

198 """Detailed string representation of the log level.""" 

199 return f"LogLevel.{self.name}(label='{self.label}', no={self.no}, fg='{self.fg}', bg='{self.bg}')" 

200 

201 def get_rich_style(self) -> str: 

202 """ 

203 Get the Rich style string for this log level. 

204 

205 Returns: 

206 Rich style string (e.g., "bold red", "cyan", etc.) 

207 """ 

208 styles = { 

209 "DEBUG": "cyan", 

210 "INFO": "blue", 

211 "SUCCESS": "bold green", 

212 "WARNING": "bold yellow", 

213 "ERROR": "bold red", 

214 "CRITICAL": "bold magenta on red", 

215 } 

216 return styles.get(self.name, "")