Code deduplication and cleanup

Moved loop handling, exception handling and program
running methods of the gui tools to the utils file.

fixes QubesOS/qubes-issues#5342
This commit is contained in:
Marta Marczykowska-Górecka 2019-09-26 22:31:39 +02:00
parent 8a3653723d
commit 32078242c9
No known key found for this signature in database
GPG Key ID: 9A752C30B26FD04B
8 changed files with 117 additions and 334 deletions

View File

@ -20,18 +20,14 @@
# #
# #
import traceback
import signal import signal
import quamash from qubesadmin import exc
from qubesadmin import Qubes, exc
from qubesadmin import utils as admin_utils from qubesadmin import utils as admin_utils
from qubesadmin import events
from qubes.storage.file import get_disk_usage from qubes.storage.file import get_disk_usage
from PyQt5 import QtCore # pylint: disable=import-error from PyQt5 import QtCore # pylint: disable=import-error
from PyQt5 import QtWidgets # pylint: disable=import-error from PyQt5 import QtWidgets # pylint: disable=import-error
from PyQt5 import QtGui
from . import ui_backupdlg # pylint: disable=no-name-in-module from . import ui_backupdlg # pylint: disable=no-name-in-module
from . import multiselectwidget from . import multiselectwidget
@ -393,57 +389,10 @@ class BackupVMsWindow(ui_backupdlg.Ui_Backup, QtWidgets.QWizard):
self.select_dir_page.completeChanged.emit() self.select_dir_page.completeChanged.emit()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception(exc_type, exc_value, exc_traceback):
filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
filename = os.path.basename(filename)
error = "%s: %s" % (exc_type.__name__, exc_value)
QtWidgets.QMessageBox.critical(
None,
"Houston, we have a problem...",
"Whoops. A critical error has occured. This is most likely a bug "
"in Qubes Global Settings application.<br><br><b><i>%s</i></b>" %
error + "at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% (line, filename))
def loop_shutdown():
pending = asyncio.Task.all_tasks()
for task in pending:
with suppress(asyncio.CancelledError):
task.cancel()
def main(): def main():
qt_app = QtWidgets.QApplication(sys.argv) utils.run_asynchronous("Qubes Backup VMs",
qt_app.setOrganizationName("The Qubes Project") QtGui.QIcon.fromTheme("qubes-manager"),
qt_app.setOrganizationDomain("http://qubes-os.org") BackupVMsWindow)
qt_app.setApplicationName("Qubes Backup VMs")
qt_app.lastWindowClosed.connect(loop_shutdown)
sys.excepthook = handle_exception
qubes_app = Qubes()
loop = quamash.QEventLoop(qt_app)
asyncio.set_event_loop(loop)
dispatcher = events.EventsDispatcher(qubes_app)
backup_window = BackupVMsWindow(qt_app, qubes_app, dispatcher)
backup_window.show()
try:
loop.run_until_complete(
asyncio.ensure_future(dispatcher.listen_for_events()))
except asyncio.CancelledError:
pass
except Exception: # pylint: disable=broad-except
loop_shutdown()
exc_type, exc_value, exc_traceback = sys.exc_info()[:3]
handle_exception(exc_type, exc_value, exc_traceback)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -17,7 +17,7 @@
# #
# #
import sys import functools
import subprocess import subprocess
from . import utils from . import utils
from . import ui_bootfromdevice # pylint: disable=no-name-in-module from . import ui_bootfromdevice # pylint: disable=no-name-in-module
@ -28,7 +28,7 @@ from qubesadmin.tools import qvm_start
class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog, class VMBootFromDeviceWindow(ui_bootfromdevice.Ui_BootDialog,
QtWidgets.QDialog): QtWidgets.QDialog):
def __init__(self, vm, qapp, parent=None): def __init__(self, vm, qapp, qubesapp=None, parent=None):
super(VMBootFromDeviceWindow, self).__init__(parent) super(VMBootFromDeviceWindow, self).__init__(parent)
self.vm = vm self.vm = vm
@ -147,19 +147,8 @@ def main(args=None):
args = parser.parse_args(args) args = parser.parse_args(args)
vm = args.domains.pop() vm = args.domains.pop()
qapp = QtWidgets.QApplication(sys.argv) utils.run_synchronous("Boot Qube From Device",
qapp.setOrganizationName('Invisible Things Lab') functools.partial(VMBootFromDeviceWindow, vm))
qapp.setOrganizationDomain("https://www.qubes-os.org/")
qapp.setApplicationName("Boot Qube From Device")
# if not utils.is_debug(): #FIXME
# sys.excepthook = handle_exception
bootfromdevice_window = VMBootFromDeviceWindow(vm, qapp)
bootfromdevice_window.show()
qapp.exec_()
qapp.exit()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -20,14 +20,11 @@
# #
# #
import sys
import os import os
import os.path import os.path
import traceback
import subprocess import subprocess
from PyQt5 import QtWidgets # pylint: disable=import-error from PyQt5 import QtWidgets # pylint: disable=import-error
from qubesadmin import Qubes
from qubesadmin.utils import parse_size from qubesadmin.utils import parse_size
from . import ui_globalsettingsdlg # pylint: disable=no-name-in-module from . import ui_globalsettingsdlg # pylint: disable=no-name-in-module
@ -406,39 +403,9 @@ class GlobalSettingsWindow(ui_globalsettingsdlg.Ui_GlobalSettings,
self.__apply_updates__() self.__apply_updates__()
self.__apply_repos__() self.__apply_repos__()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception(exc_type, exc_value, exc_traceback):
filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
filename = os.path.basename(filename)
error = "%s: %s" % (exc_type.__name__, exc_value)
QtWidgets.QMessageBox.critical(
None,
"Houston, we have a problem...",
"Whoops. A critical error has occured. This is most likely a bug "
"in Qubes Global Settings application.<br><br><b><i>%s</i></b>" %
error + "at <b>line %d</b> of file <b>%s</b>.<br/><br/>"
% (line, filename))
def main(): def main():
qtapp = QtWidgets.QApplication(sys.argv) utils.run_synchronous("Qubes Global Settings", GlobalSettingsWindow)
qtapp.setOrganizationName("The Qubes Project")
qtapp.setOrganizationDomain("http://qubes-os.org")
qtapp.setApplicationName("Qubes Global Settings")
sys.excepthook = handle_exception
app = Qubes()
global_window = GlobalSettingsWindow(qtapp, app)
global_window.show()
qtapp.exec_()
qtapp.exit()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -21,21 +21,13 @@
# with this program; if not, see <http://www.gnu.org/licenses/>. # with this program; if not, see <http://www.gnu.org/licenses/>.
# #
# #
import sys
import os import os
import os.path import os.path
import subprocess import subprocess
from datetime import datetime, timedelta from datetime import datetime, timedelta
import traceback
from contextlib import suppress
import quamash
import asyncio
from qubesadmin import Qubes
from qubesadmin import exc from qubesadmin import exc
from qubesadmin import utils from qubesadmin import utils
from qubesadmin import events
from PyQt5 import QtWidgets, QtCore, QtGui # pylint: disable=import-error from PyQt5 import QtWidgets, QtCore, QtGui # pylint: disable=import-error
@ -1306,71 +1298,11 @@ class VmManagerWindow(ui_qubemanager.Ui_VmManagerWindow, QtWidgets.QMainWindow):
log_dlg.exec_() log_dlg.exec_()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception(exc_type, exc_value, exc_traceback):
filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
filename = os.path.basename(filename)
error = "%s: %s" % (exc_type.__name__, exc_value)
strace = ""
stacktrace = traceback.extract_tb(exc_traceback)
while stacktrace:
(filename, line, func, txt) = stacktrace.pop()
strace += "----\n"
strace += "line: %s\n" % txt
strace += "func: %s\n" % func
strace += "line no.: %d\n" % line
strace += "file: %s\n" % filename
msg_box = QtWidgets.QMessageBox()
msg_box.setDetailedText(strace)
msg_box.setIcon(QtWidgets.QMessageBox.Critical)
msg_box.setWindowTitle("Houston, we have a problem...")
msg_box.setText("Whoops. A critical error has occured. "
"This is most likely a bug in Qubes Manager.<br><br>"
"<b><i>%s</i></b>" % error +
"<br/>at line <b>%d</b><br/>of file %s.<br/><br/>"
% (line, filename))
msg_box.exec_()
def loop_shutdown():
pending = asyncio.Task.all_tasks()
for task in pending:
with suppress(asyncio.CancelledError):
task.cancel()
def main(): def main():
qt_app = QtWidgets.QApplication(sys.argv) manager_utils.run_asynchronous(
qt_app.setOrganizationName("The Qubes Project") "Qube Manager",
qt_app.setOrganizationDomain("http://qubes-os.org") QtGui.QIcon.fromTheme("qubes-manager"),
qt_app.setApplicationName("Qube Manager") VmManagerWindow)
qt_app.setWindowIcon(QtGui.QIcon.fromTheme("qubes-manager"))
qt_app.lastWindowClosed.connect(loop_shutdown)
qubes_app = Qubes()
loop = quamash.QEventLoop(qt_app)
asyncio.set_event_loop(loop)
dispatcher = events.EventsDispatcher(qubes_app)
manager_window = VmManagerWindow(qt_app, qubes_app, dispatcher)
manager_window.show()
try:
loop.run_until_complete(
asyncio.ensure_future(dispatcher.listen_for_events()))
except asyncio.CancelledError:
pass
except Exception: # pylint: disable=broad-except
loop_shutdown()
exc_type, exc_value, exc_traceback = sys.exc_info()[:3]
handle_exception(exc_type, exc_value, exc_traceback)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -20,11 +20,9 @@
# #
# #
import sys
from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error from PyQt5 import QtCore, QtWidgets # pylint: disable=import-error
import os import os
import os.path import os.path
import traceback
import logging import logging
import logging.handlers import logging.handlers
@ -33,6 +31,7 @@ from qubes import backup
from . import ui_restoredlg # pylint: disable=no-name-in-module from . import ui_restoredlg # pylint: disable=no-name-in-module
from . import multiselectwidget from . import multiselectwidget
from . import backup_utils from . import backup_utils
from . import utils
from multiprocessing import Queue from multiprocessing import Queue
from queue import Empty from queue import Empty
@ -292,39 +291,8 @@ class RestoreVMsWindow(ui_restoredlg.Ui_Restore, QtWidgets.QWizard):
self.select_dir_page.completeChanged.emit() self.select_dir_page.completeChanged.emit()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception(exc_type, exc_value, exc_traceback):
filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
filename = os.path.basename(filename)
error = "%s: %s" % (exc_type.__name__, exc_value)
QtWidgets.QMessageBox.critical(
None, "Houston, we have a problem...",
"Whoops. A critical error has occured. This is most likely a bug "
"in Qubes Restore VMs application.<br><br><b><i>%s</i></b>" % error +
"at <b>line %d</b> of file <b>%s</b>.<br/><br/>" % (line, filename))
def main(): def main():
utils.run_synchronous("Qubes Restore VMs", RestoreVMsWindow)
qt_app = QtWidgets.QApplication(sys.argv)
qt_app.setOrganizationName("The Qubes Project")
qt_app.setOrganizationDomain("http://qubes-os.org")
qt_app.setApplicationName("Qubes Restore VMs")
sys.excepthook = handle_exception
qubes_app = Qubes()
restore_window = RestoreVMsWindow(qt_app, qubes_app)
restore_window.show()
qt_app.exec_()
qt_app.exit()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -23,12 +23,10 @@
# #
import collections import collections
import os.path import functools
import os
import re import re
import subprocess import subprocess
import traceback import traceback
import sys
from qubesadmin.tools import QubesArgumentParser from qubesadmin.tools import QubesArgumentParser
from qubesadmin import devices from qubesadmin import devices
from qubesadmin import utils as admin_utils from qubesadmin import utils as admin_utils
@ -128,11 +126,13 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
('services', 5), ('services', 5),
)) ))
def __init__(self, vm, qapp, init_page="basic", parent=None): def __init__(self, vm, init_page="basic", qapp=None, qubesapp=None,
parent=None):
super(VMSettingsWindow, self).__init__(parent) super(VMSettingsWindow, self).__init__(parent)
self.vm = vm self.vm = vm
self.qapp = qapp self.qapp = qapp
self.qubesapp = qubesapp
self.threads_list = [] self.threads_list = []
self.progress = None self.progress = None
self.thread_closes = False self.thread_closes = False
@ -1218,38 +1218,6 @@ class VMSettingsWindow(ui_settingsdlg.Ui_SettingsDialog, QtWidgets.QDialog):
self.fw_model.remove_child(i) self.fw_model.remove_child(i)
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception(exc_type, exc_value, exc_traceback):
filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
filename = os.path.basename(filename)
error = "%s: %s" % (exc_type.__name__, exc_value)
strace = ""
stacktrace = traceback.extract_tb(exc_traceback)
while stacktrace:
(filename, line, func, txt) = stacktrace.pop()
strace += "----\n"
strace += "line: %s\n" % txt
strace += "func: %s\n" % func
strace += "line no.: %d\n" % line
strace += "file: %s\n" % filename
msg_box = QtWidgets.QMessageBox()
msg_box.setDetailedText(strace)
msg_box.setIcon(QtWidgets.QMessageBox.Critical)
msg_box.setWindowTitle("Houston, we have a problem...")
msg_box.setText("Whoops. A critical error has occured. "
"This is most likely a bug in Qubes Manager.<br><br>"
"<b><i>%s</i></b>" % error +
"<br/>at line <b>%d</b><br/>of file %s.<br/><br/>"
% (line, filename))
msg_box.exec_()
parser = QubesArgumentParser(vmname_nargs=1) parser = QubesArgumentParser(vmname_nargs=1)
parser.add_argument('--tab', metavar='TAB', parser.add_argument('--tab', metavar='TAB',
@ -1265,19 +1233,8 @@ def main(args=None):
args = parser.parse_args(args) args = parser.parse_args(args)
vm = args.domains.pop() vm = args.domains.pop()
qapp = QtWidgets.QApplication(sys.argv) utils.run_synchronous("Qube Settings",
qapp.setOrganizationName('Invisible Things Lab') functools.partial(VMSettingsWindow, vm, args.tab))
qapp.setOrganizationDomain("https://www.qubes-os.org/")
qapp.setApplicationName("Qube Settings")
if not utils.is_debug():
sys.excepthook = handle_exception
settings_window = VMSettingsWindow(vm, qapp, args.tab)
settings_window.show()
qapp.exec_()
qapp.exit()
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -20,21 +20,12 @@
# #
# #
import sys
import os
import os.path
import traceback
import quamash
import asyncio
from contextlib import suppress
from qubesadmin import Qubes
from qubesadmin import exc from qubesadmin import exc
from qubesadmin import events
from PyQt5 import QtWidgets, QtGui, QtCore # pylint: disable=import-error from PyQt5 import QtWidgets, QtGui, QtCore # pylint: disable=import-error
from . import ui_templatemanager # pylint: disable=no-name-in-module from . import ui_templatemanager # pylint: disable=no-name-in-module
from . import utils
column_names = ['State', 'Qube', 'Current template', 'New template'] column_names = ['State', 'Qube', 'Current template', 'New template']
@ -385,72 +376,11 @@ class VMRow:
row, column_names.index('State')) row, column_names.index('State'))
self.checkbox = None self.checkbox = None
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception(exc_type, exc_value, exc_traceback):
filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
filename = os.path.basename(filename)
error = "%s: %s" % (exc_type.__name__, exc_value)
strace = ""
stacktrace = traceback.extract_tb(exc_traceback)
while stacktrace:
(filename, line, func, txt) = stacktrace.pop()
strace += "----\n"
strace += "line: %s\n" % txt
strace += "func: %s\n" % func
strace += "line no.: %d\n" % line
strace += "file: %s\n" % filename
msg_box = QtWidgets.QMessageBox()
msg_box.setDetailedText(strace)
msg_box.setIcon(QtWidgets.QMessageBox.Critical)
msg_box.setWindowTitle("Houston, we have a problem...")
msg_box.setText("Whoops. A critical error has occured. "
"This is most likely a bug in Qubes Manager.<br><br>"
"<b><i>%s</i></b>" % error +
"<br/>at line <b>%d</b><br/>of file %s.<br/><br/>"
% (line, filename))
msg_box.exec_()
def loop_shutdown():
pending = asyncio.Task.all_tasks()
for task in pending:
with suppress(asyncio.CancelledError):
task.cancel()
def main(): def main():
qt_app = QtWidgets.QApplication(sys.argv) utils.run_asynchronous("Template Manager",
qt_app.setOrganizationName("The Qubes Project") QtGui.QIcon.fromTheme("qubes-manager"),
qt_app.setOrganizationDomain("http://qubes-os.org") TemplateManagerWindow)
qt_app.setApplicationName("Qube Manager")
qt_app.setWindowIcon(QtGui.QIcon.fromTheme("qubes-manager"))
qt_app.lastWindowClosed.connect(loop_shutdown)
qubes_app = Qubes()
loop = quamash.QEventLoop(qt_app)
asyncio.set_event_loop(loop)
dispatcher = events.EventsDispatcher(qubes_app)
manager_window = TemplateManagerWindow(qt_app, qubes_app, dispatcher)
manager_window.show()
try:
loop.run_until_complete(
asyncio.ensure_future(dispatcher.listen_for_events()))
except asyncio.CancelledError:
pass
except Exception: # pylint: disable=broad-except
loop_shutdown()
exc_type, exc_value, exc_traceback = sys.exc_info()[:3]
handle_exception(exc_type, exc_value, exc_traceback)
if __name__ == "__main__": if __name__ == "__main__":

