Coverage for src / ezpl / handlers / wizard / panels.py: 62.92%

81 statements  

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

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

2# EZPL - Wizard Panels Mixin 

3# Project: ezpl 

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

5 

6""" 

7Panel methods mixin for Rich Wizard. 

8 

9This module provides all panel-related methods for the RichWizard class. 

10""" 

11 

12from __future__ import annotations 

13 

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

15# IMPORTS 

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

17# Standard library imports 

18from typing import Any 

19 

20# Third-party imports 

21from rich.align import Align 

22from rich.console import Console 

23from rich.panel import Panel 

24from rich.text import Text 

25 

26# Local imports 

27from ...utils import safe_str_convert 

28 

29# /////////////////////////////////////////////////////////////// 

30# CLASSES 

31# /////////////////////////////////////////////////////////////// 

32 

33 

34class PanelMixin: 

35 """ 

36 Mixin providing panel display methods for RichWizard. 

37 

38 This mixin adds all panel-related functionality including 

39 generic panels, info panels, success panels, error panels, 

40 warning panels, and installation panels. 

41 """ 

42 

43 # Type hints for attributes provided by RichWizard 

44 _console: Console 

45 

46 # /////////////////////////////////////////////////////////////// 

47 # PANEL METHODS 

48 # /////////////////////////////////////////////////////////////// 

49 

50 def panel( 

51 self, 

52 content: Any, 

53 title: str | None = None, 

54 border_style: str = "blue", 

55 width: int | None = None, 

56 **kwargs, 

57 ) -> None: 

58 """ 

59 Display a Rich panel with the given content. 

60 

61 Args: 

62 content: Panel content (any type, will be converted to string) 

63 title: Optional panel title 

64 border_style: Panel border style (Rich style string) 

65 width: Optional panel width 

66 **kwargs: Additional Panel arguments 

67 """ 

68 try: 

69 if not isinstance(content, str): 

70 content = safe_str_convert(content) 

71 

72 panel = Panel( 

73 content, title=title, border_style=border_style, width=width, **kwargs 

74 ) 

75 self._console.print(panel) 

76 except Exception as e: 

77 try: 

78 self._console.print(f"[red]Panel error:[/red] {type(e).__name__}") 

79 except Exception as e: 

80 raise ValueError(f"Failed to display panel: {e}") from e 

81 

82 def info_panel( 

83 self, 

84 title: str, 

85 content: str, 

86 style: str = "cyan", 

87 border_style: str = "cyan", 

88 width: int | None = None, 

89 **kwargs, 

90 ) -> None: 

91 """ 

92 Display an info panel with title and content. 

93 

94 Args: 

95 title: Panel title 

96 content: Panel content 

97 style: Content text style 

98 border_style: Panel border style 

99 width: Optional panel width 

100 **kwargs: Additional Panel arguments 

101 """ 

102 try: 

103 text = Text(content, style=style) 

104 panel = Panel( 

105 Align(text, align="left"), 

106 title=f"ℹ️ {title}", 

107 border_style=border_style, 

108 width=width, 

109 **kwargs, 

110 ) 

111 self._console.print(panel) 

112 except Exception as e: 

113 try: 

114 self._console.print(f"[red]Info panel error:[/red] {type(e).__name__}") 

115 except Exception as e: 

116 raise ValueError(f"Failed to display info panel: {e}") from e 

117 

118 def success_panel( 

119 self, 

120 title: str, 

121 content: str, 

122 border_style: str = "green", 

123 width: int | None = None, 

124 **kwargs, 

125 ) -> None: 

126 """ 

127 Display a success panel with green styling. 

128 

129 Args: 

130 title: Panel title 

131 content: Panel content 

132 border_style: Panel border style 

133 width: Optional panel width 

134 **kwargs: Additional Panel arguments 

135 """ 

136 try: 

137 text = Text(content, style="green") 

