report-xfstests: Split out the test chooser into a new file
And add support for tests against tagged kernels Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
This commit is contained in:
parent
51f50a54b4
commit
f1b6f42009
|
@ -0,0 +1,2 @@
|
||||||
|
__pycache__
|
||||||
|
*.pyc
|
|
@ -4,6 +4,7 @@ gi.require_version("Gtk", "4.0")
|
||||||
|
|
||||||
import bisect
|
import bisect
|
||||||
import pathlib
|
import pathlib
|
||||||
|
import reporter
|
||||||
import re
|
import re
|
||||||
import sys
|
import sys
|
||||||
import xdg.BaseDirectory
|
import xdg.BaseDirectory
|
||||||
|
@ -14,104 +15,6 @@ from gi.repository import Gio
|
||||||
|
|
||||||
XFSTESTS = pathlib.Path(xdg.BaseDirectory.xdg_data_home) / "xfstests" / "date"
|
XFSTESTS = pathlib.Path(xdg.BaseDirectory.xdg_data_home) / "xfstests" / "date"
|
||||||
|
|
||||||
class Calendar(Gtk.Calendar):
|
|
||||||
def __init__(self):
|
|
||||||
Gtk.Calendar.__init__(self, show_day_names=True)
|
|
||||||
self.connect("next-month", self.view_changed)
|
|
||||||
self.connect("next-year", self.view_changed)
|
|
||||||
self.connect("prev-month", self.view_changed)
|
|
||||||
self.connect("prev-year", self.view_changed)
|
|
||||||
self.view_changed(self)
|
|
||||||
|
|
||||||
def get_month_directory(self):
|
|
||||||
date = self.get_date()
|
|
||||||
month = XFSTESTS / f"{date.get_year():04}" / f"{date.get_month():02}"
|
|
||||||
return month if month.is_dir() else None
|
|
||||||
|
|
||||||
def get_selected_day(self):
|
|
||||||
if month := self.get_month_directory():
|
|
||||||
day = month / f"{self.get_date().get_day_of_month():02}"
|
|
||||||
return day if day.is_dir() else None
|
|
||||||
|
|
||||||
def view_changed(self, calendar):
|
|
||||||
self.clear_marks()
|
|
||||||
if month := self.get_month_directory():
|
|
||||||
for day in month.iterdir():
|
|
||||||
self.mark_day(int(day.stem))
|
|
||||||
self.emit("day-selected")
|
|
||||||
|
|
||||||
|
|
||||||
class ServerRow(Gtk.TreeExpander):
|
|
||||||
def __init__(self):
|
|
||||||
Gtk.TreeExpander.__init__(self)
|
|
||||||
self.set_child(Gtk.Label(xalign=0))
|
|
||||||
self.get_child().set_state_flags(Gtk.StateFlags.CHECKED, False)
|
|
||||||
|
|
||||||
def set_item(self, item):
|
|
||||||
self.set_list_row(item)
|
|
||||||
self.get_child().set_text(item.get_item().get_name() if item else "")
|
|
||||||
|
|
||||||
|
|
||||||
class ServerSorter(Gtk.Sorter):
|
|
||||||
def do_compare(self, a, b):
|
|
||||||
if a.get_name() < b.get_name():
|
|
||||||
return Gtk.Ordering.SMALLER
|
|
||||||
elif a.get_name() > b.get_name():
|
|
||||||
return Gtk.Ordering.LARGER
|
|
||||||
return Gtk.Ordering.EQUAL
|
|
||||||
|
|
||||||
|
|
||||||
class ServerWindow(Gtk.ScrolledWindow):
|
|
||||||
def __init__(self):
|
|
||||||
Gtk.ScrolledWindow.__init__(self, vexpand=True, hscrollbar_policy=Gtk.PolicyType.NEVER)
|
|
||||||
self.servers = Gtk.TreeListModel.new(Gtk.DirectoryList(), False, True, self.create_func)
|
|
||||||
self.sorter = Gtk.TreeListRowSorter.new(ServerSorter())
|
|
||||||
self.sorted = Gtk.SortListModel.new(self.servers, self.sorter)
|
|
||||||
self.selection = Gtk.SingleSelection.new(self.sorted)
|
|
||||||
self.factory = Gtk.SignalListItemFactory()
|
|
||||||
self.view = Gtk.ListView.new(self.selection, self.factory)
|
|
||||||
|
|
||||||
self.selection.set_autoselect(False)
|
|
||||||
|
|
||||||
self.factory.connect("setup", self.setup)
|
|
||||||
self.factory.connect("bind", self.bind)
|
|
||||||
self.factory.connect("unbind", self.unbind)
|
|
||||||
self.factory.connect("teardown", self.teardown)
|
|
||||||
self.selection.connect("selection-changed", self.selection_changed)
|
|
||||||
self.set_child(self.view)
|
|
||||||
|
|
||||||
def selection_changed(self, selection, position, n_items):
|
|
||||||
treeitem = self.selection.get_selected_item()
|
|
||||||
file = treeitem.get_item().get_attribute_object("standard::file")
|
|
||||||
self.emit("test-changed", file if treeitem.get_depth() > 0 else None)
|
|
||||||
|
|
||||||
def setup(self, factory, listitem):
|
|
||||||
listitem.set_child(ServerRow())
|
|
||||||
|
|
||||||
def bind(self, factory, listitem):
|
|
||||||
listitem.get_child().set_item(listitem.get_item())
|
|
||||||
listitem.set_selectable(listitem.get_item().get_depth() > 0)
|
|
||||||
|
|
||||||
def unbind(self, factory, listitem):
|
|
||||||
listitem.get_child().set_item(None)
|
|
||||||
|
|
||||||
def teardown(self, factory, listitem):
|
|
||||||
listitem.set_child(None)
|
|
||||||
|
|
||||||
def create_func(self, item):
|
|
||||||
file = item.get_attribute_object("standard::file")
|
|
||||||
root = pathlib.Path(self.servers.get_model().get_file().get_path())
|
|
||||||
if pathlib.Path(file.get_path()).parent == root:
|
|
||||||
return Gtk.DirectoryList.new(file=file)
|
|
||||||
|
|
||||||
def set_day(self, day):
|
|
||||||
file = Gio.File.new_for_path(str(day)) if day else None
|
|
||||||
self.servers.get_model().set_file(file)
|
|
||||||
|
|
||||||
@GObject.Signal(arg_types=(Gio.File,))
|
|
||||||
def test_changed(self, file): pass
|
|
||||||
|
|
||||||
|
|
||||||
class TestProperty():
|
class TestProperty():
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
|
@ -215,7 +118,7 @@ class TestResultsModel(GObject.GObject, Gio.ListModel):
|
||||||
self.properties.clear()
|
self.properties.clear()
|
||||||
self.tests.clear()
|
self.tests.clear()
|
||||||
|
|
||||||
for file in sorted(path.iterdir()):
|
for file in sorted(path.iterdir() if path else []):
|
||||||
self.columns.append(file.stem)
|
self.columns.append(file.stem)
|
||||||
root = xml.etree.ElementTree.parse(file).getroot()
|
root = xml.etree.ElementTree.parse(file).getroot()
|
||||||
for prop in root.attrib.keys():
|
for prop in root.attrib.keys():
|
||||||
|
@ -354,8 +257,7 @@ class TestWindow(Gtk.ScrolledWindow):
|
||||||
class Window(Gtk.Window):
|
class Window(Gtk.Window):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
Gtk.Window.__init__(self, title="Xfstests Results")
|
Gtk.Window.__init__(self, title="Xfstests Results")
|
||||||
self.calendar = Calendar()
|
self.chooser = reporter.TestChooser()
|
||||||
self.servers = ServerWindow()
|
|
||||||
self.passing = Gtk.Switch(halign=Gtk.Align.CENTER, active=True)
|
self.passing = Gtk.Switch(halign=Gtk.Align.CENTER, active=True)
|
||||||
self.lpass = Gtk.Label.new("Show Passing Tests")
|
self.lpass = Gtk.Label.new("Show Passing Tests")
|
||||||
self.skipped = Gtk.Switch(halign=Gtk.Align.CENTER, active=True)
|
self.skipped = Gtk.Switch(halign=Gtk.Align.CENTER, active=True)
|
||||||
|
@ -363,15 +265,13 @@ class Window(Gtk.Window):
|
||||||
self.search = Gtk.SearchEntry(placeholder_text="Type To Filter Tests")
|
self.search = Gtk.SearchEntry(placeholder_text="Type To Filter Tests")
|
||||||
self.popover = FilterPopover(parent=self.search)
|
self.popover = FilterPopover(parent=self.search)
|
||||||
self.xfstests = TestWindow()
|
self.xfstests = TestWindow()
|
||||||
self.sz_group = Gtk.SizeGroup.new(Gtk.SizeGroupMode.VERTICAL)
|
|
||||||
|
|
||||||
self.left = Gtk.Grid(row_spacing=5)
|
self.left = Gtk.Grid(row_spacing=5)
|
||||||
self.left.attach(self.calendar, 0, 0, 2, 1)
|
self.left.attach(self.chooser, 0, 0, 2, 1)
|
||||||
self.left.attach(self.servers, 0, 1, 2, 1)
|
self.left.attach(self.passing, 0, 1, 1, 1)
|
||||||
self.left.attach(self.passing, 0, 2, 1, 1)
|
self.left.attach(self.lpass, 1, 1, 1, 1)
|
||||||
self.left.attach(self.lpass, 1, 2, 1, 1)
|
self.left.attach(self.skipped, 0, 2, 1, 1)
|
||||||
self.left.attach(self.skipped, 0, 3, 1, 1)
|
self.left.attach(self.lskip, 1, 2, 1, 1)
|
||||||
self.left.attach(self.lskip, 1, 3, 1, 1)
|
|
||||||
|
|
||||||
self.right = Gtk.Box.new(Gtk.Orientation.VERTICAL, 5)
|
self.right = Gtk.Box.new(Gtk.Orientation.VERTICAL, 5)
|
||||||
self.right.append(self.xfstests.notebook)
|
self.right.append(self.xfstests.notebook)
|
||||||
|
@ -382,26 +282,20 @@ class Window(Gtk.Window):
|
||||||
self.child.append(self.left)
|
self.child.append(self.left)
|
||||||
self.child.append(self.right)
|
self.child.append(self.right)
|
||||||
|
|
||||||
self.sz_group.add_widget(self.calendar)
|
reporter.common.SizeGroup.add_widget(self.xfstests.notebook)
|
||||||
self.sz_group.add_widget(self.xfstests.notebook)
|
|
||||||
|
|
||||||
self.lskip.set_xalign(0)
|
self.lskip.set_xalign(0)
|
||||||
self.lpass.set_xalign(0)
|
self.lpass.set_xalign(0)
|
||||||
self.set_default_size(1100, 750)
|
self.set_default_size(1100, 750)
|
||||||
self.set_child(self.child)
|
self.set_child(self.child)
|
||||||
|
|
||||||
self.calendar.connect("day-selected", self.date_changed)
|
self.chooser.connect("test-selected", self.test_changed)
|
||||||
self.servers.connect("test-changed", self.test_changed)
|
|
||||||
self.passing.connect("notify::active", self.show_passing)
|
self.passing.connect("notify::active", self.show_passing)
|
||||||
self.skipped.connect("notify::active", self.show_skipped)
|
self.skipped.connect("notify::active", self.show_skipped)
|
||||||
self.search.connect("search-changed", self.search_changed)
|
self.search.connect("search-changed", self.search_changed)
|
||||||
self.date_changed(self.calendar)
|
|
||||||
|
|
||||||
def date_changed(self, calendar):
|
|
||||||
self.servers.set_day(calendar.get_selected_day())
|
|
||||||
|
|
||||||
def test_changed(self, window, file):
|
def test_changed(self, window, file):
|
||||||
self.xfstests.set_tests(pathlib.Path(file.get_path()))
|
self.xfstests.set_tests(file.path if file else None)
|
||||||
|
|
||||||
def show_passing(self, passing, param):
|
def show_passing(self, passing, param):
|
||||||
self.xfstests.set_show_passing(passing.get_active())
|
self.xfstests.set_show_passing(passing.get_active())
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
from . import common
|
||||||
|
from . import testchooser
|
||||||
|
from gi.repository import GObject
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
class TestChooser(Gtk.Box):
|
||||||
|
def __init__(self):
|
||||||
|
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL)
|
||||||
|
self.stack = testchooser.Stack()
|
||||||
|
self.append(Gtk.StackSwitcher(stack=self.stack))
|
||||||
|
self.append(self.stack)
|
||||||
|
self.stack.connect("test-selected", self.on_test_selected)
|
||||||
|
|
||||||
|
def on_test_selected(self, stack, path):
|
||||||
|
self.emit("test-selected", path)
|
||||||
|
|
||||||
|
@GObject.Signal(arg_types=(testchooser.Path,))
|
||||||
|
def test_selected(self, path): pass
|
|
@ -0,0 +1,14 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
import gi
|
||||||
|
import pathlib
|
||||||
|
import xdg.BaseDirectory
|
||||||
|
|
||||||
|
gi.require_version("Gtk", "4.0")
|
||||||
|
from gi.repository import Gtk
|
||||||
|
|
||||||
|
|
||||||
|
XFSTESTS_BASE = pathlib.Path(xdg.BaseDirectory.xdg_data_home) / "xfstests"
|
||||||
|
XFSTESTS_DATE = XFSTESTS_BASE / "date"
|
||||||
|
XFSTESTS_TAGS = XFSTESTS_BASE / "tags"
|
||||||
|
|
||||||
|
SizeGroup = Gtk.SizeGroup.new(Gtk.SizeGroupMode.VERTICAL)
|
|
@ -0,0 +1,163 @@
|
||||||
|
#!/usr/bin/python
|
||||||
|
import pathlib
|
||||||
|
from . import common
|
||||||
|
from gi.repository import GObject
|
||||||
|
from gi.repository import Gtk
|
||||||
|
from gi.repository import Gio
|
||||||
|
|
||||||
|
|
||||||
|
class Path(GObject.GObject):
|
||||||
|
def __init__(self, path):
|
||||||
|
GObject.GObject.__init__(self)
|
||||||
|
self.path = path
|
||||||
|
|
||||||
|
def __lt__(self, rhs): return self.path < rhs.path
|
||||||
|
def get_is_test_result(self):
|
||||||
|
return False not in [ f.is_file() for f in self.path.iterdir() ]
|
||||||
|
def get_name(self): return self.path.name
|
||||||
|
def get_model(self):
|
||||||
|
if not self.get_is_test_result():
|
||||||
|
return DirectoryModel(self.path)
|
||||||
|
|
||||||
|
|
||||||
|
class DirectoryModel(GObject.GObject, Gio.ListModel):
|
||||||
|
def __init__(self, path=None):
|
||||||
|
GObject.GObject.__init__(self)
|
||||||
|
self.children = [ ]
|
||||||
|
self.set_path(path)
|
||||||
|
|
||||||
|
def do_get_item_type(self): return GObject.TYPE_PYOBJECT
|
||||||
|
def do_get_n_items(self): return len(self.children)
|
||||||
|
def do_get_item(self, n): return self.children[n]
|
||||||
|
|
||||||
|
def set_path(self, path):
|
||||||
|
rm = len(self.children)
|
||||||
|
self.children.clear()
|
||||||
|
self.path = path if path and path.is_dir() else None
|
||||||
|
if self.path:
|
||||||
|
self.children = sorted([ Path(c) for c in path.iterdir() ])
|
||||||
|
self.emit("items-changed", 0, rm, len(self.children))
|
||||||
|
|
||||||
|
|
||||||
|
class DirectoryWindow(Gtk.ScrolledWindow):
|
||||||
|
def __init__(self, path=None, autoexpand=True):
|
||||||
|
Gtk.ScrolledWindow.__init__(self, vexpand=True,
|
||||||
|
hscrollbar_policy=Gtk.PolicyType.NEVER)
|
||||||
|
self.dirtree = Gtk.TreeListModel.new(root=DirectoryModel(path),
|
||||||
|
passthrough=False,
|
||||||
|
autoexpand=autoexpand,
|
||||||
|
create_func=self.create_func)
|
||||||
|
self.selection = Gtk.SingleSelection.new(self.dirtree)
|
||||||
|
self.selection.set_autoselect(False)
|
||||||
|
self.selection.set_can_unselect(True)
|
||||||
|
self.selection.connect("selection-changed", self.selection_changed)
|
||||||
|
|
||||||
|
self.factory = Gtk.SignalListItemFactory()
|
||||||
|
self.factory.connect("setup", self.on_setup)
|
||||||
|
self.factory.connect("bind", self.on_bind)
|
||||||
|
self.factory.connect("unbind", self.on_unbind)
|
||||||
|
self.factory.connect("teardown", self.on_teardown)
|
||||||
|
|
||||||
|
self.listview = Gtk.ListView.new(self.selection, self.factory)
|
||||||
|
self.set_child(self.listview)
|
||||||
|
|
||||||
|
def create_func(self, path):
|
||||||
|
return path.get_model()
|
||||||
|
|
||||||
|
def on_setup(self, factory, listitem):
|
||||||
|
listitem.set_child(Gtk.TreeExpander(child=Gtk.Label(xalign=0)))
|
||||||
|
|
||||||
|
def on_bind(self, factory, listitem):
|
||||||
|
treerow = listitem.get_item()
|
||||||
|
filepath = treerow.get_item()
|
||||||
|
expander = listitem.get_child()
|
||||||
|
expander.set_list_row(treerow)
|
||||||
|
expander.get_child().set_text(filepath.get_name())
|
||||||
|
listitem.set_selectable(filepath.get_is_test_result())
|
||||||
|
|
||||||
|
def on_unbind(self, factory, listitem):
|
||||||
|
expander = listitem.get_child()
|
||||||
|
expander.set_list_row(None)
|
||||||
|
expander.get_child().set_text("")
|
||||||
|
|
||||||
|
def on_teardown(self, factory, treeitem):
|
||||||
|
treeitem.set_child(None)
|
||||||
|
|
||||||
|
def set_directory(self, path):
|
||||||
|
self.dirtree.get_model().set_path(path)
|
||||||
|
|
||||||
|
def selection_changed(self, selection, position, n_items):
|
||||||
|
treeitem = self.selection.get_selected_item()
|
||||||
|
self.emit("test-selected", treeitem.get_item() if treeitem else None)
|
||||||
|
|
||||||
|
def select_none(self):
|
||||||
|
self.selection.unselect_item(self.selection.get_selected())
|
||||||
|
|
||||||
|
@GObject.Signal(arg_types=(Path,))
|
||||||
|
def test_selected(self, filepath): pass
|
||||||
|
|
||||||
|
|
||||||
|
class Calendar(Gtk.Calendar):
|
||||||
|
def __init__(self):
|
||||||
|
Gtk.Calendar.__init__(self, show_day_names=True)
|
||||||
|
self.connect("next-month", self.view_changed)
|
||||||
|
self.connect("next-year", self.view_changed)
|
||||||
|
self.connect("prev-month", self.view_changed)
|
||||||
|
self.connect("prev-year", self.view_changed)
|
||||||
|
common.SizeGroup.add_widget(self)
|
||||||
|
self.view_changed(self)
|
||||||
|
|
||||||
|
def get_month_directory(self):
|
||||||
|
date = self.get_date()
|
||||||
|
month = common.XFSTESTS_DATE / f"{date.get_year():04}" / f"{date.get_month():02}"
|
||||||
|
return month if month.is_dir() else None
|
||||||
|
|
||||||
|
def get_selected_day(self):
|
||||||
|
if month := self.get_month_directory():
|
||||||
|
day = month / f"{self.get_date().get_day_of_month():02}"
|
||||||
|
return day if day.is_dir() else None
|
||||||
|
|
||||||
|
def view_changed(self, calendar):
|
||||||
|
self.clear_marks()
|
||||||
|
if month := self.get_month_directory():
|
||||||
|
for day in month.iterdir():
|
||||||
|
self.mark_day(int(day.stem))
|
||||||
|
self.emit("day-selected")
|
||||||
|
|
||||||
|
|
||||||
|
class DatePage(Gtk.Box):
|
||||||
|
def __init__(self):
|
||||||
|
Gtk.Box.__init__(self, orientation=Gtk.Orientation.VERTICAL, spacing=5)
|
||||||
|
self.calendar = Calendar()
|
||||||
|
self.dirwin = DirectoryWindow(self.calendar.get_selected_day())
|
||||||
|
self.append(self.calendar)
|
||||||
|
self.append(self.dirwin)
|
||||||
|
self.get_first_child().connect("day-selected", self.on_day_selected)
|
||||||
|
|
||||||
|
def on_day_selected(self, calendar):
|
||||||
|
self.dirwin.set_directory(self.calendar.get_selected_day())
|
||||||
|
|
||||||
|
def select_none(self):
|
||||||
|
self.dirwin.select_none()
|
||||||
|
|
||||||
|
|
||||||
|
class Stack(Gtk.Stack):
|
||||||
|
def __init__(self):
|
||||||
|
Gtk.Stack.__init__(self, transition_type=Gtk.StackTransitionType.OVER_LEFT_RIGHT)
|
||||||
|
self.date = DatePage()
|
||||||
|
self.tags = DirectoryWindow(common.XFSTESTS_TAGS, autoexpand=False)
|
||||||
|
self.add_titled(self.date, "Date", "Date")
|
||||||
|
self.add_titled(self.tags, "Tags", "Tags")
|
||||||
|
self.date.dirwin.connect("test-selected", self.on_test_selected)
|
||||||
|
self.tags.connect("test-selected", self.on_test_selected)
|
||||||
|
self.connect("notify::visible-child", self.on_page_changed)
|
||||||
|
|
||||||
|
def on_test_selected(self, widget, test):
|
||||||
|
self.emit("test-selected", test)
|
||||||
|
|
||||||
|
def on_page_changed(self, stack, param):
|
||||||
|
stack.get_visible_child().select_none()
|
||||||
|
self.emit("test-selected", None)
|
||||||
|
|
||||||
|
@GObject.Signal(arg_types=(Path,))
|
||||||
|
def test_selected(self, path): pass
|
Loading…
Reference in New Issue