[supervision] Do not crash if qtwebkit is not installed. (#2982)

* [supervision] Do not crash if qtwebkit is not installed.

* Fix test

* fix return type.

* Better conf error propagation.
This commit is contained in:
Fabien-B
2023-02-07 17:47:22 +01:00
committed by GitHub
parent 8833bb4fc5
commit de258cf6bd
3 changed files with 59 additions and 41 deletions
+28 -30
View File
@@ -11,6 +11,10 @@ MOD_DEP = os.path.join(utils.PAPARAZZI_SRC, "sw", "tools", "generators", "dump_m
CONF = os.path.join(utils.PAPARAZZI_HOME, "conf", "conf.xml")
class ConfError(Exception):
...
@dataclass
class Setting:
name: str
@@ -36,9 +40,6 @@ class Aircraft:
settings_modules: List[Setting] = field(default_factory=list)
boards: Dict[str, str] = field(default_factory=dict, init=False) # {target: board}
def __post_init__(self):
self.update_targets()
def get_color(self) -> str:
if self.gui_color.startswith("#"):
r = self.gui_color[1:3]
@@ -61,36 +62,35 @@ class Aircraft:
def update(self):
self.update_targets()
return self.update_settings()
self.update_settings()
def update_settings(self):
completed = subprocess.run([MOD_DEP, "-ac", self.name, "-af", self.airframe, "-fp", self.flight_plan],
capture_output=True)
if completed.returncode == 0:
if completed.returncode != 0:
raise ConfError(completed.stderr.decode().strip())
def make_setting(m):
setting = Setting(m, True)
for s in self.settings_modules:
if m == s.name and not s.enabled:
setting.enabled = False
return setting
def make_setting(m):
setting = Setting(m, True)
for s in self.settings_modules:
if m == s.name and not s.enabled:
setting.enabled = False
return setting
new_settings_modules = []
for module_path in completed.stdout.decode().strip().split():
module = utils.remove_prefix(module_path, utils.CONF_DIR)
xml = ET.parse(module_path)
for xml_setting in xml.getroot().findall("settings"):
name = xml_setting.get("name")
if name is None:
txt = module
else:
txt = "{}~{}~".format(module, name)
setting = make_setting(txt)
new_settings_modules.append(setting)
new_settings_modules = []
for module_path in completed.stdout.decode().strip().split():
module = utils.remove_prefix(module_path, utils.CONF_DIR)
xml = ET.parse(module_path)
for xml_setting in xml.getroot().findall("settings"):
name = xml_setting.get("name")
if name is None:
txt = module
else:
txt = "{}~{}~".format(module, name)
setting = make_setting(txt)
new_settings_modules.append(setting)
self.settings_modules = new_settings_modules
return completed.returncode, completed.stderr
self.settings_modules = new_settings_modules
def to_xml(self) -> ET.Element:
xml = ET.Element("aircraft")
@@ -131,11 +131,9 @@ class Aircraft:
board = target_xml.get("board")
self.boards[target] = board
except OSError as e:
print("OSError, file {} probably not found!".format(self.airframe))
print(e)
raise ConfError("OSError, file {} probably not found!".format(self.airframe))
except ET.XMLSyntaxError as e:
print("XMLSyntaxError, file {} is illformed !".format(self.airframe))
print(e)
raise ConfError("XMLSyntaxError, file {} is illformed !".format(self.airframe))
class Conf:
+25 -4
View File
@@ -1,9 +1,20 @@
# Copyright (C) 2008-2022 The Paparazzi Team
# released under GNU GPLv2 or later. See COPYING file.
from generated.ui_doc_viewer import Ui_DocPanel
from PyQt5.QtWidgets import *
from PyQt5.QtCore import QUrl
from PyQt5.QtCore import QUrl, Qt
try:
from generated.ui_doc_viewer import Ui_DocPanel
except ImportError:
class Ui_DocPanel:
def setupUi(self, DocPanel):
self.deactivated = True
self.lay = QVBoxLayout(DocPanel)
label = QLabel("Please install 'python3-pyqt5.qtwebkit' to view the doc.", DocPanel)
label.setTextInteractionFlags(Qt.TextSelectableByMouse | Qt.TextSelectableByKeyboard)
self.lay.addWidget(label)
from PyQt5.QtGui import QDesktopServices
import utils
import os
@@ -19,6 +30,11 @@ class DocPanel(QWidget, Ui_DocPanel):
def __init__(self, parent=None):
QWidget.__init__(self, parent=parent)
self.setupUi(self)
try:
self.deactivated
return
except AttributeError:
...
self.current_ac = None
self.doc_source_combo.currentTextChanged.connect(self.change_doc_source)
self.open_browser_button.clicked.connect(lambda: QDesktopServices.openUrl(self.webView.url()))
@@ -47,6 +63,11 @@ class DocPanel(QWidget, Ui_DocPanel):
...
def set_aircraft(self, ac: conf.Aircraft):
try:
self.deactivated
return
except AttributeError:
...
self.current_ac = ac
targets = ac.boards.keys()
self.target_combo.clear()
@@ -111,7 +132,7 @@ class DocPanel(QWidget, Ui_DocPanel):
args.extend(["-t", target])
completed = subprocess.run(args, capture_output=True)
if completed.returncode != 0:
return completed.returncode, completed.stderr
return [] # completed.returncode, completed.stderr
modules_list = []
module_lines = completed.stdout.decode().strip().split("\n")
+6 -7
View File
@@ -9,7 +9,7 @@ from PyQt5.QtWidgets import *
from PyQt5 import QtCore, QtGui
import utils
from lxml import etree as ET
from conf import Conf, Aircraft
from conf import Conf, Aircraft, ConfError
from app_settings import AppSettings
from generated.ui_supervision_window import Ui_SupervisionWindow
from generated.ui_new_ac_dialog import Ui_NewACDialog
@@ -74,18 +74,17 @@ class PprzCenter(QMainWindow, Ui_SupervisionWindow):
else:
self.header.id_spinBox.setStyleSheet("background-color: white;")
# update ac, then update all widgets
status, stderr = ac.update()
if status != 0:
self.handle_error(stderr.decode().strip())
else:
try:
ac.update()
self.clear_error()
pass
except ConfError as e:
self.handle_error(e.__str__())
self.change_ac(ac)
def handle_ac_changed(self, ac_name):
ac = self.conf[ac_name]
if ac is not None:
# self.handle_ac_edited(ac) # update AC ?
self.handle_ac_edited(ac) # update AC
self.change_ac(ac)
def handle_remove_ac(self, ac: Aircraft):