Coverage for .tox/coverage/lib/python3.13/site-packages/wuttaweb/views/problems.py: 100%

93 statements  

« prev     ^ index     » next       coverage.py v7.17.0, created at 2026-10-24 16:36 -0500

1# -*- coding: utf-8; -*- 

2################################################################################ 

3# 

4# wuttaweb -- Web App for Wutta Framework 

5# Copyright © 2024-2026 Lance Edgar 

6# 

7# This file is part of Wutta Framework. 

8# 

9# Wutta Framework is free software: you can redistribute it and/or modify it 

10# under the terms of the GNU General Public License as published by the Free 

11# Software Foundation, either version 3 of the License, or (at your option) any 

12# later version. 

13# 

14# Wutta Framework is distributed in the hope that it will be useful, but 

15# WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 

16# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 

17# more details. 

18# 

19# You should have received a copy of the GNU General Public License along with 

20# Wutta Framework. If not, see <http://www.gnu.org/licenses/>. 

21# 

22################################################################################ 

23""" 

24Views for Problem Checks 

25""" 

26 

27import datetime 

28 

29import colander 

30 

31from wuttaweb.views import MasterView 

32from wuttaweb.forms.schema import EmailRecipients, WuttaDateTime 

33from wuttaweb.forms.widgets import EmailSettingRefWidget, WuttaDateTimeWidget 

34 

35 

36class ProblemCheckView(MasterView): # pylint: disable=abstract-method 

37 """ 

38 Master view for :term:`problem checks <problem check>` 

39 """ 

40 

41 model_name = "problem_check" 

42 model_key = ("system_key", "problem_key") 

43 model_title = "Problem Check" 

44 route_prefix = "problem_checks" 

45 url_prefix = "/problem-checks" 

46 # pylint: disable=duplicate-code 

47 filterable = False 

48 sortable = True 

49 sort_on_backend = False 

50 paginated = False 

51 creatable = False 

52 deletable = False 

53 # pylint: enable=duplicate-code 

54 executable = True 

55 

56 labels = { 

57 "lastrun": "Last Run", 

58 } 

59 

60 grid_columns = [ 

61 "system_key", 

62 "problem_key", 

63 "title", 

64 "email_recipients", 

65 "enabled", 

66 "lastrun", 

67 ] 

68 

69 form_fields = [ 

70 "system_key", 

71 "problem_key", 

72 "title", 

73 "description", 

74 "email_key", 

75 "email_recipients", 

76 "enabled", 

77 "lastrun", 

78 ] 

79 

80 def __init__(self, request, context=None): 

81 super().__init__(request, context=context) 

82 self.problem_handler = self.app.get_problem_handler() 

83 

84 def normalize_problem_check(self, check): # pylint: disable=empty-docstring 

85 """ """ 

86 email_handler = self.app.get_email_handler() 

87 session = self.Session() 

88 key = f"{check.system_key}.{check.problem_key}" 

89 

90 email_key = self.problem_handler.get_email_key(check) 

91 email_to = email_handler.get_auto_to(email_key) 

92 email_cc = email_handler.get_auto_cc(email_key) 

93 email_bcc = email_handler.get_auto_bcc(email_key) 

94 email_recips = ",".join(set(email_to + email_cc + email_bcc)) 

95 

96 if lastrun := self.app.get_setting( 

97 session, f"{self.config.appname}.problems.{key}.lastrun" 

98 ): 

99 lastrun = datetime.datetime.fromisoformat(lastrun) 

100 

101 return { 

102 "_check": check, 

103 "system_key": check.system_key, 

104 "problem_key": check.problem_key, 

105 "title": check.title, 

106 "description": (check.__doc__ or "").strip(), 

107 "email_key": email_key, 

108 "email_recipients": email_recips, 

109 "enabled": self.problem_handler.is_enabled(check), 

110 "lastrun": lastrun, 

111 } 

112 

113 def get_grid_data(self, columns=None, session=None): 

114 """ 

115 This calls 

116 :meth:`~wuttjamaican:wuttjamaican.problems.ProblemHandler.get_all_problem_checks()` 

117 on the :term:`problem handler` to obtain the grid data. 

118 """ 

