#!/usr/bin/env python2 import yum from gi.repository import Gtk class YumDB: def __init__(self): self.yb = yum.YumBase() self.yb.conf def get_reasons(self, patterns=None): reasons = [] for pkg in sorted(self.yb.rpmdb.returnPackages(patterns=patterns)): reasons.append({'nevra': pkg.nevra, \ 'group_member': pkg.yumdb_info.group_member \ if hasattr(pkg.yumdb_info, 'group_member') else '', \ 'reason': pkg.yumdb_info.reason \ if hasattr(pkg.yumdb_info, 'reason') else '<unset>', \ 'reason_editor': pkg.yumdb_info.reason_editor \ if hasattr(pkg.yumdb_info, 'reason_editor') else ''}) return reasons def get_summary(self, nevra): return self.yb.rpmdb.returnPackages(patterns=[ nevra ])[0].summary def get_description(self, nevra): return self.yb.rpmdb.returnPackages(patterns=[ nevra ])[0].description def set_reason(self, nevra, value): try: pkg = self.yb.rpmdb.returnPackages(patterns=[ nevra ])[0] except IndexError as e: return '{} does not exists!'.format(nevra) try: pkg.yumdb_info.reason = value pkg.yumdb_info.reason_editor = 'modified' except Exception as e: return '{} fails: {}'.format(nevra, e[1]) return True class PkgList(Gtk.TreeView): def add_column(self, name, index): renderer = Gtk.CellRendererText() column = Gtk.TreeViewColumn(name) column.pack_start(renderer, True) column.add_attribute(renderer, 'text', index) column.set_resizable(True) column.set_sort_column_id(index) column.set_sort_indicator(index) self.append_column(column) class ReasonEditor(Gtk.Window): COLUMN_NUMBER = 0 COLUMN_NEVRA = 1 COLUMN_GROUP = 2 COLUMN_REASON = 3 COLUMN_STATUS = 4 def __init__(self): Gtk.Window.__init__(self, title='YumDB Reason Editor') self.set_default_size(800, 600) self.vbox = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, spacing=5) self.pkg_store = Gtk.ListStore(int, str, str, str, str) self.pkg_list = PkgList(self.pkg_store) self.pkg_list.add_column('#', 0) self.pkg_list.add_column('Name-Version-Arch', 1) self.pkg_list.add_column('Group', 2) self.pkg_list.add_column('Reason', 3) self.pkg_list.add_column('Status', 4) self.pkg_list.set_enable_search(False) self.pkg_list.set_search_column(self.COLUMN_NEVRA) self.pkg_list.connect('row-activated', self.toggle_reason) self.pkg_scrollable = Gtk.ScrolledWindow() self.pkg_scrollable.add(self.pkg_list) self.count_label = Gtk.Label() self.bottom_buttons = Gtk.Box() self.reload_db = Gtk.Button.new_with_mnemonic(label='_Reload YumDB') self.reload_db.connect('clicked', self.load_database) self.show_info = Gtk.Button.new_with_mnemonic(label='_Info') self.show_info.connect('clicked', self.show_summary_description) self.enable_search = Gtk.ToggleButton('_Search Disabled') self.enable_search.connect('toggled', self.toggle_search) self.enable_search.set_use_underline(True) self.bottom_buttons.pack_start(self.reload_db, True, True, 0) self.bottom_buttons.pack_start(self.show_info, True, True, 0) self.bottom_buttons.pack_start(self.enable_search, True, True, 0) self.vbox.pack_start(self.pkg_scrollable, True, True, 0) self.vbox.pack_start(self.count_label, False, False, 0) self.vbox.pack_start(self.bottom_buttons, False, False, 0) self.add(self.vbox) self.show_all() self.load_database() def load_database(self, unused=None): self.yumdb = YumDB() self.pkg_store.clear() print('Loading database ...') data = self.yumdb.get_reasons() print('Adding entries ...') self.dep_count = 0 self.user_count = 0 for index, entry in enumerate(data): self.pkg_store.append([ index + 1, entry['nevra'], entry['group_member'], entry['reason'], entry['reason_editor'] ]) if entry['reason'] == 'dep': self.dep_count += 1 else: self.user_count += 1 self.pkg_count = index + 1 self.update_count() self.show_all() def update_count(self): self.count_label.set_label('{} dep, {} user, {} pkgs'.format( self.dep_count, self.user_count, self.pkg_count)) def toggle_search(self, unused=None): if self.enable_search.get_active(): self.enable_search.set_label('_Search Enabled') self.pkg_list.set_enable_search(True) else: self.enable_search.set_label('_Search Disabled') self.pkg_list.set_enable_search(False) def toggle_reason(self, path, column, unused=None): model = self.pkg_list.get_model() tree_path = self.pkg_list.get_cursor()[0] if tree_path == None: return tree_iter = model.get_iter(tree_path) if tree_iter == None: return nevra = model[tree_iter][self.COLUMN_NEVRA] is_dep = model[tree_iter][self.COLUMN_REASON] == 'dep' result = self.yumdb.set_reason(nevra, 'user' if is_dep else 'dep') if result != True: error_dialog = Gtk.MessageDialog( title='YumDB Error', buttons=Gtk.ButtonsType.CLOSE, message_type=Gtk.MessageType.ERROR, message_format=result) error_dialog.run() error_dialog.destroy() return new_entry = self.yumdb.get_reasons([ nevra ])[0] model[tree_iter][self.COLUMN_REASON] = new_entry['reason'] model[tree_iter][self.COLUMN_STATUS] = new_entry['reason_editor'] tree_path.next() self.pkg_list.set_cursor(tree_path) if is_dep: self.dep_count -= 1 self.user_count += 1 else: self.dep_count += 1 self.user_count -= 1 self.update_count() def show_summary_description(self, unused=None): model, tree_iter = self.pkg_list.get_selection().get_selected() if tree_iter == None: return nevra = model[tree_iter][1] dialog = Gtk.MessageDialog( title=nevra, buttons=Gtk.ButtonsType.CLOSE, message_type=Gtk.MessageType.INFO, message_format=None) dialog.set_markup('<big><b>{}</b></big>\n\n{}'.format( self.yumdb.get_summary(nevra), self.yumdb.get_description(nevra))) dialog.run() dialog.destroy() if __name__ == '__main__': editor = ReasonEditor() editor.connect('delete-event', Gtk.main_quit) Gtk.main()