Improved automated python tools for maintenance (#2433)

* Added last commit dates to lists of untested flight plans and airframes

* Improved paparazzi_health to include a list of all modules and their usage

* improved paparazzi_health to include a list of board makefiles not used by any airframe

* improved paparazzi_health to generate list of unused airframes, flightplans and boards sorted by most recently changed

* airframe details now stores modules as tuple of name and type: [(name, type), ...]

* added seeing includes in paparazzi_health

* Removed unneccesary print statements

* Added widget to start.py to generate html table of the module usage of the airframes for the selected conf

* improved html table readability and sorted airframe names alphabetically

* fixed alphabetical ordering of airframe name being case sensitive and added comments

* Added module class, more info about modules now gets printed. Commit dates should still be fixed

* Did speed improvement, but still slow

* split up more info and lists of untested files

* Added checkboxes to start.py to give user option to show airframe detail, or untested files, or both

* Cleaned up some code

* Added separator to make link between checkboxes and MoreInfo button clearer

* Fixed code style

* Added description to the module listing

* one should now be able to select which aspects to show in the maintenance tools

* Initial version of maintenance tools window

* Now also checks if modules are mentioned in the settings modules in an userconf

* Improved layout of maintenance tool window

* Improved variable names and tooltip information

* Small QoL changes to prepare for pull request

* Fixed a bug with the untested boards not showing correctly if airframes was not also selected and fixed some Codacy issues
This commit is contained in:
Matteo Barbera
2019-06-09 10:55:49 +02:00
committed by Christophe De Wagter
parent 1da047b8ce
commit d23ed71ede
3 changed files with 583 additions and 113 deletions
+124 -22
View File
@@ -66,21 +66,22 @@ class ConfChooser(object):
# CallBack Functions
def find_conf_files(self):
def find_conf_files(self, combo):
conf_files = paparazzi.get_list_of_conf_files(self.exclude_backups)
self.update_combo(self.conf_file_combo, conf_files, self.conf_xml)
self.update_combo(combo, conf_files, self.conf_xml)
def find_controlpanel_files(self):
controlpanel_files = paparazzi.get_list_of_controlpanel_files(self.exclude_backups)
self.update_combo(self.controlpanel_file_combo, controlpanel_files, self.controlpanel_xml)
def count_airframes_in_conf(self):
@staticmethod
def count_airframes_in_conf(combo, conf_airframes):
airframes = 0
releases = 0
if self.conf_file_combo.get_active_text() is None:
if combo.get_active_text() is None:
return
desc = ""
afile = os.path.join(paparazzi.conf_dir, self.conf_file_combo.get_active_text())
afile = os.path.join(paparazzi.conf_dir, combo.get_active_text())
if os.path.exists(afile):
e = xml.etree.ElementTree.parse(afile).getroot()
for atype in e.findall('aircraft'):
@@ -94,7 +95,7 @@ class ConfChooser(object):
else:
desc += atype.get('name')
desc = "<b>" + str(airframes) + " airframes:</b> " + desc
self.conf_airframes.set_markup(desc)
conf_airframes.set_markup(desc)
return
def about(self, widget):
@@ -120,13 +121,22 @@ class ConfChooser(object):
def set_backups(self, widget):
self.exclude_backups = not widget.get_active()
self.find_conf_files()
self.find_conf_files(self.conf_file_combo)
self.find_controlpanel_files()
def more_info(self, widget):
obj = PaparazziOverview(0)
obj.run()
self.obj.run()
def show_untested(self, widget, data):
self.obj.run(show_af_detail=False, show_untested=True,
show_airframes=data["Airframes"].get_active(),
show_flightplans=data["Flightplans"].get_active(),
show_boards=data["Boards"].get_active(),
show_modules=data["Modules"].get_active())
def module_usage(self, widget, data):
selected_conf = data.get_active_text()
self.obj.airframe_module_overview(selected_conf)
def launch(self, widget):
self.accept(widget)
@@ -184,8 +194,8 @@ class ConfChooser(object):
if os.path.exists(filename):
os.remove(filename)
self.update_conf_label()
self.count_airframes_in_conf()
self.find_conf_files()
self.count_airframes_in_conf(self.conf_file_combo, self.conf_airframes)
self.find_conf_files(self.conf_file_combo)
self.print_status("Deleted: " + filename)
def delete_controlpanel(self, widget):
@@ -208,8 +218,8 @@ class ConfChooser(object):
os.remove(self.conf_xml)
os.symlink(selected, self.conf_xml)
self.update_conf_label()
self.count_airframes_in_conf()
self.find_conf_files()
self.count_airframes_in_conf(self.conf_file_combo, self.conf_airframes)
self.find_conf_files(self.conf_file_combo)
selected = self.controlpanel_file_combo.get_active_text()
if selected == "control_panel.xml":
@@ -232,8 +242,8 @@ class ConfChooser(object):
os.remove(self.conf_xml)
os.symlink(self.conf_personal_name, self.conf_xml)
self.update_conf_label()
self.count_airframes_in_conf()
self.find_conf_files()
self.count_airframes_in_conf(self.conf_file_combo, self.conf_airframes)
self.find_conf_files(self.conf_file_combo)
def personal_controlpanel(self, widget):
if os.path.exists(self.controlpanel_personal):
@@ -250,11 +260,94 @@ class ConfChooser(object):
def print_status(self, text):
self.statusbar.push(self.context_id, text)
def changed_cb(self, entry):
self.count_airframes_in_conf()
def changed_cb(self, widget, data):
self.count_airframes_in_conf(data["combo"], data["list"])
def maintenance_window(self, widget):
mtn_window = gtk.Window()
mtn_window.set_position(gtk.WIN_POS_CENTER)
mtn_window.set_size_request(750, 300)
mtn_window.set_title("Maintenance Tools")
mnt_vbox = gtk.VBox()
mnt_conf_label = gtk.Label("Conf:")
mnt_conf_label.set_size_request(100, 30)
mnt_conf_file_combo = gtk.combo_box_new_text()
self.find_conf_files(mnt_conf_file_combo)
mnt_conf_file_combo.set_size_request(500, 30)
mnt_conf_airframes = gtk.Label("")
self.count_airframes_in_conf(mnt_conf_file_combo, mnt_conf_airframes)
mnt_conf_airframes.set_size_request(650, 180)
mnt_conf_airframes.set_line_wrap(True)
combo_list = {"combo": mnt_conf_file_combo, "list": mnt_conf_airframes}
mnt_conf_file_combo.connect("changed", self.changed_cb, combo_list)
mnt_confbar = gtk.HBox()
mnt_confbar.pack_start(mnt_conf_label)
mnt_confbar.pack_start(mnt_conf_file_combo)
mnt_vbox.pack_start(mnt_confbar, False)
btnModule = gtk.Button("Module\nUsage")
btnModule.connect("clicked", self.module_usage, mnt_conf_file_combo)
btnModule.set_tooltip_text("More information on the modules used by these airframes")
mnt_caexbar = gtk.HBox()
mnt_caexbar.pack_start(mnt_conf_airframes)
mnt_caexbar.pack_start(btnModule)
mnt_vbox.pack_start(mnt_caexbar)
separator = gtk.HSeparator()
mnt_vbox.pack_start(separator)
cbtnAirframes = gtk.CheckButton()
cbtnAirframes.set_label("Airframes")
cbtnAirframes.set_active(True)
cbtnFlightplans = gtk.CheckButton()
cbtnFlightplans.set_label("Flight plans")
cbtnFlightplans.set_active(True)
cbtnBoards = gtk.CheckButton()
cbtnBoards.set_label("Boards")
cbtnBoards.set_active(True)
cbtnModules = gtk.CheckButton()
cbtnModules.set_label("Modules")
cbtnModules.set_active(False)
selectedOptions = {"Airframes": cbtnAirframes, "Flightplans": cbtnFlightplans,
"Boards": cbtnBoards, "Modules": cbtnModules}
btnUntested = gtk.Button(None, "Show Untested Files")
btnUntested.connect("clicked", self.show_untested, selectedOptions)
btnUntested.set_tooltip_text("For the selected options show the files not tested by any conf")
untestedHBox = gtk.HBox()
cbtnVBox = gtk.VBox()
cbRowUpper = gtk.HBox()
cbRowLower = gtk.HBox()
cbRowUpper.pack_start(cbtnAirframes)
cbRowUpper.pack_start(cbtnBoards)
cbRowLower.pack_start(cbtnFlightplans)
cbRowLower.pack_start(cbtnModules)
cbtnVBox.pack_start(cbRowUpper)
cbtnVBox.pack_start(cbRowLower)
untestedHBox.pack_start(cbtnVBox)
untestedHBox.pack_start(btnUntested)
mnt_vbox.pack_start(untestedHBox)
mtn_window.add(mnt_vbox)
mtn_window.show_all()
# Constructor Functions
def __init__(self):
self.obj = PaparazziOverview(0)
# paparazzi process
self.pp = None
@@ -311,8 +404,7 @@ class ConfChooser(object):
self.conf_label.set_size_request(100, 30)
self.conf_file_combo = gtk.combo_box_new_text()
self.find_conf_files()
self.conf_file_combo.connect("changed", self.changed_cb)
self.find_conf_files(self.conf_file_combo)
self.conf_file_combo.set_size_request(550, 30)
self.btnDeleteConf = gtk.Button(None, gtk.STOCK_DELETE)
@@ -344,17 +436,27 @@ class ConfChooser(object):
# Count Airframes
self.conf_airframes = gtk.Label("")
self.count_airframes_in_conf()
self.conf_airframes.set_size_request(650,180)
self.count_airframes_in_conf(self.conf_file_combo, self.conf_airframes)
self.conf_airframes.set_size_request(650, 180)
self.conf_airframes.set_line_wrap(True)
self.combo_list = {"combo": self.conf_file_combo, "list": self.conf_airframes}
self.conf_file_combo.connect("changed", self.changed_cb, self.combo_list)
self.btnInfo = gtk.Button(None, "More\nInfo")
self.btnInfo.connect("clicked", self.more_info)
self.btnInfo.set_tooltip_text("More information on airframe files")
self.btnMaintenance = gtk.Button(None, "Maintenance\n\tTools")
self.btnMaintenance.connect("clicked", self.maintenance_window)
self.btnMaintenance.set_tooltip_text("Show maintenance tools")
self.caexbar = gtk.HBox()
self.caexbar.pack_start(self.conf_airframes)
self.caexbar.pack_start(self.btnInfo)
self.caexbar_btns = gtk.VBox()
self.caexbar.pack_start(self.caexbar_btns)
self.caexbar_btns.pack_start(self.btnInfo)
self.caexbar_btns.pack_start(self.btnMaintenance)
self.my_vbox.pack_start(self.caexbar, False)
+2 -1
View File
@@ -14,7 +14,8 @@ import lxml.etree as ET
# if PAPARAZZI_HOME not set, then assume the tree containing this
# file is a reasonable substitute
PAPARAZZI_HOME = getenv("PAPARAZZI_HOME", path.normpath(path.join(path.dirname(path.abspath(__file__)), '../../../')))
PAPARAZZI_SRC = getenv("PAPARAZZI_HOME", path.normpath(path.join(path.dirname(path.abspath(__file__)), '../../../')))
PAPARAZZI_HOME = getenv("PAPARAZZI_HOME", PAPARAZZI_SRC)
# Directories
conf_dir = path.join(PAPARAZZI_HOME, "conf/")
File diff suppressed because it is too large Load Diff