119 data = [] 

120 for check in self.problem_handler.get_all_problem_checks(): 

121 data.append(self.normalize_problem_check(check)) 

122 return data 

123 

124 def configure_grid(self, grid): # pylint: disable=empty-docstring 

125 """ """ 

126 g = grid 

127 super().configure_grid(g) 

128 

129 # problem_key 

130 g.set_link("problem_key") 

131 

132 # title 

133 g.set_link("title") 

134 

135 # enabled 

136 g.set_renderer("enabled", "boolean") 

137 

138 # lastrun 

139 g.set_renderer("lastrun", "datetime") 

140 

141 def get_instance( 

142 self, **kwargs 

143 ): # pylint: disable=empty-docstring,arguments-differ,unused-argument 

144 """ """ 

145 if check := self.problem_handler.get_problem_check( 

146 self.request.matchdict["system_key"], self.request.matchdict["problem_key"] 

147 ): 

148 return self.normalize_problem_check(check) 

149 

150 raise self.notfound() 

151 

152 def get_instance_title(self, instance): # pylint: disable=empty-docstring 

153 """ """ 

154 check = instance 

155 return check["title"] 

156 

157 def configure_form(self, form): # pylint: disable=empty-docstring 

158 """ """ 

159 f = form 

160 super().configure_form(f) 

161 

162 # title 

163 f.set_readonly("title") 

164 

165 # description 

166 f.set_widget("description", "notes") 

167 f.set_readonly("description") 

168 

169 # email_key 

170 f.set_widget("email_key", EmailSettingRefWidget(self.request)) 

171 f.set_readonly("email_key") 

172 

173 # email_recipients 

174 f.set_node("email_recipients", EmailRecipients()) 

175 f.set_readonly("email_recipients") 

176 

177 # enabled 

178 f.set_node("enabled", colander.Boolean()) 

179 

180 # lastrun 

181 f.set_node("lastrun", WuttaDateTime()) 

182 f.set_widget("lastrun", WuttaDateTimeWidget(self.request)) 

183 f.set_readonly("lastrun") 

184 

185 def get_xref_buttons(self, obj): 

186 """ 

187 By default this returns a button to view the related 

188 :term:`email setting`. 

189 """ 

190 check = obj 

191 buttons = [] 

192 

193 handler = self.app.get_problem_handler() 

194 key = handler.get_email_key(check["_check"]) 

195 url = self.request.route_url("email_settings.view", key=key) 

196 buttons.append( 

197 self.make_button( 

198 "Email Setting", primary=True, url=url, icon_left="envelope" 

199 ) 

200 ) 

201 

202 return buttons 

203 

204 def persist(self, obj, session=None): # pylint: disable=empty-docstring 

205 """ """ 

206 check = obj 

207 session = session or self.Session() 

208 key = f"{check['system_key']}.{check['problem_key']}" 

209 self.app.save_setting( 

210 session, 

211 f"{self.config.appname}.problems.{key}.enabled", 

212 "true" if check["enabled"] else "false", 

213 ) 

214 

215 def execute_instance(self, obj, user, progress=None): 

216 """ 

217 This calls 

218 :meth:`~wuttjamaican.problems.ProblemHandler.run_problem_check()` 

219 on the :term:`problem handler`. 

220 

221 Returns a success message indicating number of problems found 

222 by the check. 

223 

224 See also parent method: 

225 :meth:`~wuttaweb.views.master.MasterView.execute_instance()` 

226 """ 

227 check = obj["_check"] 

228 if problems := self.problem_handler.run_problem_check(check, force=True): 

229 return f"Found {len(problems)} problems" 

230 return "No problems found" 

231 

232 

233def defaults(config, **kwargs): # pylint: disable=missing-function-docstring 

234 base = globals() 

235 

236 ProblemCheckView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name 

237 "ProblemCheckView", base["ProblemCheckView"] 

238 ) 

239 ProblemCheckView.defaults(config) 

240 

241 

242def includeme(config): # pylint: disable=missing-function-docstring 

243 defaults(config)