View File

@ -23,7 +23,14 @@ import itertools
import os import os
import re import re
import qubesadmin import qubesadmin
import traceback
import asyncio
from contextlib import suppress
import sys
import quamash
from qubesadmin import events
from PyQt5 import QtWidgets
from PyQt5.QtGui import QIcon # pylint: disable=import-error from PyQt5.QtGui import QIcon # pylint: disable=import-error
@ -215,3 +222,87 @@ def format_dependencies_list(dependencies):
prop, holder.name) prop, holder.name)
return list_text return list_text
def loop_shutdown():
pending = asyncio.Task.all_tasks()
for task in pending:
with suppress(asyncio.CancelledError):
task.cancel()
# Bases on the original code by:
# Copyright (c) 2002-2007 Pascal Varet <p.varet@gmail.com>
def handle_exception(exc_type, exc_value, exc_traceback):
filename, line, dummy, dummy = traceback.extract_tb(exc_traceback).pop()
filename = os.path.basename(filename)
error = "%s: %s" % (exc_type.__name__, exc_value)
strace = ""
stacktrace = traceback.extract_tb(exc_traceback)
while stacktrace:
(filename, line, func, txt) = stacktrace.pop()
strace += "----\n"
strace += "line: %s\n" % txt
strace += "func: %s\n" % func
strace += "line no.: %d\n" % line
strace += "file: %s\n" % filename
msg_box = QtWidgets.QMessageBox()
msg_box.setDetailedText(strace)
msg_box.setIcon(QtWidgets.QMessageBox.Critical)
msg_box.setWindowTitle("Houston, we have a problem...")
msg_box.setText("Whoops. A critical error has occured. "
"This is most likely a bug in Qubes Manager.<br><br>"
"<b><i>%s</i></b>" % error +
"<br/>at line <b>%d</b><br/>of file %s.<br/><br/>"
% (line, filename))
msg_box.exec_()
def run_asynchronous(app_name, icon, window_class):
qt_app = QtWidgets.QApplication(sys.argv)
qt_app.setOrganizationName("The Qubes Project")
qt_app.setOrganizationDomain("http://qubes-os.org")
qt_app.setApplicationName(app_name)
qt_app.setWindowIcon(icon)
qt_app.lastWindowClosed.connect(loop_shutdown)
qubes_app = qubesadmin.Qubes()
loop = quamash.QEventLoop(qt_app)
asyncio.set_event_loop(loop)
dispatcher = events.EventsDispatcher(qubes_app)
window = window_class(qt_app, qubes_app, dispatcher)
window.show()
try:
loop.run_until_complete(
asyncio.ensure_future(dispatcher.listen_for_events()))
except asyncio.CancelledError:
pass
except Exception: # pylint: disable=broad-except
loop_shutdown()
exc_type, exc_value, exc_traceback = sys.exc_info()[:3]
handle_exception(exc_type, exc_value, exc_traceback)
def run_synchronous(app_name, window_class):
qt_app = QtWidgets.QApplication(sys.argv)
qt_app.setOrganizationName("The Qubes Project")
qt_app.setOrganizationDomain("http://qubes-os.org")
qt_app.setApplicationName(app_name)
sys.excepthook = handle_exception
qubes_app = qubesadmin.Qubes()
window = window_class(qt_app, qubes_app)
window.show()
qt_app.exec_()
qt_app.exit()