138 panel = Panel( 

139 Align(text, align="left"), 

140 title=f"✅ {title}", 

141 border_style=border_style, 

142 width=width, 

143 **kwargs, 

144 ) 

145 self._console.print(panel) 

146 except Exception as e: 

147 try: 

148 self._console.print( 

149 f"[red]Success panel error:[/red] {type(e).__name__}" 

150 ) 

151 except Exception as e: 

152 raise ValueError(f"Failed to display success panel: {e}") from e 

153 

154 def error_panel( 

155 self, 

156 title: str, 

157 content: str, 

158 border_style: str = "red", 

159 width: int | None = None, 

160 **kwargs, 

161 ) -> None: 

162 """ 

163 Display an error panel with red styling. 

164 

165 Args: 

166 title: Panel title 

167 content: Panel content 

168 border_style: Panel border style 

169 width: Optional panel width 

170 **kwargs: Additional Panel arguments 

171 """ 

172 try: 

173 text = Text(content, style="red") 

174 panel = Panel( 

175 Align(text, align="left"), 

176 title=f"❌ {title}", 

177 border_style=border_style, 

178 width=width, 

179 **kwargs, 

180 ) 

181 self._console.print(panel) 

182 except Exception as e: 

183 try: 

184 self._console.print(f"[red]Error panel error:[/red] {type(e).__name__}") 

185 except Exception as e: 

186 raise ValueError(f"Failed to display error panel: {e}") from e 

187 

188 def warning_panel( 

189 self, 

190 title: str, 

191 content: str, 

192 border_style: str = "yellow", 

193 width: int | None = None, 

194 **kwargs, 

195 ) -> None: 

196 """ 

197 Display a warning panel with yellow styling. 

198 

199 Args: 

200 title: Panel title 

201 content: Panel content 

202 border_style: Panel border style 

203 width: Optional panel width 

204 **kwargs: Additional Panel arguments 

205 """ 

206 try: 

207 text = Text(content, style="yellow") 

208 panel = Panel( 

209 Align(text, align="left"), 

210 title=f"⚠️ {title}", 

211 border_style=border_style, 

212 width=width, 

213 **kwargs, 

214 ) 

215 self._console.print(panel) 

216 except Exception as e: 

217 try: 

218 self._console.print( 

219 f"[red]Warning panel error:[/red] {type(e).__name__}" 

220 ) 

221 except Exception as e: 

222 raise ValueError(f"Failed to display warning panel: {e}") from e 

223 

224 def installation_panel( 

225 self, 

226 step: str, 

227 description: str, 

228 status: str = "pending", 

229 border_style: str = "blue", 

230 width: int | None = None, 

231 **kwargs, 

232 ) -> None: 

233 """ 

234 Display an installation step panel. 

235 

236 Args: 

237 step: Installation step name 

238 description: Step description 

239 status: Status ("success", "error", "warning", "pending") 

240 border_style: Panel border style 

241 width: Optional panel width 

242 **kwargs: Additional Panel arguments 

243 """ 

244 try: 

245 if status == "success": 

246 icon = "✅" 

247 style = "green" 

248 elif status == "error": 

249 icon = "❌" 

250 style = "red" 

251 elif status == "warning": 251 ↛ 252line 251 didn't jump to line 252 because the condition on line 251 was never true

252 icon = "⚠️" 

253 style = "yellow" 

254 else: 

255 icon = "⏳" 

256 style = "blue" 

257 

258 text = Text(description, style=style) 

259 panel = Panel( 

260 Align(text, align="left"), 

261 title=f"{icon} {step}", 

262 border_style=border_style, 

263 width=width, 

264 **kwargs, 

265 ) 

266 self._console.print(panel) 

267 except Exception as e: 

268 try: 

269 self._console.print( 

270 f"[red]Installation panel error:[/red] {type(e).__name__}" 

271 ) 

272 except Exception as e: 

273 raise ValueError(f"Failed to display installation panel: {e}") from e