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
« 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"""
27import datetime
29import colander
31from wuttaweb.views import MasterView
32from wuttaweb.forms.schema import EmailRecipients, WuttaDateTime
33from wuttaweb.forms.widgets import EmailSettingRefWidget, WuttaDateTimeWidget
36class ProblemCheckView(MasterView): # pylint: disable=abstract-method
37 """
38 Master view for :term:`problem checks <problem check>`
39 """
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
56 labels = {
57 "lastrun": "Last Run",
58 }
60 grid_columns = [
61 "system_key",
62 "problem_key",
63 "title",
64 "email_recipients",
65 "enabled",
66 "lastrun",
67 ]
69 form_fields = [
70 "system_key",
71 "problem_key",
72 "title",
73 "description",
74 "email_key",
75 "email_recipients",
76 "enabled",
77 "lastrun",
78 ]
80 def __init__(self, request, context=None):
81 super().__init__(request, context=context)
82 self.problem_handler = self.app.get_problem_handler()
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}"
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))
96 if lastrun := self.app.get_setting(
97 session, f"{self.config.appname}.problems.{key}.lastrun"
98 ):
99 lastrun = datetime.datetime.fromisoformat(lastrun)
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 }
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
124 def configure_grid(self, grid): # pylint: disable=empty-docstring
125 """ """
126 g = grid
127 super().configure_grid(g)
129 # problem_key
130 g.set_link("problem_key")
132 # title
133 g.set_link("title")
135 # enabled
136 g.set_renderer("enabled", "boolean")
138 # lastrun
139 g.set_renderer("lastrun", "datetime")
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)
150 raise self.notfound()
152 def get_instance_title(self, instance): # pylint: disable=empty-docstring
153 """ """
154 check = instance
155 return check["title"]
157 def configure_form(self, form): # pylint: disable=empty-docstring
158 """ """
159 f = form
160 super().configure_form(f)
162 # title
163 f.set_readonly("title")
165 # description
166 f.set_widget("description", "notes")
167 f.set_readonly("description")
169 # email_key
170 f.set_widget("email_key", EmailSettingRefWidget(self.request))
171 f.set_readonly("email_key")
173 # email_recipients
174 f.set_node("email_recipients", EmailRecipients())
175 f.set_readonly("email_recipients")
177 # enabled
178 f.set_node("enabled", colander.Boolean())
180 # lastrun
181 f.set_node("lastrun", WuttaDateTime())
182 f.set_widget("lastrun", WuttaDateTimeWidget(self.request))
183 f.set_readonly("lastrun")
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 = []
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 )
202 return buttons
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 )
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`.
221 Returns a success message indicating number of problems found
222 by the check.
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"
233def defaults(config, **kwargs): # pylint: disable=missing-function-docstring
234 base = globals()
236 ProblemCheckView = kwargs.get( # pylint: disable=invalid-name,redefined-outer-name
237 "ProblemCheckView", base["ProblemCheckView"]
238 )
239 ProblemCheckView.defaults(config)
242def includeme(config): # pylint: disable=missing-function-docstring
243 defaults(config)