Merge lp:~cr3/checkbox/warning_prompt into lp:checkbox
- warning_prompt
- Merge into trunk
Proposed by
Marc Tardif
Status: | Merged |
---|---|
Approved by: | Sylvain Pineau |
Approved revision: | 1781 |
Merged at revision: | 1785 |
Proposed branch: | lp:~cr3/checkbox/warning_prompt |
Merge into: | lp:checkbox |
Diff against target: |
395 lines (+168/-85) 3 files modified
checkbox/user_interface.py (+98/-70) plugins/jobs_info.py (+35/-15) plugins/warning_prompt.py (+35/-0) |
To merge this branch: | bzr merge lp:~cr3/checkbox/warning_prompt |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
Sylvain Pineau (community) | Approve | ||
Review via email: mp+130193@code.launchpad.net |
Commit message
Merged warning_prompt plugin for whitelist validation warnings by cr3.
Description of the change
Added warning_prompt plugin to prevent the reactor from stopping on some warnings when run non-interactively.
To post a comment you must log in.
Revision history for this message
Marc Tardif (cr3) wrote : | # |
Thanks, you can now work on having a nice user interface for Qt specifically at your leisure by overriding the show_warning method in the qt interface class.
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'checkbox/user_interface.py' | |||
2 | --- checkbox/user_interface.py 2012-07-23 20:50:14 +0000 | |||
3 | +++ checkbox/user_interface.py 2012-10-17 19:06:24 +0000 | |||
4 | @@ -29,10 +29,20 @@ | |||
5 | 29 | 29 | ||
6 | 30 | from checkbox.contrib.REThread import REThread | 30 | from checkbox.contrib.REThread import REThread |
7 | 31 | 31 | ||
9 | 32 | from checkbox.lib.environ import add_variable, get_variable, remove_variable | 32 | from checkbox.lib.environ import ( |
10 | 33 | add_variable, | ||
11 | 34 | get_variable, | ||
12 | 35 | remove_variable, | ||
13 | 36 | ) | ||
14 | 33 | 37 | ||
17 | 34 | from checkbox.job import (FAIL, PASS, UNINITIATED, | 38 | from checkbox.job import ( |
18 | 35 | UNRESOLVED, UNSUPPORTED, UNTESTED) | 39 | FAIL, |
19 | 40 | PASS, | ||
20 | 41 | UNINITIATED, | ||
21 | 42 | UNRESOLVED, | ||
22 | 43 | UNSUPPORTED, | ||
23 | 44 | UNTESTED, | ||
24 | 45 | ) | ||
25 | 36 | from checkbox.reactor import StopAllException | 46 | from checkbox.reactor import StopAllException |
26 | 37 | 47 | ||
27 | 38 | 48 | ||
28 | @@ -83,13 +93,22 @@ | |||
29 | 83 | logging.info(text) | 93 | logging.info(text) |
30 | 84 | return default | 94 | return default |
31 | 85 | 95 | ||
34 | 86 | def show_error(self, primary_text, | 96 | def show_error( |
35 | 87 | secondary_text=None, detailed_text=None): | 97 | self, primary_text, secondary_text=None, detailed_text=None): |
36 | 88 | text = filter(None, [primary_text, secondary_text, detailed_text]) | 98 | text = filter(None, [primary_text, secondary_text, detailed_text]) |
37 | 89 | text = '\n'.join(text) | 99 | text = '\n'.join(text) |
38 | 90 | logging.error(text) | 100 | logging.error(text) |
39 | 91 | raise StopAllException("Error: %s" % text) | 101 | raise StopAllException("Error: %s" % text) |
40 | 92 | 102 | ||
41 | 103 | def show_warning( | ||
42 | 104 | self, primary_text, secondary_text=None, detailed_text=None): | ||
43 | 105 | try: | ||
44 | 106 | self.show_error(primary_text, secondary_text, detailed_text) | ||
45 | 107 | except StopAllException: | ||
46 | 108 | # The only difference with show_error for now is that warnings | ||
47 | 109 | # don't stop the reactor. | ||
48 | 110 | pass | ||
49 | 111 | |||
50 | 93 | def show_progress(self, message, function, *args, **kwargs): | 112 | def show_progress(self, message, function, *args, **kwargs): |
51 | 94 | self.show_progress_start(message) | 113 | self.show_progress_start(message) |
52 | 95 | 114 | ||
53 | @@ -138,8 +157,8 @@ | |||
54 | 138 | 157 | ||
55 | 139 | Display an error dialog if everything fails.""" | 158 | Display an error dialog if everything fails.""" |
56 | 140 | 159 | ||
59 | 141 | # If we are called through sudo, determine the real user id and run the | 160 | # If we are called through sudo, determine the real user id and |
60 | 142 | # browser with it to get the user's web browser settings. | 161 | # run the browser with it to get the user's web browser settings. |
61 | 143 | try: | 162 | try: |
62 | 144 | uid = int(get_variable("SUDO_UID")) | 163 | uid = int(get_variable("SUDO_UID")) |
63 | 145 | gid = int(get_variable("SUDO_GID")) | 164 | gid = int(get_variable("SUDO_GID")) |
64 | @@ -149,67 +168,78 @@ | |||
65 | 149 | gid = None | 168 | gid = None |
66 | 150 | sudo_prefix = [] | 169 | sudo_prefix = [] |
67 | 151 | 170 | ||
129 | 152 | # figure out appropriate web browser | 171 | # if ksmserver is running, try kfmclient |
130 | 153 | try: | 172 | try: |
131 | 154 | # if ksmserver is running, try kfmclient | 173 | if (os.getenv("DISPLAY") and |
132 | 155 | try: | 174 | subprocess.call( |
133 | 156 | if os.getenv("DISPLAY") and \ | 175 | ["pgrep", "-x", "-u", str(uid), "ksmserver"], |
134 | 157 | subprocess.call(["pgrep", "-x", "-u", str(uid), "ksmserver"], | 176 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0): |
135 | 158 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: | 177 | subprocess.Popen(sudo_prefix + ["kfmclient", "openURL", url]) |
136 | 159 | subprocess.Popen(sudo_prefix + ["kfmclient", "openURL", url]) | 178 | return |
137 | 160 | return | 179 | except OSError: |
138 | 161 | except OSError: | 180 | pass |
139 | 162 | pass | 181 | |
140 | 163 | 182 | # if gnome-session is running, try gnome-open; special-case | |
141 | 164 | # if gnome-session is running, try gnome-open; special-case firefox | 183 | # firefox (and more generally, mozilla browsers) and epiphany |
142 | 165 | # (and more generally, mozilla browsers) and epiphany to open a new window | 184 | # to open a new window with respectively -new-window and |
143 | 166 | # with respectively -new-window and --new-window; special-case chromium-browser | 185 | # --new-window; special-case chromium-browser to allow file:// |
144 | 167 | # to allow file:// URLs as needed by the checkbox report. | 186 | # URLs as needed by the checkbox report. |
145 | 168 | try: | 187 | try: |
146 | 169 | if os.getenv("DISPLAY") and \ | 188 | if (os.getenv("DISPLAY") and |
147 | 170 | subprocess.call(["pgrep", "-x", "-u", str(uid), "gnome-panel|gconfd-2"], | 189 | subprocess.call( |
148 | 171 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0: | 190 | ["pgrep", "-x", "-u", str(uid), "gnome-panel|gconfd-2"], |
149 | 172 | from gi.repository import Gio | 191 | stdout=subprocess.PIPE, stderr=subprocess.PIPE) == 0): |
150 | 173 | 192 | from gi.repository import Gio | |
151 | 174 | preferred_xml_app = Gio.app_info_get_default_for_type("application/xml",False) | 193 | |
152 | 175 | if preferred_xml_app: | 194 | preferred_xml_app = Gio.app_info_get_default_for_type( |
153 | 176 | preferred_browser = preferred_xml_app.get_executable() | 195 | "application/xml", False) |
154 | 177 | browser = re.match("((firefox|seamonkey|flock)[^\s]*)", preferred_browser) | 196 | if preferred_xml_app: |
155 | 178 | if browser: | 197 | preferred_browser = preferred_xml_app.get_executable() |
156 | 179 | subprocess.Popen(sudo_prefix + [browser.group(0), "-new-window", url]) | 198 | browser = re.match( |
157 | 180 | return | 199 | "((firefox|seamonkey|flock)[^\s]*)", |
158 | 181 | 200 | preferred_browser) | |
159 | 182 | browser = re.match("(epiphany[^\s]*)", preferred_browser) | 201 | if browser: |
160 | 183 | if browser: | 202 | subprocess.Popen( |
161 | 184 | subprocess.Popen(sudo_prefix + [browser.group(0), "--new-window", url]) | 203 | sudo_prefix + |
162 | 185 | return | 204 | [browser.group(0), "-new-window", url]) |
163 | 186 | 205 | return | |
164 | 187 | browser = re.match("(chromium-browser[^\s]*)", preferred_browser) | 206 | |
165 | 188 | if browser: | 207 | browser = re.match("(epiphany[^\s]*)", preferred_browser) |
166 | 189 | subprocess.Popen(sudo_prefix + [browser.group(0), "--allow-file-access-from-files", url]) | 208 | if browser: |
167 | 190 | return | 209 | subprocess.Popen( |
168 | 191 | 210 | sudo_prefix + | |
169 | 192 | subprocess.Popen(sudo_prefix + [preferred_browser % url], shell=True) | 211 | [browser.group(0), "--new-window", url]) |
170 | 193 | return | 212 | return |
171 | 194 | 213 | ||
172 | 195 | subprocess.Popen(sudo_prefix + ["gnome-open", url]) | 214 | browser = re.match( |
173 | 196 | return | 215 | "(chromium-browser[^\s]*)", preferred_browser) |
174 | 197 | except OSError: | 216 | if browser: |
175 | 198 | pass | 217 | subprocess.Popen( |
176 | 199 | 218 | sudo_prefix + | |
177 | 200 | # fall back to webbrowser | 219 | [browser.group(0), |
178 | 201 | if uid and gid: | 220 | "--allow-file-access-from-files", url]) |
179 | 202 | os.setgroups([gid]) | 221 | return |
180 | 203 | os.setgid(gid) | 222 | |
181 | 204 | os.setuid(uid) | 223 | subprocess.Popen( |
182 | 205 | remove_variable("SUDO_USER") | 224 | sudo_prefix + |
183 | 206 | add_variable("HOME", pwd.getpwuid(uid).pw_dir) | 225 | [preferred_browser % url], shell=True) |
184 | 207 | 226 | return | |
185 | 208 | webbrowser.open(url, new=True, autoraise=True) | 227 | |
186 | 209 | return | 228 | subprocess.Popen(sudo_prefix + ["gnome-open", url]) |
187 | 210 | 229 | return | |
188 | 211 | except Exception as e: | 230 | except OSError: |
189 | 212 | pass | 231 | pass |
190 | 232 | |||
191 | 233 | # fall back to webbrowser | ||
192 | 234 | if uid and gid: | ||
193 | 235 | os.setgroups([gid]) | ||
194 | 236 | os.setgid(gid) | ||
195 | 237 | os.setuid(uid) | ||
196 | 238 | remove_variable("SUDO_USER") | ||
197 | 239 | add_variable("HOME", pwd.getpwuid(uid).pw_dir) | ||
198 | 240 | |||
199 | 241 | webbrowser.open(url, new=True, autoraise=True) | ||
200 | 242 | return | ||
201 | 213 | 243 | ||
202 | 214 | def show_report(self, text, results): | 244 | def show_report(self, text, results): |
203 | 215 | """ | 245 | """ |
204 | @@ -225,5 +255,3 @@ | |||
205 | 225 | about each job. | 255 | about each job. |
206 | 226 | """ | 256 | """ |
207 | 227 | pass | 257 | pass |
208 | 228 | |||
209 | 229 | |||
210 | 230 | 258 | ||
211 | === modified file 'plugins/jobs_info.py' | |||
212 | --- plugins/jobs_info.py 2012-06-26 14:07:30 +0000 | |||
213 | +++ plugins/jobs_info.py 2012-10-17 19:06:24 +0000 | |||
214 | @@ -16,18 +16,29 @@ | |||
215 | 16 | # You should have received a copy of the GNU General Public License | 16 | # You should have received a copy of the GNU General Public License |
216 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. |
217 | 18 | # | 18 | # |
219 | 19 | import os, sys, re | 19 | import os |
220 | 20 | import re | ||
221 | 21 | import sys | ||
222 | 22 | |||
223 | 20 | import difflib | 23 | import difflib |
224 | 21 | import gettext | 24 | import gettext |
225 | 22 | import logging | 25 | import logging |
226 | 23 | 26 | ||
227 | 24 | from collections import defaultdict | 27 | from collections import defaultdict |
228 | 28 | from gettext import gettext as _ | ||
229 | 25 | 29 | ||
230 | 26 | from checkbox.lib.resolver import Resolver | 30 | from checkbox.lib.resolver import Resolver |
231 | 27 | 31 | ||
232 | 28 | from checkbox.arguments import coerce_arguments | 32 | from checkbox.arguments import coerce_arguments |
233 | 29 | from checkbox.properties import Float, Int, List, Map, Path, String | ||
234 | 30 | from checkbox.plugin import Plugin | 33 | from checkbox.plugin import Plugin |
235 | 34 | from checkbox.properties import ( | ||
236 | 35 | Float, | ||
237 | 36 | Int, | ||
238 | 37 | List, | ||
239 | 38 | Map, | ||
240 | 39 | Path, | ||
241 | 40 | String, | ||
242 | 41 | ) | ||
243 | 31 | 42 | ||
244 | 32 | 43 | ||
245 | 33 | job_schema = Map({ | 44 | job_schema = Map({ |
246 | @@ -76,14 +87,17 @@ | |||
247 | 76 | def register(self, manager): | 87 | def register(self, manager): |
248 | 77 | super(JobsInfo, self).register(manager) | 88 | super(JobsInfo, self).register(manager) |
249 | 78 | 89 | ||
252 | 79 | self.whitelist_patterns = self.get_patterns(self.whitelist, self.whitelist_file) | 90 | self.whitelist_patterns = self.get_patterns( |
253 | 80 | self.blacklist_patterns = self.get_patterns(self.blacklist, self.blacklist_file) | 91 | self.whitelist, self.whitelist_file) |
254 | 92 | self.blacklist_patterns = self.get_patterns( | ||
255 | 93 | self.blacklist, self.blacklist_file) | ||
256 | 81 | self.selected_jobs = defaultdict(list) | 94 | self.selected_jobs = defaultdict(list) |
257 | 82 | 95 | ||
258 | 83 | self._manager.reactor.call_on("prompt-begin", self.prompt_begin) | 96 | self._manager.reactor.call_on("prompt-begin", self.prompt_begin) |
259 | 84 | self._manager.reactor.call_on("gather", self.gather) | 97 | self._manager.reactor.call_on("gather", self.gather) |
260 | 85 | if logging.getLogger().getEffectiveLevel() <= logging.DEBUG: | 98 | if logging.getLogger().getEffectiveLevel() <= logging.DEBUG: |
262 | 86 | self._manager.reactor.call_on("prompt-gather", self.post_gather, 90) | 99 | self._manager.reactor.call_on( |
263 | 100 | "prompt-gather", self.post_gather, 90) | ||
264 | 87 | self._manager.reactor.call_on("report-job", self.report_job, -100) | 101 | self._manager.reactor.call_on("report-job", self.report_job, -100) |
265 | 88 | 102 | ||
266 | 89 | def prompt_begin(self, interface): | 103 | def prompt_begin(self, interface): |
267 | @@ -92,7 +106,8 @@ | |||
268 | 92 | to display errors | 106 | to display errors |
269 | 93 | """ | 107 | """ |
270 | 94 | self.interface = interface | 108 | self.interface = interface |
272 | 95 | self.unused_patterns = self.whitelist_patterns + self.blacklist_patterns | 109 | self.unused_patterns = ( |
273 | 110 | self.whitelist_patterns + self.blacklist_patterns) | ||
274 | 96 | 111 | ||
275 | 97 | def check_ordered_messages(self, messages): | 112 | def check_ordered_messages(self, messages): |
276 | 98 | """Return whether the list of messages are ordered or not.""" | 113 | """Return whether the list of messages are ordered or not.""" |
277 | @@ -113,8 +128,8 @@ | |||
278 | 113 | try: | 128 | try: |
279 | 114 | file = open(filename) | 129 | file = open(filename) |
280 | 115 | except IOError as e: | 130 | except IOError as e: |
283 | 116 | error_message=(gettext.gettext("Failed to open file '%s': %s") % | 131 | error_message = (_("Failed to open file '%s': %s") |
284 | 117 | (filename, e.strerror)) | 132 | % (filename, e.strerror)) |
285 | 118 | logging.critical(error_message) | 133 | logging.critical(error_message) |
286 | 119 | sys.stderr.write("%s\n" % error_message) | 134 | sys.stderr.write("%s\n" % error_message) |
287 | 120 | sys.exit(os.EX_NOINPUT) | 135 | sys.exit(os.EX_NOINPUT) |
288 | @@ -148,7 +163,9 @@ | |||
289 | 148 | def report_message(message): | 163 | def report_message(message): |
290 | 149 | if self.whitelist_patterns: | 164 | if self.whitelist_patterns: |
291 | 150 | name = message["name"] | 165 | name = message["name"] |
293 | 151 | if not [name for p in self.whitelist_patterns if p.match(name)]: | 166 | names = [name for p in self.whitelist_patterns |
294 | 167 | if p.match(name)] | ||
295 | 168 | if not names: | ||
296 | 152 | return | 169 | return |
297 | 153 | 170 | ||
298 | 154 | messages.append(message) | 171 | messages.append(message) |
299 | @@ -156,7 +173,8 @@ | |||
300 | 156 | # Set domain and message event handler | 173 | # Set domain and message event handler |
301 | 157 | old_domain = gettext.textdomain() | 174 | old_domain = gettext.textdomain() |
302 | 158 | gettext.textdomain(self.domain) | 175 | gettext.textdomain(self.domain) |
304 | 159 | event_id = self._manager.reactor.call_on("report-message", report_message, 100) | 176 | event_id = self._manager.reactor.call_on( |
305 | 177 | "report-message", report_message, 100) | ||
306 | 160 | 178 | ||
307 | 161 | for directory in self.directories: | 179 | for directory in self.directories: |
308 | 162 | self._manager.reactor.fire("message-directory", directory) | 180 | self._manager.reactor.fire("message-directory", directory) |
309 | @@ -182,7 +200,8 @@ | |||
310 | 182 | messages = sorted(messages, key=key_function) | 200 | messages = sorted(messages, key=key_function) |
311 | 183 | 201 | ||
312 | 184 | if not self.check_ordered_messages(messages): | 202 | if not self.check_ordered_messages(messages): |
314 | 185 | old_message_names = [message["name"] + "\n" for message in messages] | 203 | old_message_names = [ |
315 | 204 | message["name"] + "\n" for message in messages] | ||
316 | 186 | resolver = Resolver(key_func=lambda m: m["name"]) | 205 | resolver = Resolver(key_func=lambda m: m["name"]) |
317 | 187 | for message in messages: | 206 | for message in messages: |
318 | 188 | resolver.add( | 207 | resolver.add( |
319 | @@ -192,7 +211,8 @@ | |||
320 | 192 | # Check if messages are already topologically ordered | 211 | # Check if messages are already topologically ordered |
321 | 193 | if (self.whitelist_patterns and | 212 | if (self.whitelist_patterns and |
322 | 194 | logging.getLogger().getEffectiveLevel() <= logging.DEBUG): | 213 | logging.getLogger().getEffectiveLevel() <= logging.DEBUG): |
324 | 195 | new_message_names = [message["name"] + "\n" for message in messages] | 214 | new_message_names = [ |
325 | 215 | message["name"] + "\n" for message in messages] | ||
326 | 196 | detailed_text = "".join( | 216 | detailed_text = "".join( |
327 | 197 | difflib.unified_diff( | 217 | difflib.unified_diff( |
328 | 198 | old_message_names, | 218 | old_message_names, |
329 | @@ -200,7 +220,7 @@ | |||
330 | 200 | "old whitelist", | 220 | "old whitelist", |
331 | 201 | "new whitelist")) | 221 | "new whitelist")) |
332 | 202 | self._manager.reactor.fire( | 222 | self._manager.reactor.fire( |
334 | 203 | "prompt-error", | 223 | "prompt-warning", |
335 | 204 | self.interface, | 224 | self.interface, |
336 | 205 | "Whitelist not topologically ordered", | 225 | "Whitelist not topologically ordered", |
337 | 206 | "Jobs will be reordered to fix broken dependencies", | 226 | "Jobs will be reordered to fix broken dependencies", |
338 | @@ -231,7 +251,7 @@ | |||
339 | 231 | 'Please make sure that the patterns you used are up-to-date\n' | 251 | 'Please make sure that the patterns you used are up-to-date\n' |
340 | 232 | .format('\n'.join(['- {0}'.format(tc) | 252 | .format('\n'.join(['- {0}'.format(tc) |
341 | 233 | for tc in orphan_test_cases]))) | 253 | for tc in orphan_test_cases]))) |
343 | 234 | self._manager.reactor.fire('prompt-error', self.interface, | 254 | self._manager.reactor.fire('prompt-warning', self.interface, |
344 | 235 | 'Orphan test cases detected', | 255 | 'Orphan test cases detected', |
345 | 236 | "Some test cases aren't included " | 256 | "Some test cases aren't included " |
346 | 237 | 'in any test suite', | 257 | 'in any test suite', |
347 | @@ -244,7 +264,7 @@ | |||
348 | 244 | "Please make sure that the patterns you used are up-to-date\n" | 264 | "Please make sure that the patterns you used are up-to-date\n" |
349 | 245 | .format('\n'.join(['- {0}'.format(p.pattern[1:-1]) | 265 | .format('\n'.join(['- {0}'.format(p.pattern[1:-1]) |
350 | 246 | for p in self.unused_patterns]))) | 266 | for p in self.unused_patterns]))) |
352 | 247 | self._manager.reactor.fire('prompt-error', self.interface, | 267 | self._manager.reactor.fire('prompt-warning', self.interface, |
353 | 248 | 'Unused patterns', | 268 | 'Unused patterns', |
354 | 249 | 'Please make sure that the patterns ' | 269 | 'Please make sure that the patterns ' |
355 | 250 | 'you used are up-to-date', | 270 | 'you used are up-to-date', |
356 | 251 | 271 | ||
357 | === added file 'plugins/warning_prompt.py' | |||
358 | --- plugins/warning_prompt.py 1970-01-01 00:00:00 +0000 | |||
359 | +++ plugins/warning_prompt.py 2012-10-17 19:06:24 +0000 | |||
360 | @@ -0,0 +1,35 @@ | |||
361 | 1 | # | ||
362 | 2 | # This file is part of Checkbox. | ||
363 | 3 | # | ||
364 | 4 | # Copyright 2012 Canonical Ltd. | ||
365 | 5 | # | ||
366 | 6 | # Checkbox is free software: you can redistribute it and/or modify | ||
367 | 7 | # it under the terms of the GNU General Public License as published by | ||
368 | 8 | # the Free Software Foundation, either version 3 of the License, or | ||
369 | 9 | # (at your option) any later version. | ||
370 | 10 | # | ||
371 | 11 | # Checkbox is distributed in the hope that it will be useful, | ||
372 | 12 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
373 | 13 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
374 | 14 | # GNU General Public License for more details. | ||
375 | 15 | # | ||
376 | 16 | # You should have received a copy of the GNU General Public License | ||
377 | 17 | # along with Checkbox. If not, see <http://www.gnu.org/licenses/>. | ||
378 | 18 | # | ||
379 | 19 | from checkbox.plugin import Plugin | ||
380 | 20 | |||
381 | 21 | |||
382 | 22 | class WarningPrompt(Plugin): | ||
383 | 23 | |||
384 | 24 | def register(self, manager): | ||
385 | 25 | super(WarningPrompt, self).register(manager) | ||
386 | 26 | |||
387 | 27 | self._manager.reactor.call_on("prompt-warning", | ||
388 | 28 | self.prompt_warning) | ||
389 | 29 | |||
390 | 30 | def prompt_warning(self, interface, | ||
391 | 31 | primary_text, secondary_text=None, detailed_text=None): | ||
392 | 32 | interface.show_warning(primary_text, secondary_text, detailed_text) | ||
393 | 33 | |||
394 | 34 | |||
395 | 35 | factory = WarningPrompt |
There's a lot of pep8 fixes but i'm happy with the skeleton of show_warning() in base checkbox/ user_interface. py.
Thanks