mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-10 06:59:54 +08:00
Improvement to start.py maintenance tools (#2438)
* 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 * Added functionality to generate module overview by board name * Module overview table now also displays the xml file and of the airframe * Update health_monitor_update branch with master changes * Bug-fixes and added description to maintenance tools
This commit is contained in:
committed by
Gautier Hattenberger
parent
208c37bc98
commit
8c145b7e49
@@ -21,6 +21,7 @@ from paparazzi_health import PaparazziOverview
|
||||
|
||||
import xml.etree.ElementTree
|
||||
|
||||
|
||||
class ConfChooser(object):
|
||||
|
||||
# General Functions
|
||||
@@ -29,10 +30,11 @@ class ConfChooser(object):
|
||||
combo.set_sensitive(False)
|
||||
combo.get_model().clear()
|
||||
current_index = 0
|
||||
combo.append_text("------None Selected------")
|
||||
for (i, text) in enumerate(clist):
|
||||
combo.append_text(text)
|
||||
if os.path.join(paparazzi.conf_dir, text) == os.path.realpath(active):
|
||||
current_index = i
|
||||
if active is not None and os.path.join(paparazzi.conf_dir, text) == os.path.realpath(active):
|
||||
current_index = i + 1 # Add one due to ---None Selected---
|
||||
combo.set_active(current_index)
|
||||
combo.set_sensitive(True)
|
||||
|
||||
@@ -70,6 +72,10 @@ class ConfChooser(object):
|
||||
conf_files = paparazzi.get_list_of_conf_files(self.exclude_backups)
|
||||
self.update_combo(combo, conf_files, self.conf_xml)
|
||||
|
||||
def find_board_files(self, combo):
|
||||
board_files = paparazzi.get_list_of_boards()
|
||||
self.update_combo(combo, board_files, None)
|
||||
|
||||
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)
|
||||
@@ -135,8 +141,10 @@ class ConfChooser(object):
|
||||
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)
|
||||
if data["Conf"].get_active() is not 0:
|
||||
self.obj.airframe_module_overview(data["Conf"].get_active_text())
|
||||
elif data["Board"].get_active() is not 0:
|
||||
self.obj.airframe_module_overview(data["Board"].get_active_text() + ".makefile")
|
||||
|
||||
def launch(self, widget):
|
||||
self.accept(widget)
|
||||
@@ -263,20 +271,39 @@ class ConfChooser(object):
|
||||
def changed_cb(self, widget, data):
|
||||
self.count_airframes_in_conf(data["combo"], data["list"])
|
||||
|
||||
@staticmethod
|
||||
def deactivate_cb(widget, combo):
|
||||
current_selection = widget.get_active()
|
||||
combo.set_active(0)
|
||||
widget.set_active(current_selection)
|
||||
|
||||
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_size_request(750, 360)
|
||||
mtn_window.set_title("Maintenance Tools")
|
||||
|
||||
mnt_vbox = gtk.VBox()
|
||||
|
||||
mnt_desc_label = gtk.Label("")
|
||||
desc_text = "Show module usage of all airframes in a selected conf file <b>or</b> all airframes " \
|
||||
"with a specific board across all conf files."
|
||||
mnt_desc_label.set_markup(desc_text)
|
||||
mnt_desc_label.set_size_request(720, 40)
|
||||
mnt_desc_label.set_line_wrap(True)
|
||||
|
||||
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_board_label = gtk.Label("Board:")
|
||||
mnt_board_label.set_size_request(100, 30)
|
||||
mnt_board_file_combo = gtk.combo_box_new_text()
|
||||
self.find_board_files(mnt_board_file_combo)
|
||||
mnt_board_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)
|
||||
@@ -284,14 +311,24 @@ class ConfChooser(object):
|
||||
|
||||
combo_list = {"combo": mnt_conf_file_combo, "list": mnt_conf_airframes}
|
||||
mnt_conf_file_combo.connect("changed", self.changed_cb, combo_list)
|
||||
mnt_conf_file_combo.connect("changed", self.deactivate_cb, mnt_board_file_combo)
|
||||
|
||||
mnt_board_file_combo.connect("changed", self.deactivate_cb, mnt_conf_file_combo)
|
||||
|
||||
mnt_combos = {"Conf": mnt_conf_file_combo, "Board": mnt_board_file_combo}
|
||||
|
||||
mnt_confbar = gtk.HBox()
|
||||
mnt_confbar.pack_start(mnt_conf_label)
|
||||
mnt_confbar.pack_start(mnt_conf_file_combo)
|
||||
mnt_boardbar = gtk.HBox()
|
||||
mnt_boardbar.pack_start(mnt_board_label)
|
||||
mnt_boardbar.pack_start(mnt_board_file_combo)
|
||||
mnt_vbox.pack_start(mnt_desc_label)
|
||||
mnt_vbox.pack_start(mnt_confbar, False)
|
||||
mnt_vbox.pack_start(mnt_boardbar, False)
|
||||
|
||||
btnModule = gtk.Button("Module\nUsage")
|
||||
btnModule.connect("clicked", self.module_usage, mnt_conf_file_combo)
|
||||
btnModule.connect("clicked", self.module_usage, mnt_combos)
|
||||
btnModule.set_tooltip_text("More information on the modules used by these airframes")
|
||||
|
||||
mnt_caexbar = gtk.HBox()
|
||||
|
||||
@@ -8,6 +8,7 @@ import datetime
|
||||
from fnmatch import fnmatch
|
||||
import re
|
||||
import numpy as np
|
||||
from functools import wraps
|
||||
from collections import Counter
|
||||
import paparazzi
|
||||
import xml.etree.ElementTree
|
||||
@@ -17,6 +18,34 @@ import subprocess
|
||||
PIPE = subprocess.PIPE
|
||||
|
||||
|
||||
def conf_board_decorator(module_overview_func):
|
||||
"""
|
||||
This decorator extends the function PaparazziOverview.airframe_module_overview to generate the html
|
||||
table either for airframes in a conf file or all airframes with a specific board
|
||||
"""
|
||||
@wraps(module_overview_func)
|
||||
def wrapper(self, selected_file):
|
||||
|
||||
if selected_file[-3:] == "xml":
|
||||
airframes = self.list_airframes_in_conf(selected_file)
|
||||
module_overview_func(self, iter(airframes))
|
||||
elif selected_file[-8:] == "makefile":
|
||||
board = selected_file[:-9]
|
||||
conf_files = iter(paparazzi.get_list_of_conf_files())
|
||||
airframes = []
|
||||
for conf in conf_files:
|
||||
afs_in_conf = iter(self.list_airframes_in_conf(conf))
|
||||
for af in afs_in_conf:
|
||||
ac = self.airframe_details(af.xml)
|
||||
if board in ac.boards:
|
||||
airframes.append(af)
|
||||
module_overview_func(self, iter(airframes))
|
||||
else:
|
||||
raise ValueError("selected file is neither a conf.xml or board.makefile")
|
||||
|
||||
return wrapper
|
||||
|
||||
|
||||
class Airframe:
|
||||
name = ""
|
||||
ac_id = ""
|
||||
@@ -318,19 +347,25 @@ class PaparazziOverview(object):
|
||||
|
||||
def generate_sorted_list(self, lst):
|
||||
commit_dates = [re.sub(r"( \n)$", "", self.get_last_commit_date(paparazzi.conf_dir + elm)) for elm in lst]
|
||||
file_date_lst = sorted(zip(lst, commit_dates), key=lambda x: datetime.datetime.strptime(x[1], '%d-%m-%Y'),
|
||||
untracked_zip = []
|
||||
tracked_zip = []
|
||||
for z in zip(lst, commit_dates):
|
||||
if z[1] != "00-00-0000":
|
||||
tracked_zip.append(z)
|
||||
else:
|
||||
untracked_zip.append((z[0], "Untracked file"))
|
||||
file_date_lst = untracked_zip + sorted(tracked_zip, key=lambda x: datetime.datetime.strptime(x[1], '%d-%m-%Y'),
|
||||
reverse=True)
|
||||
return file_date_lst
|
||||
|
||||
def airframe_module_overview(self, selected_conf):
|
||||
@conf_board_decorator
|
||||
def airframe_module_overview(self, airframes):
|
||||
"""
|
||||
Creates a nested dictionary of the airframe names and the modules they use to generate an html table
|
||||
that provides an overview of module usage of the airframes of interest
|
||||
|
||||
:param selected_conf: str of the name of conf file
|
||||
:param airframes: list or iterator of airframes to be analyzed
|
||||
"""
|
||||
# Looks at airframes in selected conf (not the currently active conf)
|
||||
airframes = self.list_airframes_in_conf(selected_conf)
|
||||
|
||||
# Structure of nested dictionary: {af name: {module name: module type}}
|
||||
afs_mods = {}
|
||||
@@ -350,14 +385,16 @@ class PaparazziOverview(object):
|
||||
del unique_mods_ctr['xml']
|
||||
|
||||
# Table initialization, airframe names are ordered alphabetically, module names by most used
|
||||
ac_mod_table = np.zeros((len(afs_mods.keys()) + 1, len(unique_mods_ctr.keys()) + 1), dtype=object)
|
||||
ac_mod_table = np.zeros((len(afs_mods.keys()) + 1, len(unique_mods_ctr.keys()) + 2), dtype=object)
|
||||
ac_mod_table[0, 0] = "Name \\ Modules"
|
||||
ac_mod_table[0, 1] = "XML File"
|
||||
ac_mod_table[1:, 0] = sorted(afs_mods.keys(), key=lambda s: s.lower())
|
||||
ac_mod_table[0, 1:] = [i for i, _ in unique_mods_ctr.most_common()]
|
||||
ac_mod_table[0, 2:] = [i for i, _ in unique_mods_ctr.most_common()]
|
||||
|
||||
for i in range(1, len(ac_mod_table[:, 0])):
|
||||
for j in range(1, len(ac_mod_table[0, :])):
|
||||
ac_name = ac_mod_table[i, 0]
|
||||
ac_name = ac_mod_table[i, 0]
|
||||
ac_mod_table[i, 1] = afs_mods[ac_name]["xml"][0]
|
||||
for j in range(2, len(ac_mod_table[0, :])):
|
||||
module_name = ac_mod_table[0, j]
|
||||
if ac_mod_table[0, j] not in afs_mods[ac_name]:
|
||||
ac_mod_table[i, j] = "\\"
|
||||
|
||||
Reference in New Issue
Block a user