From 156aa631839caa415acbd7187c145a23f3e77212 Mon Sep 17 00:00:00 2001 From: Aaron Franke Date: Sun, 27 Oct 2024 20:49:00 -0700 Subject: [PATCH] Format Python files with Ruff --- .../change_version_page.py | 20 ++-- .../change_version_worker.py | 15 +-- src/gtk/app_row.py | 5 +- src/gtk/attempt_install_dialog.py | 17 ++- src/gtk/error_toast.py | 4 +- src/gtk/installation_chooser.py | 7 +- src/gtk/loading_status.py | 3 +- src/gtk/sidebar_button.py | 1 + src/host_info.py | 106 ++++++++++-------- src/install_page/file_install_dialog.py | 1 + src/install_page/install_page.py | 5 +- src/install_page/pending_page.py | 8 +- src/install_page/result_row.py | 1 + src/install_page/results_page.py | 22 ++-- src/install_page/select_page.py | 15 ++- src/main.py | 20 +--- src/main_window/window.py | 1 + src/package_install_worker.py | 45 ++++---- src/packages_page/filters_page.py | 9 +- src/packages_page/packages_page.py | 28 +++-- src/packages_page/uninstall_dialog.py | 1 + src/properties_page/properties_page.py | 44 ++++---- src/remotes_page/add_remote_dialog.py | 10 +- src/remotes_page/remote_row.py | 12 +- src/remotes_page/remotes_page.py | 21 ++-- src/snapshot_page/new_snapshot_dialog.py | 3 +- src/snapshot_page/snapshot_box.py | 25 +++-- src/snapshot_page/snapshot_page.py | 31 +++-- src/snapshot_page/snapshots_list_page.py | 1 + src/snapshot_page/tar_worker.py | 45 ++++---- src/user_data_page/data_box.py | 10 +- src/user_data_page/data_subpage.py | 30 ++++- src/user_data_page/user_data_page.py | 9 +- 33 files changed, 324 insertions(+), 251 deletions(-) diff --git a/src/change_version_page/change_version_page.py b/src/change_version_page/change_version_page.py index a44324f..6f92158 100644 --- a/src/change_version_page/change_version_page.py +++ b/src/change_version_page/change_version_page.py @@ -1,13 +1,14 @@ -from gi.repository import Adw, Gtk,GLib, Gio +from gi.repository import Adw, Gtk, GLib, Gio from .error_toast import ErrorToast from .host_info import HostInfo from .loading_status import LoadingStatus from .change_version_worker import ChangeVersionWorker import subprocess + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/change_version_page/change_version_page.ui") class ChangeVersionPage(Adw.NavigationPage): - __gtype_name__ = 'ChangeVersionPage' + __gtype_name__ = "ChangeVersionPage" gtc = Gtk.Template.Child toast_overlay = gtc() scrolled_window = gtc() @@ -23,7 +24,7 @@ class ChangeVersionPage(Adw.NavigationPage): failure = None def get_commits(self, *args): - cmd = ['flatpak-spawn', '--host', 'sh', '-c'] + cmd = ["flatpak-spawn", "--host", "sh", "-c"] script = f"LC_ALL=C flatpak remote-info --log {self.package.info['origin']} {self.package.info['ref']} " installation = self.package.info["installation"] if installation == "user" or installation == "system": @@ -35,10 +36,10 @@ class ChangeVersionPage(Adw.NavigationPage): commits = [] changes = [] - dates = [] + dates = [] try: output = subprocess.run(cmd, check=True, capture_output=True, text=True).stdout - lines = output.strip().split('\n') + lines = output.strip().split("\n") for line in lines: line = line.strip().split(": ", 1) if len(line) < 2: @@ -62,7 +63,9 @@ class ChangeVersionPage(Adw.NavigationPage): def idle(*args): for index, commit in enumerate(commits): - row = Adw.ActionRow(title=GLib.markup_escape_text(changes[index]), subtitle=f"{GLib.markup_escape_text(commit)}\n{GLib.markup_escape_text(dates[index])}") + row = Adw.ActionRow( + title=GLib.markup_escape_text(changes[index]), subtitle=f"{GLib.markup_escape_text(commit)}\n{GLib.markup_escape_text(dates[index])}" + ) if commit == self.package.cli_info.get("commit", None): row.set_sensitive(False) row.add_prefix(Gtk.Image(icon_name="check-plain-symbolic", margin_start=5, margin_end=5)) @@ -90,7 +93,7 @@ class ChangeVersionPage(Adw.NavigationPage): def callback(self, did_error): HostInfo.main_window.refresh_handler() if not did_error: - HostInfo.main_window.toast_overlay.add_toast(Adw.Toast(title=_("Changed {}'s Version").format(self.package.info['name']))) + HostInfo.main_window.toast_overlay.add_toast(Adw.Toast(title=_("Changed {}'s Version").format(self.package.info["name"]))) def error_callback(self, user_facing_label, error_message): HostInfo.main_window.toast_overlay.add_toast(ErrorToast(user_facing_label, error_message).toast) @@ -98,7 +101,8 @@ class ChangeVersionPage(Adw.NavigationPage): def on_apply(self, *args): if ChangeVersionWorker.change_version( self.mask_row.get_active(), - self.package, self.selected_commit, + self.package, + self.selected_commit, self.packages_page.changing_version, self.callback, self.error_callback, diff --git a/src/change_version_page/change_version_worker.py b/src/change_version_page/change_version_worker.py index 839cd1a..cb95e25 100644 --- a/src/change_version_page/change_version_worker.py +++ b/src/change_version_page/change_version_worker.py @@ -2,6 +2,7 @@ from gi.repository import GLib, Gio from .host_info import HostInfo import subprocess, re + class ChangeVersionWorker: process = None callback = None @@ -23,9 +24,9 @@ class ChangeVersionWorker: @classmethod def change_version_thread(this, should_mask, package, commit): try: - cmd = ['flatpak-spawn', '--host', 'pkexec', 'sh', '-c'] + cmd = ["flatpak-spawn", "--host", "pkexec", "sh", "-c"] - installation = package.info['installation'] + installation = package.info["installation"] real_installation = "" if installation == "user" or installation == "system": real_installation = f"--{installation}" @@ -44,9 +45,9 @@ class ChangeVersionWorker: suffix += mask_cmd cmd.append(suffix) - this.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - percent_pattern = r'\d{1,3}%' - amount_pattern = r'(\d+)/(\d+)' + this.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + percent_pattern = r"\d{1,3}%" + amount_pattern = r"(\d+)/(\d+)" for line in this.process.stdout: line = line.strip() percent_match = re.search(percent_pattern, line) @@ -54,7 +55,7 @@ class ChangeVersionWorker: ratio = int(percent_match.group()[0:-1]) / 100.0 amount_match = re.search(amount_pattern, line) if amount_match: - amount = amount_match.group().split('/') + amount = amount_match.group().split("/") complete = int(amount[0]) - 1 total = int(amount[1]) this.update_status(ratio, complete, total) @@ -65,7 +66,7 @@ class ChangeVersionWorker: if error := this.process.communicate()[1].strip(): this.on_error(_("Error occurred while changing version"), error) - except subprocess.TimeoutExpired as te: + except subprocess.TimeoutExpired: this.process.terminate() this.on_error(_("Error occurred while changing version"), _("Failed to exit cleanly")) diff --git a/src/gtk/app_row.py b/src/gtk/app_row.py index 99d5d33..9cee05b 100644 --- a/src/gtk/app_row.py +++ b/src/gtk/app_row.py @@ -1,8 +1,9 @@ from gi.repository import Adw, Gtk, GLib + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/gtk/app_row.ui") class AppRow(Adw.ActionRow): - __gtype_name__ = 'AppRow' + __gtype_name__ = "AppRow" gtc = Gtk.Template.Child image = gtc() eol_package_package_status_icon = gtc() @@ -35,7 +36,7 @@ class AppRow(Adw.ActionRow): GLib.idle_add(lambda *_: self.idle_stuff()) self.add_controller(self.rclick_gesture) self.add_controller(self.long_press_gesture) - if package.info['id'] == "io.github.flattool.Warehouse": + if package.info["id"] == "io.github.flattool.Warehouse": self.check_button.set_active = lambda *_: None self.check_button.set_sensitive(False) diff --git a/src/gtk/attempt_install_dialog.py b/src/gtk/attempt_install_dialog.py index b997e11..45504e2 100644 --- a/src/gtk/attempt_install_dialog.py +++ b/src/gtk/attempt_install_dialog.py @@ -2,6 +2,7 @@ from gi.repository import Adw, Gtk from .host_info import HostInfo from .error_toast import ErrorToast + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/gtk/attempt_install_dialog.ui") class AttemptInstallDialog(Adw.AlertDialog): __gtype_name__ = "AttemptInstallDialog" @@ -46,12 +47,16 @@ class AttemptInstallDialog(Adw.AlertDialog): install_page = HostInfo.main_window.pages[HostInfo.main_window.install_row] HostInfo.main_window.activate_row(HostInfo.main_window.install_row) self.callback(True) - install_page.install_packages([{ - "remote": row.remote_name, - "installation": row.remote_installation, - "package_names": self.package_names, - "extra_flags": [], - }]) + install_page.install_packages( + [ + { + "remote": row.remote_name, + "installation": row.remote_installation, + "package_names": self.package_names, + "extra_flags": [], + } + ] + ) elif not self.callback is None: self.callback(False) diff --git a/src/gtk/error_toast.py b/src/gtk/error_toast.py index 378202f..a2581bb 100644 --- a/src/gtk/error_toast.py +++ b/src/gtk/error_toast.py @@ -1,7 +1,9 @@ from gi.repository import Adw, Gtk, Gdk, GLib + class ErrorToast: main_window = None + def __init__(self, display_msg, error_msg): def on_response(dialog, response_id): if response_id == "copy": @@ -17,7 +19,7 @@ class ErrorToast: print(error_msg) popup.add_response("copy", _("Copy")) popup.add_response("ok", _("OK")) - lb = Gtk.Label(selectable=True, wrap=True)#, natural_wrap_mode=Gtk.NaturalWrapMode.WORD) + lb = Gtk.Label(selectable=True, wrap=True) # , natural_wrap_mode=Gtk.NaturalWrapMode.WORD) lb.set_markup(f"{GLib.markup_escape_text(error_msg)}") # lb.set_label(error_msg) # lb.set_selectable(True) diff --git a/src/gtk/installation_chooser.py b/src/gtk/installation_chooser.py index fe26d18..54be3b1 100644 --- a/src/gtk/installation_chooser.py +++ b/src/gtk/installation_chooser.py @@ -1,9 +1,10 @@ from gi.repository import Adw, Gtk from .host_info import HostInfo + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/gtk/installation_chooser.ui") class InstallationChooser(Adw.PreferencesGroup): - __gtype_name__ = 'InstallationChooser' + __gtype_name__ = "InstallationChooser" gtc = Gtk.Template.Child user_row = gtc() @@ -20,7 +21,7 @@ class InstallationChooser(Adw.PreferencesGroup): if button.get_active(): return func() - return "" # Case for when no button is active (which shouldn't happen) + return "" # Case for when no button is active (which shouldn't happen) def set_content_strings(self, content_name, is_plural): if is_plural: @@ -36,7 +37,7 @@ class InstallationChooser(Adw.PreferencesGroup): super().__init__(**kwargs) self.check_buttons = { - self.user_check : lambda: "user", + self.user_check: lambda: "user", self.system_check: lambda: "system", self.single_check: self.single_row.get_title, self.choice_check: lambda: self.choice_row.get_selected_item().get_string(), diff --git a/src/gtk/loading_status.py b/src/gtk/loading_status.py index 2ac8a50..5936c32 100644 --- a/src/gtk/loading_status.py +++ b/src/gtk/loading_status.py @@ -1,8 +1,9 @@ from gi.repository import Gtk, GLib + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/gtk/loading_status.ui") class LoadingStatus(Gtk.ScrolledWindow): - __gtype_name__ = 'LoadingStatus' + __gtype_name__ = "LoadingStatus" gtc = Gtk.Template.Child title_label = gtc() diff --git a/src/gtk/sidebar_button.py b/src/gtk/sidebar_button.py index a829e80..a327592 100644 --- a/src/gtk/sidebar_button.py +++ b/src/gtk/sidebar_button.py @@ -1,6 +1,7 @@ from gi.repository import Gtk from .host_info import HostInfo + class SidebarButton(Gtk.Button): __gtype_name__ = "SidebarButton" diff --git a/src/host_info.py b/src/host_info.py index 4590f7b..f220d71 100644 --- a/src/host_info.py +++ b/src/host_info.py @@ -7,14 +7,16 @@ icon_theme = Gtk.IconTheme.new() icon_theme.add_search_path(f"{home}/.local/share/flatpak/exports/share/icons") direction = Gtk.Image().get_direction() + class Flatpak: def open_app(self, callback=None): self.failed_app_run = None + def thread(*args): if self.is_runtime: self.failed_app_run = "error: cannot open a runtime" try: - subprocess.run(['flatpak-spawn', '--host', 'flatpak', 'run', f"{self.info['ref']}"], capture_output=True, text=True, check=True) + subprocess.run(["flatpak-spawn", "--host", "flatpak", "run", f"{self.info['ref']}"], capture_output=True, text=True, check=True) except subprocess.CalledProcessError as cpe: self.failed_app_run = cpe except Exception as e: @@ -32,17 +34,20 @@ class Flatpak: def get_data_size(self, callback=None): size = [None] + def thread(*args): sed = "sed 's/K/ KB/; s/M/ MB/; s/G/ GB/; s/T/ TB/; s/P/ PB/;'" - size[0] = subprocess.run(['sh', '-c', f"du -sh {self.data_path} | {sed}"], capture_output=True, text=True).stdout.split("\t")[0] + size[0] = subprocess.run(["sh", "-c", f"du -sh {self.data_path} | {sed}"], capture_output=True, text=True).stdout.split("\t")[0] + def on_done(*arg): if callback: callback(f"~ {size[0]}") + Gio.Task.new(None, None, on_done).run_in_thread(thread) def trash_data(self, callback=None): try: - subprocess.run(['gio', 'trash', self.data_path], capture_output=True, text=True, check=True) + subprocess.run(["gio", "trash", self.data_path], capture_output=True, text=True, check=True) except subprocess.CalledProcessError as cpe: raise cpe except Exception as e: @@ -50,8 +55,9 @@ class Flatpak: def set_mask(self, should_mask, callback=None): self.failed_mask = None + def thread(*args): - cmd = ['flatpak-spawn', '--host', 'flatpak', 'mask', self.info["id"]] + cmd = ["flatpak-spawn", "--host", "flatpak", "mask", self.info["id"]] installation = self.info["installation"] if installation == "user" or installation == "system": cmd.append(f"--{installation}") @@ -77,7 +83,7 @@ class Flatpak: self.failed_pin = "Cannot pin an application" def thread(*args): - cmd = ['flatpak-spawn', '--host', 'flatpak', 'pin', f"runtime/{self.info['ref']}"] + cmd = ["flatpak-spawn", "--host", "flatpak", "pin", f"runtime/{self.info['ref']}"] installation = self.info["installation"] if installation == "user" or installation == "system": cmd.append(f"--{installation}") @@ -106,7 +112,7 @@ class Flatpak: def thread(*args): HostInfo.main_window.add_refresh_lockout("uninstalling packages") - cmd = ['flatpak-spawn', '--host', 'flatpak', 'uninstall', '-y', self.info["ref"]] + cmd = ["flatpak-spawn", "--host", "flatpak", "uninstall", "-y", self.info["ref"]] installation = self.info["installation"] if installation == "system" or installation == "user": cmd.append(f"--{installation}") @@ -136,10 +142,7 @@ class Flatpak: cmd += self.info["ref"] try: - output = subprocess.run( - ['flatpak-spawn', '--host', 'sh', '-c', cmd], - text=True, capture_output=True - ).stdout + output = subprocess.run(["flatpak-spawn", "--host", "sh", "-c", cmd], text=True, capture_output=True).stdout except Exception as e: raise e @@ -172,23 +175,23 @@ class Flatpak: def __init__(self, columns): self.info = { - "name": columns[0], - "id": columns[1], - "version": columns[2], - "branch": columns[3], - "arch": columns[4], - "origin": columns[5], - "installation": columns[6], - "ref": columns[7], + "name": columns[0], + "id": columns[1], + "version": columns[2], + "branch": columns[3], + "arch": columns[4], + "origin": columns[5], + "installation": columns[6], + "ref": columns[7], "installed_size": columns[8], - "options": columns[9], + "options": columns[9], } self.is_runtime = "runtime" in self.info["options"] self.data_path = f"{home}/.var/app/{self.info["id"]}" self.data_size = -1 self.cli_info = None installation = self.info["installation"] - if len(i := installation.split(' ')) > 1: + if len(i := installation.split(" ")) > 1: self.info["installation"] = i[1].replace("(", "").replace(")", "") else: self.info["installation"] = installation @@ -211,13 +214,7 @@ class Flatpak: self.is_pinned = False try: - self.icon_path = ( - icon_theme.lookup_icon( - self.info["id"], None, 512, 1, direction, 0 - ) - .get_file() - .get_path() - ) + self.icon_path = icon_theme.lookup_icon(self.info["id"], None, 512, 1, direction, 0).get_file().get_path() except GLib.GError as e: print(f"Minor error in looking up icon for {self.info['id']}", e) self.icon_path = None @@ -231,6 +228,7 @@ class Remote: if title == "" or title == "-": self.title = name + class HostInfo: home = home clipboard = Gdk.Display.get_default().get_clipboard() @@ -239,8 +237,7 @@ class HostInfo: # Get all possible installation icon theme dirs output = subprocess.run( - ['flatpak-spawn', '--host', - 'flatpak', '--installations'], + ["flatpak-spawn", "--host", "flatpak", "--installations"], text=True, capture_output=True, ).stdout @@ -256,6 +253,7 @@ class HostInfo: masks = {} pins = {} dependent_runtime_refs = [] + @classmethod def get_flatpaks(this, callback=None): # Callback is a function to run after the host flatpaks are found @@ -271,52 +269,62 @@ class HostInfo: def thread(task, *args): # Remotes def remote_info(installation): - cmd = ['flatpak-spawn', '--host', - 'flatpak', 'remotes', '--columns=name,title,options', '--show-disabled'] + cmd = ["flatpak-spawn", "--host", "flatpak", "remotes", "--columns=name,title,options", "--show-disabled"] if installation == "user" or installation == "system": cmd.append(f"--{installation}") else: cmd.append(f"--installation={installation}") output = subprocess.run( - cmd, text=True, + cmd, + text=True, capture_output=True, ).stdout lines = output.strip().split("\n") remote_list = [] - if lines[0] != '': + if lines[0] != "": for line in lines: line = line.split("\t") remote_list.append(Remote(name=line[0], title=line[1], disabled=(len(line) == 3) and "disabled" in line[2])) this.remotes[installation] = remote_list # Masks - cmd = ['flatpak-spawn', '--host', - 'flatpak', 'mask',] + cmd = [ + "flatpak-spawn", + "--host", + "flatpak", + "mask", + ] if installation == "user" or installation == "system": cmd.append(f"--{installation}") else: cmd.append(f"--installation={installation}") output = subprocess.run( - cmd, text=True, + cmd, + text=True, capture_output=True, ).stdout lines = output.strip().replace(" ", "").split("\n") - if lines[0] != '': + if lines[0] != "": this.masks[installation] = lines # Pins - cmd = ['flatpak-spawn', '--host', - 'flatpak', 'pin',] + cmd = [ + "flatpak-spawn", + "--host", + "flatpak", + "pin", + ] if installation == "user" or installation == "system": cmd.append(f"--{installation}") else: cmd.append(f"--installation={installation}") output = subprocess.run( - cmd, text=True, + cmd, + text=True, capture_output=True, ).stdout lines = output.strip().replace(" ", "").split("\n") - if lines[0] != '': + if lines[0] != "": this.pins[installation] = lines try: @@ -329,7 +337,7 @@ class HostInfo: for line in f: if line.startswith("[Installation"): # Get specifically the installation name itself - this.installations.append(line.replace("[Installation \"", "").replace("\"]", "").strip()) + this.installations.append(line.replace('[Installation "', "").replace('"]', "").strip()) this.installations.append("user") this.installations.append("system") @@ -340,9 +348,9 @@ class HostInfo: # Packages output = subprocess.run( - ['flatpak-spawn', '--host', 'flatpak', 'list', - '--columns=name,application,version,branch,arch,origin,installation,ref,size,options'], - text=True, check=True, + ["flatpak-spawn", "--host", "flatpak", "list", "--columns=name,application,version,branch,arch,origin,installation,ref,size,options"], + text=True, + check=True, capture_output=True, ).stdout lines = output.strip().split("\n") @@ -354,15 +362,15 @@ class HostInfo: # Dependent Runtimes output = subprocess.run( - ['flatpak-spawn', '--host', - 'flatpak', 'list', '--columns=runtime,ref'], - text=True, check=True, + ["flatpak-spawn", "--host", "flatpak", "list", "--columns=runtime,ref"], + text=True, + check=True, capture_output=True, ).stdout lines = output.split("\n") for index, line in enumerate(lines): split_line = line.split("\t") - if len(split_line) < 2 or split_line[0] == '': + if len(split_line) < 2 or split_line[0] == "": continue package = this.flatpaks[index] diff --git a/src/install_page/file_install_dialog.py b/src/install_page/file_install_dialog.py index 7a85bc9..2ae0949 100644 --- a/src/install_page/file_install_dialog.py +++ b/src/install_page/file_install_dialog.py @@ -1,5 +1,6 @@ from gi.repository import Adw, Gtk + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/file_install_dialog.ui") class FileInstallDialog(Adw.Dialog): __gtype_name__ = "FileInstallDialog" diff --git a/src/install_page/install_page.py b/src/install_page/install_page.py index 178176e..329a5e1 100644 --- a/src/install_page/install_page.py +++ b/src/install_page/install_page.py @@ -7,6 +7,7 @@ from .loading_status import LoadingStatus from .package_install_worker import PackageInstallWorker from .error_toast import ErrorToast + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/install_page.ui") class InstallPage(Adw.BreakpointBin): __gtype_name__ = "InstallPage" @@ -25,8 +26,8 @@ class InstallPage(Adw.BreakpointBin): bottom_label = gtc() # Referred to in the main window - # It is used to determine if a new page should be made or not - # This must be set to the created object from within the class's __init__ method + # It is used to determine if a new page should be made or not + # This must be set to the created object from within the class's __init__ method instance = None page_name = "install" diff --git a/src/install_page/pending_page.py b/src/install_page/pending_page.py index 8c2a1c6..c9b54ac 100644 --- a/src/install_page/pending_page.py +++ b/src/install_page/pending_page.py @@ -2,6 +2,7 @@ from gi.repository import Adw, Gtk from .host_info import HostInfo from .result_row import ResultRow + class AddedGroup(Adw.PreferencesGroup): __gtype_name__ = "AddedGroup" @@ -33,12 +34,13 @@ class AddedGroup(Adw.PreferencesGroup): icon_name="list-remove-all-symbolic", label=_("Remove All"), ), - valign = Gtk.Align.CENTER, + valign=Gtk.Align.CENTER, ) remove_all.add_css_class("flat") remove_all.connect("clicked", self.remove_all) self.set_header_suffix(remove_all) + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/pending_page.ui") class PendingPage(Adw.NavigationPage): __gtype_name__ = "PendingPage" @@ -100,7 +102,7 @@ class PendingPage(Adw.NavigationPage): "extra_flags": [], } for row in group.rows: - item['package_names'].append(row.package.app_id) + item["package_names"].append(row.package.app_id) package_requests.append(item) @@ -119,7 +121,7 @@ class PendingPage(Adw.NavigationPage): super().__init__(**kwargs) # Extra Object Creation - self.groups = {} # remote<>installation: adw.preference_group + self.groups = {} # remote<>installation: adw.preference_group self.added_packages = [] # Connections diff --git a/src/install_page/result_row.py b/src/install_page/result_row.py index 5061ec3..1edee1e 100644 --- a/src/install_page/result_row.py +++ b/src/install_page/result_row.py @@ -1,6 +1,7 @@ from gi.repository import Adw, Gtk, GLib from enum import Enum + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/result_row.ui") class ResultRow(Adw.ActionRow): __gtype_name__ = "ResultRow" diff --git a/src/install_page/results_page.py b/src/install_page/results_page.py index 0e5f692..84bb00a 100644 --- a/src/install_page/results_page.py +++ b/src/install_page/results_page.py @@ -5,6 +5,7 @@ from .loading_status import LoadingStatus from .error_toast import ErrorToast import subprocess + class AddedPackage: def __eq__(self, other): return ( @@ -17,11 +18,7 @@ class AddedPackage: ) def is_similar(self, other): - return ( - self.app_id == other.app_id - and self.branch == other.branch - and self.version == other.version - ) + return self.app_id == other.app_id and self.branch == other.branch and self.version == other.version def __init__(self, name, app_id, branch, version, remote, installation): self.name = name @@ -31,6 +28,7 @@ class AddedPackage: self.remote = remote self.installation = installation + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/results_page.ui") class ResultsPage(Adw.NavigationPage): __gtype_name__ = "ResultsPage" @@ -41,7 +39,7 @@ class ResultsPage(Adw.NavigationPage): stack = gtc() new_search = gtc() too_many = gtc() - results_view= gtc() + results_view = gtc() no_results = gtc() def show_remote(self, row, remote, installation, nav_view=None): @@ -76,9 +74,11 @@ class ResultsPage(Adw.NavigationPage): try: output = subprocess.run( - ['flatpak-spawn', '--host', 'flatpak', 'search', '--columns=all', installation, self.search_entry.get_text()], - check=True, text=True, capture_output=True - ).stdout.split('\n') + ["flatpak-spawn", "--host", "flatpak", "search", "--columns=all", installation, self.search_entry.get_text()], + check=True, + text=True, + capture_output=True, + ).stdout.split("\n") if len(output) > 100: GLib.idle_add(lambda *_: self.stack.set_visible_child(self.too_many)) return @@ -86,11 +86,11 @@ class ResultsPage(Adw.NavigationPage): for line in output: line = line.strip() - info = line.split('\t') + info = line.split("\t") if len(info) != 6: continue - remotes = info[5].split(',') + remotes = info[5].split(",") if not self.remote.name in remotes: continue diff --git a/src/install_page/select_page.py b/src/install_page/select_page.py index 7e036d4..f6f323a 100644 --- a/src/install_page/select_page.py +++ b/src/install_page/select_page.py @@ -5,6 +5,7 @@ from .results_page import ResultsPage from .sidebar_button import SidebarButton from .file_install_dialog import FileInstallDialog + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/install_page/select_page.ui") class SelectPage(Adw.NavigationPage): __gtype_name__ = "SelectPage" @@ -41,12 +42,14 @@ class SelectPage(Adw.NavigationPage): requests = [] for file in file_names: # sadly flatpak doesn't support multiple local installs in one command :( - requests.append({ - "remote": "local_file", - "installation": installation, - "package_names": [file.get_path()], - "extra_flags": [], - }) + requests.append( + { + "remote": "local_file", + "installation": installation, + "package_names": [file.get_path()], + "extra_flags": [], + } + ) install_page.install_packages(requests) diff --git a/src/main.py b/src/main.py index eafe529..6dd4c8c 100644 --- a/src/main.py +++ b/src/main.py @@ -30,6 +30,7 @@ from .window import WarehouseWindow from .const import Config from .error_toast import ErrorToast + class WarehouseApplication(Adw.Application): """The main application singleton class.""" @@ -55,7 +56,7 @@ class WarehouseApplication(Adw.Application): self.create_action("show-install-page", lambda *_: self.props.active_window.switch_page_shortcut_handler("i"), ["i"]) self.create_action("toggle-select-mode", self.on_toggle_select_mode_shortcut, ["b", "Return"]) - self.create_action("toggle-selection-kp-enter", self.on_toggle_select_mode_shortcut, ["KP_Enter"]) # Doesn't show in the shortcuts window + self.create_action("toggle-selection-kp-enter", self.on_toggle_select_mode_shortcut, ["KP_Enter"]) # Doesn't show in the shortcuts window self.create_action("search-mode", self.on_search_mode_shortcut, ["f"]) self.create_action("filter", self.on_filter_shortcut, ["t"]) self.create_action("new", self.on_new_shortcut, ["n"]) @@ -64,20 +65,8 @@ class WarehouseApplication(Adw.Application): self.is_dialog_open = False - gtk_version = ( - str(Gtk.MAJOR_VERSION) - + "." - + str(Gtk.MINOR_VERSION) - + "." - + str(Gtk.MICRO_VERSION) - ) - adw_version = ( - str(Adw.MAJOR_VERSION) - + "." - + str(Adw.MINOR_VERSION) - + "." - + str(Adw.MICRO_VERSION) - ) + gtk_version = str(Gtk.MAJOR_VERSION) + "." + str(Gtk.MINOR_VERSION) + "." + str(Gtk.MICRO_VERSION) + adw_version = str(Adw.MAJOR_VERSION) + "." + str(Adw.MINOR_VERSION) + "." + str(Adw.MICRO_VERSION) os_string = GLib.get_os_info("NAME") + " " + GLib.get_os_info("VERSION") lang = GLib.environ_getenv(GLib.get_environ(), "LANG") @@ -252,6 +241,7 @@ class WarehouseApplication(Adw.Application): if shortcuts: self.set_accels_for_action(f"app.{name}", shortcuts) + def main(version): """The application's entry point.""" app = WarehouseApplication() diff --git a/src/main_window/window.py b/src/main_window/window.py index 23683ae..cbf9f29 100644 --- a/src/main_window/window.py +++ b/src/main_window/window.py @@ -26,6 +26,7 @@ from .install_page import InstallPage from .error_toast import ErrorToast from .const import Config + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/main_window/window.ui") class WarehouseWindow(Adw.ApplicationWindow): __gtype_name__ = "WarehouseWindow" diff --git a/src/package_install_worker.py b/src/package_install_worker.py index 51fc36a..0c045e4 100644 --- a/src/package_install_worker.py +++ b/src/package_install_worker.py @@ -2,19 +2,20 @@ from gi.repository import Gio, GLib from .host_info import HostInfo import subprocess, re + class PackageInstallWorker: - """ Expect Package Installation Request Data to be Formatted as Such - [ - { - "remote": "" or "local_file", - "installation": "", - "package_names": ["", "", ...], - "extra_flags": ["", "", ...], - }, - { - ... - }, - ] + """Expect Package Installation Request Data to be Formatted as Such + [ + { + "remote": "" or "local_file", + "installation": "", + "package_names": ["", "", ...], + "extra_flags": ["", "", ...], + }, + { + ... + }, + ] """ groups = None @@ -46,22 +47,22 @@ class PackageInstallWorker: return real_installation = "" - installation = group['installation'] + installation = group["installation"] if installation == "user" or installation == "system": real_installation = f"--{installation}" else: real_installation = f"--installation={installation}" - cmd = ['flatpak-spawn', '--host', 'flatpak', 'install', '-y'] + cmd = ["flatpak-spawn", "--host", "flatpak", "install", "-y"] # Handle local file installs. They don't have a remote specified - if group['remote'] != "local_file": - cmd.append(group['remote']) + if group["remote"] != "local_file": + cmd.append(group["remote"]) - cmd += [real_installation] + group['package_names'] + group['extra_flags'] - this.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) - percent_pattern = r'\d{1,3}%' - amount_pattern = r'(\d+)/(\d+)' + cmd += [real_installation] + group["package_names"] + group["extra_flags"] + this.process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) + percent_pattern = r"\d{1,3}%" + amount_pattern = r"(\d+)/(\d+)" for line in this.process.stdout: line = line.strip() percent_match = re.search(percent_pattern, line) @@ -69,7 +70,7 @@ class PackageInstallWorker: ratio = int(percent_match.group()[0:-1]) / 100.0 amount_match = re.search(amount_pattern, line) if amount_match: - amount = amount_match.group().split('/') + amount = amount_match.group().split("/") complete = int(amount[0]) - 1 total = int(amount[1]) this.update_status(index, ratio, complete, total) @@ -83,7 +84,7 @@ class PackageInstallWorker: if len(errors) > 0: this.on_error(_("Errors occurred during installation"), "\n".join(errors)) - except subprocess.TimeoutExpired as te: + except subprocess.TimeoutExpired: this.process.terminate() this.on_error(_("Error occurred during installation"), _("Failed to exit cleanly")) diff --git a/src/packages_page/filters_page.py b/src/packages_page/filters_page.py index 789c0ed..de3630b 100644 --- a/src/packages_page/filters_page.py +++ b/src/packages_page/filters_page.py @@ -1,8 +1,10 @@ from gi.repository import Adw, Gtk, Gio from .host_info import HostInfo + class FilterRow(Adw.ActionRow): - __gtype_name__ = 'FilterRow' + __gtype_name__ = "FilterRow" + def __init__(self, item=None, installation=None, **kwargs): super().__init__(**kwargs) self.item = item @@ -11,9 +13,10 @@ class FilterRow(Adw.ActionRow): self.add_suffix(self.check_button) self.set_activatable_widget(self.check_button) + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/packages_page/filters_page.ui") class FiltersPage(Adw.NavigationPage): - __gtype_name__ = 'FiltersPage' + __gtype_name__ = "FiltersPage" gtc = Gtk.Template.Child app_check = gtc() runtime_check = gtc() @@ -173,7 +176,7 @@ class FiltersPage(Adw.NavigationPage): super().__init__(**kwargs) # Extra Objects Creation - self.packages_page = None # To be set in packages page + self.packages_page = None # To be set in packages page self.main_window = HostInfo.main_window self.settings = Gio.Settings.new("io.github.flattool.Warehouse.filter") self.is_settings_settable = False diff --git a/src/packages_page/packages_page.py b/src/packages_page/packages_page.py index 5f8efc7..7d2638e 100644 --- a/src/packages_page/packages_page.py +++ b/src/packages_page/packages_page.py @@ -11,9 +11,10 @@ from .package_install_worker import PackageInstallWorker from .change_version_worker import ChangeVersionWorker import subprocess, os + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/packages_page/packages_page.ui") class PackagesPage(Adw.BreakpointBin): - __gtype_name__ = 'PackagesPage' + __gtype_name__ = "PackagesPage" gtc = Gtk.Template.Child packages_bpt = gtc() packages_toast_overlay = gtc() @@ -49,8 +50,8 @@ class PackagesPage(Adw.BreakpointBin): filters_page = gtc() # Referred to in the main window - # It is used to determine if a new page should be made or not - # This must be set to the created object from within the class's __init__ method + # It is used to determine if a new page should be made or not + # This must be set to the created object from within the class's __init__ method instance = None page_name = "packages" last_activated_row = None @@ -110,7 +111,9 @@ class PackagesPage(Adw.BreakpointBin): visible = False if remotes_list != "all" and not f"{row.package.info['origin']}<>{row.package.info['installation']}" in remotes_list: visible = False - if runtimes_list != "all" and (row.package.is_runtime or row.package.dependent_runtime and not row.package.dependent_runtime.info["ref"] in runtimes_list): + if runtimes_list != "all" and ( + row.package.is_runtime or row.package.dependent_runtime and not row.package.dependent_runtime.info["ref"] in runtimes_list + ): visible = False row.set_visible(visible) @@ -195,7 +198,7 @@ class PackagesPage(Adw.BreakpointBin): self.apply_filters() self.select_first_visible_row() - self.scrolled_window.set_vadjustment(Gtk.Adjustment.new(0,0,0,0,0,0)) # Scroll list to top + self.scrolled_window.set_vadjustment(Gtk.Adjustment.new(0, 0, 0, 0, 0, 0)) # Scroll list to top def row_activate_handler(self, list_box, row): if self.select_button.get_active(): @@ -248,7 +251,7 @@ class PackagesPage(Adw.BreakpointBin): to_copy = [] for row in self.selected_rows: to_copy.append(row.package.info[info]) - to_copy += ['\n'] + to_copy += ["\n"] try: HostInfo.clipboard.set("".join(to_copy[:-1])) self.packages_toast_overlay.add_toast(Adw.Toast(title=_("Copied {}").format(feedback))) @@ -262,18 +265,19 @@ class PackagesPage(Adw.BreakpointBin): def on_response(should_trash): GLib.idle_add(lambda *_: self.set_status(self.uninstalling)) error = [] + def thread(*args): HostInfo.main_window.add_refresh_lockout("batch uninstalling packages") - cmd = ['flatpak-spawn', '--host', 'flatpak', 'uninstall', '-y'] - to_uninstall = {} # { <>: [, , , ...], ... } + cmd = ["flatpak-spawn", "--host", "flatpak", "uninstall", "-y"] + to_uninstall = {} # { <>: [, , , ...], ... } to_trash = [] for row in self.selected_rows: - key = row.package.info['installation'] + key = row.package.info["installation"] if ls := to_uninstall.get(key, False): - ls.append(row.package.info['ref']) + ls.append(row.package.info["ref"]) else: - to_uninstall[key] = [row.package.info['ref']] + to_uninstall[key] = [row.package.info["ref"]] if should_trash and os.path.exists(row.package.data_path): to_trash.append(row.package.data_path) @@ -294,7 +298,7 @@ class PackagesPage(Adw.BreakpointBin): if should_trash and len(to_trash) > 0: try: - subprocess.run(['gio', 'trash'] + to_trash, check=True, text=True, capture_output=True) + subprocess.run(["gio", "trash"] + to_trash, check=True, text=True, capture_output=True) except subprocess.CalledProcessError as cpe: error.append(cpe) diff --git a/src/packages_page/uninstall_dialog.py b/src/packages_page/uninstall_dialog.py index 6a0e2e0..93348c9 100644 --- a/src/packages_page/uninstall_dialog.py +++ b/src/packages_page/uninstall_dialog.py @@ -1,5 +1,6 @@ from gi.repository import Adw, Gtk, GLib + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/packages_page/uninstall_dialog.ui") class UninstallDialog(Adw.AlertDialog): __gtype_name__ = "UninstallDialog" diff --git a/src/properties_page/properties_page.py b/src/properties_page/properties_page.py index 213c3d3..292342a 100644 --- a/src/properties_page/properties_page.py +++ b/src/properties_page/properties_page.py @@ -7,9 +7,10 @@ from .loading_status import LoadingStatus from .package_install_worker import PackageInstallWorker import subprocess, os + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/properties_page/properties_page.ui") class PropertiesPage(Adw.NavigationPage): - __gtype_name__ = 'PropertiesPage' + __gtype_name__ = "PropertiesPage" gtc = Gtk.Template.Child stack = gtc() error_tbv = gtc() @@ -89,12 +90,12 @@ class PropertiesPage(Adw.NavigationPage): self.open_app_button.set_visible(package.is_runtime) self.open_app_button.set_visible(not package.is_runtime) self.data_row.set_visible(not package.is_runtime) - self.uninstall_button.set_sensitive(self.package.info['id'] != "io.github.flattool.Warehouse") + self.uninstall_button.set_sensitive(self.package.info["id"] != "io.github.flattool.Warehouse") if package.is_runtime: self.runtime_row.set_visible(False) else: has_path = os.path.exists(package.data_path) - self.trash_data_button.set_sensitive(has_path and self.package.info['id'] != "io.github.flattool.Warehouse") + self.trash_data_button.set_sensitive(has_path and self.package.info["id"] != "io.github.flattool.Warehouse") self.open_data_button.set_sensitive(has_path) if not self.package.dependent_runtime is None: @@ -163,7 +164,7 @@ class PropertiesPage(Adw.NavigationPage): def trash_data_handler(self, *args): def on_choice(dialog, response): - if response != 'continue': + if response != "continue": return try: self.package.trash_data() @@ -184,16 +185,17 @@ class PropertiesPage(Adw.NavigationPage): dialog = Adw.AlertDialog( heading=_("Send {}'s User Data to the Trash?").format(self.package.info["name"]), - body=_("Your settings and data for this app will be sent to the trash") + body=_("Your settings and data for this app will be sent to the trash"), ) - dialog.add_response('cancel', _("Cancel")) - dialog.add_response('continue', _("Trash Data")) + dialog.add_response("cancel", _("Cancel")) + dialog.add_response("continue", _("Trash Data")) dialog.connect("response", on_choice) - dialog.set_response_appearance('continue', Adw.ResponseAppearance.DESTRUCTIVE) + dialog.set_response_appearance("continue", Adw.ResponseAppearance.DESTRUCTIVE) dialog.present(self.main_window) def set_mask_handler(self, *args): state = not self.mask_switch.get_active() + def callback(*args): if fail := self.package.failed_mask: response = _("Could not Disable Updates") if state else _("Could not Enable Updates") @@ -212,6 +214,7 @@ class PropertiesPage(Adw.NavigationPage): def set_pin_handler(self, *args): state = not self.pin_switch.get_active() + def callback(*args): if fail := self.package.failed_pin: response = _("Could not Disable Autoremoval") if state else _("Could not Enable Autoremoval") @@ -278,7 +281,7 @@ class PropertiesPage(Adw.NavigationPage): def reinstall_callback(self): HostInfo.main_window.refresh_handler() if not self.reinstall_did_error: - HostInfo.main_window.toast_overlay.add_toast(Adw.Toast(title=_("Reinstalled {}").format(self.package.info['name']))) + HostInfo.main_window.toast_overlay.add_toast(Adw.Toast(title=_("Reinstalled {}").format(self.package.info["name"]))) def reinstall_error_callback(self, user_facing_label, error_message): self.reinstall_did_error = True @@ -291,12 +294,14 @@ class PropertiesPage(Adw.NavigationPage): self.reinstall_did_error = False PackageInstallWorker.install( - [{ - "installation": self.package.info['installation'], - "remote": self.package.info['origin'], - "package_names": [self.package.info['ref']], - "extra_flags": ["--reinstall"], - }], + [ + { + "installation": self.package.info["installation"], + "remote": self.package.info["origin"], + "package_names": [self.package.info["ref"]], + "extra_flags": ["--reinstall"], + } + ], self.packages_page.reinstalling, self.reinstall_callback, self.reinstall_error_callback, @@ -304,8 +309,8 @@ class PropertiesPage(Adw.NavigationPage): self.packages_page.set_status(self.packages_page.reinstalling) dialog = Adw.AlertDialog( - heading=_("Reinstall {}?").format(self.package.info['name']), - body=_("This package will be uninstalled, and then reinstalled from the same remote and installation.") + heading=_("Reinstall {}?").format(self.package.info["name"]), + body=_("This package will be uninstalled, and then reinstalled from the same remote and installation."), ) dialog.add_response("cancel", _("Cancel")) dialog.add_response("continue", _("Reinstall")) @@ -346,25 +351,22 @@ class PropertiesPage(Adw.NavigationPage): self.info_rows = { "version": self.version_row, "installed": self.installed_size_row, - "id": self.id_row, "ref": self.ref_row, "arch": self.arch_row, "branch": self.branch_row, "license": self.license_row, - "sdk": self.sdk_row, "origin": self.origin_row, "collection": self.collection_row, "installation": self.installation_row, - "commit": self.commit_row, "parent": self.parent_row, "subject": self.subject_row, "date": self.date_row, } self.loading_tbv.set_content(LoadingStatus(_("Loading Properties"), _("This should only take a moment"))) - self.packages_page = None # To be set in packages page + self.packages_page = None # To be set in packages page self.__class__.main_window = self.main_window self.view_snapshots = Gtk.Label(halign=Gtk.Align.START, label=_("View Snapshots")) self.copy_launch_command = Gtk.Label(halign=Gtk.Align.START, label=_("Copy Launch Command")) diff --git a/src/remotes_page/add_remote_dialog.py b/src/remotes_page/add_remote_dialog.py index 9db0577..574383d 100644 --- a/src/remotes_page/add_remote_dialog.py +++ b/src/remotes_page/add_remote_dialog.py @@ -5,6 +5,7 @@ from .loading_status import LoadingStatus from .installation_chooser import InstallationChooser import subprocess, re + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/remotes_page/add_remote_dialog.ui") class AddRemoteDialog(Adw.Dialog): __gtype_name__ = "AddRemoteDialog" @@ -24,12 +25,15 @@ class AddRemoteDialog(Adw.Dialog): self.parent_page.status_stack.set_visible_child(self.parent_page.adding_view) self.apply_button.set_sensitive(False) error = [None] + def thread(*args): HostInfo.main_window.add_refresh_lockout("adding remote") cmd = [ - 'flatpak-spawn', '--host', - 'flatpak', 'remote-add', - f'--title={self.title_row.get_text()}', + "flatpak-spawn", + "--host", + "flatpak", + "remote-add", + f"--title={self.title_row.get_text()}", self.name_row.get_text(), self.url_row.get_text(), ] diff --git a/src/remotes_page/remote_row.py b/src/remotes_page/remote_row.py index 5fb7c89..e9295aa 100644 --- a/src/remotes_page/remote_row.py +++ b/src/remotes_page/remote_row.py @@ -3,9 +3,10 @@ from .host_info import HostInfo from .error_toast import ErrorToast import subprocess + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/remotes_page/remote_row.ui") class RemoteRow(Adw.ActionRow): - __gtype_name__ = 'RemoteRow' + __gtype_name__ = "RemoteRow" gtc = Gtk.Template.Child suffix_label = gtc() @@ -25,8 +26,9 @@ class RemoteRow(Adw.ActionRow): return has_error = [] + def thread(*args): - cmd = ['flatpak-spawn', '--host', 'flatpak', 'remote-modify', '--enable', self.remote.name] + cmd = ["flatpak-spawn", "--host", "flatpak", "remote-modify", "--enable", self.remote.name] if self.installation == "user" or self.installation == "system": cmd.append(f"--{self.installation}") else: @@ -95,7 +97,7 @@ class RemoteRow(Adw.ActionRow): self.parent_page.toast_overlay.add_toast(ErrorToast(_("Could not disable remote"), _("Remote is already disabled")).toast) return - cmd = ['flatpak-spawn', '--host', 'flatpak', 'remote-modify', '--disable', self.remote.name] + cmd = ["flatpak-spawn", "--host", "flatpak", "remote-modify", "--disable", self.remote.name] if self.installation == "user" or self.installation == "system": cmd.append(f"--{self.installation}") else: @@ -118,7 +120,9 @@ class RemoteRow(Adw.ActionRow): Gio.Task.new(None, None, callback).run_in_thread(thread) - dialog = Adw.AlertDialog(heading=_("Disable {}?").format(self.remote.title), body=_("Any installed apps from {} will stop receiving updates").format(self.remote.name)) + dialog = Adw.AlertDialog( + heading=_("Disable {}?").format(self.remote.title), body=_("Any installed apps from {} will stop receiving updates").format(self.remote.name) + ) dialog.add_response("cancel", _("Cancel")) dialog.add_response("continue", _("Disable")) dialog.set_response_appearance("continue", Adw.ResponseAppearance.DESTRUCTIVE) diff --git a/src/remotes_page/remotes_page.py b/src/remotes_page/remotes_page.py index ec3d107..50cc6d0 100644 --- a/src/remotes_page/remotes_page.py +++ b/src/remotes_page/remotes_page.py @@ -6,6 +6,7 @@ from .add_remote_dialog import AddRemoteDialog from .loading_status import LoadingStatus import subprocess + class NewRemoteRow(Adw.ActionRow): __gtype_name__ = "NewRemoteRow" @@ -20,6 +21,7 @@ class NewRemoteRow(Adw.ActionRow): GLib.idle_add(self.idle_stuff) self.set_activatable(True) + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/remotes_page/remotes_page.ui") class RemotesPage(Adw.NavigationPage): # Preselected Remotes @@ -28,7 +30,7 @@ class RemotesPage(Adw.NavigationPage): "title": "AppCenter", "name": "appcenter", "link": "https://flatpak.elementary.io/repo.flatpakrepo", - "description": _("The open source, pay-what-you-want app store from elementary") + "description": _("The open source, pay-what-you-want app store from elementary"), }, { "title": "Flathub", @@ -59,10 +61,10 @@ class RemotesPage(Adw.NavigationPage): "name": "webkit-sdk", "link": "https://software.igalia.com/flatpak-refs/webkit-sdk.flatpakrepo", "description": _("Central repository of the WebKit Developer and Runtime SDK"), - } + }, ] - __gtype_name__ = 'RemotesPage' + __gtype_name__ = "RemotesPage" gtc = Gtk.Template.Child search_button = gtc() @@ -87,8 +89,8 @@ class RemotesPage(Adw.NavigationPage): content_page = gtc() # Referred to in the main window - # It is used to determine if a new page should be made or not - # This must be set to the created object from within the class's __init__ method + # It is used to determine if a new page should be made or not + # This must be set to the created object from within the class's __init__ method instance = None page_name = "remotes" @@ -152,9 +154,10 @@ class RemotesPage(Adw.NavigationPage): def remove_remote(self, row): error = [None] + def thread(*args): install = row.installation - cmd = ['flatpak-spawn', '--host', 'flatpak', 'remote-delete', row.remote.name, '--force'] + cmd = ["flatpak-spawn", "--host", "flatpak", "remote-delete", row.remote.name, "--force"] if install == "user" or install == "system": cmd.append(f"--{install}") else: @@ -184,7 +187,9 @@ class RemotesPage(Adw.NavigationPage): Gio.Task.new(None, None, callback).run_in_thread(thread) - dialog = Adw.AlertDialog(heading=_("Remove {}?").format(row.remote.title), body=_("Any installed apps from {} will stop receiving updates").format(row.remote.name)) + dialog = Adw.AlertDialog( + heading=_("Remove {}?").format(row.remote.title), body=_("Any installed apps from {} will stop receiving updates").format(row.remote.name) + ) dialog.add_response("cancel", _("Cancel")) dialog.add_response("continue", _("Remove")) dialog.set_response_appearance("continue", Adw.ResponseAppearance.DESTRUCTIVE) @@ -250,7 +255,7 @@ class RemotesPage(Adw.NavigationPage): total_visible = 0 for row in self.current_remote_rows: if row.remote.disabled: - if show_disabled: # show disabled + if show_disabled: # show disabled row.set_visible(True) total_visible += 1 else: diff --git a/src/snapshot_page/new_snapshot_dialog.py b/src/snapshot_page/new_snapshot_dialog.py index 39ae381..cb1ff66 100644 --- a/src/snapshot_page/new_snapshot_dialog.py +++ b/src/snapshot_page/new_snapshot_dialog.py @@ -5,6 +5,7 @@ from .app_row import AppRow from .tar_worker import TarWorker import os, time + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/snapshot_page/new_snapshot_dialog.ui") class NewSnapshotDialog(Adw.Dialog): __gtype_name__ = "NewSnapshotDialog" @@ -76,7 +77,7 @@ class NewSnapshotDialog(Adw.Dialog): def valid_checker(self): text = self.name_entry.get_text().strip() something_selected = len(self.selected_rows) > 0 - text_good = len(text) > 0 and not("/" in text or "\0" in text) + text_good = len(text) > 0 and not ("/" in text or "\0" in text) self.create_button.set_sensitive(something_selected and text_good) if text_good: self.name_entry.remove_css_class("error") diff --git a/src/snapshot_page/snapshot_box.py b/src/snapshot_page/snapshot_box.py index 758da5a..64788a9 100644 --- a/src/snapshot_page/snapshot_box.py +++ b/src/snapshot_page/snapshot_box.py @@ -4,6 +4,7 @@ from .error_toast import ErrorToast from .tar_worker import TarWorker import os, subprocess, json + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/snapshot_page/snapshot_box.ui") class SnapshotBox(Gtk.Box): __gtype_name__ = "SnapshotBox" @@ -22,10 +23,10 @@ class SnapshotBox(Gtk.Box): def create_json(self): try: data = { - 'snapshot_version': 1, - 'name': '', + "snapshot_version": 1, + "name": "", } - with open(self.json_path, 'w') as file: + with open(self.json_path, "w") as file: json.dump(data, file, indent=4) return None @@ -34,7 +35,7 @@ class SnapshotBox(Gtk.Box): def update_json(self, key, value): try: - with open(self.json_path, 'r+') as file: + with open(self.json_path, "r+") as file: data = json.load(file) data[key] = value file.seek(0) @@ -49,9 +50,9 @@ class SnapshotBox(Gtk.Box): self.create_json() try: - with open(self.json_path, 'r') as file: + with open(self.json_path, "r") as file: data = json.load(file) - name = data['name'] + name = data["name"] if name != "": self.title.set_label(GLib.markup_escape_text(name)) else: @@ -64,7 +65,7 @@ class SnapshotBox(Gtk.Box): if not self.valid_checker(): return - self.update_json('name', self.rename_entry.get_text().strip()) + self.update_json("name", self.rename_entry.get_text().strip()) self.load_from_json() self.rename_menu.popdown() @@ -87,7 +88,7 @@ class SnapshotBox(Gtk.Box): def thread(*args): try: - subprocess.run(['gio', 'trash', path], capture_output=True, text=True, check=True) + subprocess.run(["gio", "trash", path], capture_output=True, text=True, check=True) except subprocess.CalledProcessError as cpe: error[0] = cpe.stderr except Exception as e: @@ -130,9 +131,9 @@ class SnapshotBox(Gtk.Box): if self.worker in self.snapshot_page.workers: self.snapshot_page.workers.remove(self.worker) - return False # Stop the timeout + return False # Stop the timeout else: - return True # Continue the timeout + return True # Continue the timeout def on_apply(self, button): def on_response(dialog, response): @@ -162,14 +163,14 @@ class SnapshotBox(Gtk.Box): self.snapshot_page = parent_page.parent_page self.toast_overlay = toast_overlay - self.app_id = snapshots_path.split('/')[-2].strip() + self.app_id = snapshots_path.split("/")[-2].strip() self.worker = TarWorker( existing_path=f"{snapshots_path}{folder}", new_path=f"{HostInfo.home}/.var/app/{self.app_id}/", toast_overlay=self.toast_overlay, ) - split_folder = folder.split('_') + split_folder = folder.split("_") if len(split_folder) < 2: return diff --git a/src/snapshot_page/snapshot_page.py b/src/snapshot_page/snapshot_page.py index 67f0d01..6a1c26a 100644 --- a/src/snapshot_page/snapshot_page.py +++ b/src/snapshot_page/snapshot_page.py @@ -10,6 +10,7 @@ from .tar_worker import TarWorker from .attempt_install_dialog import AttemptInstallDialog import os, subprocess + class LeftoverSnapshotRow(Adw.ActionRow): __gtype_name__ = "LeftoverSnapshotRow" @@ -37,7 +38,7 @@ class LeftoverSnapshotRow(Adw.ActionRow): self.add_controller(self.rclick_gesture) self.add_controller(self.long_press_gesture) self.check_button.add_css_class("selection-mode") - self.name = self.folder.split('.')[-1] + self.name = self.folder.split(".")[-1] self.set_activatable(True) GLib.idle_add(lambda *_: self.idle_stuff()) @@ -45,6 +46,7 @@ class LeftoverSnapshotRow(Adw.ActionRow): self.rclick_gesture.connect("released", self.gesture_handler) self.long_press_gesture.connect("pressed", self.gesture_handler) + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/snapshot_page/snapshot_page.ui") class SnapshotPage(Adw.BreakpointBin): __gtype_name__ = "SnapshotPage" @@ -82,8 +84,8 @@ class SnapshotPage(Adw.BreakpointBin): trash_snapshots = gtc() # Referred to in the main window - # It is used to determine if a new page should be made or not - # This must be set to the created object from within the class's __init__ method + # It is used to determine if a new page should be made or not + # This must be set to the created object from within the class's __init__ method instance = None page_name = "snapshots" is_trash_dialog_open = False @@ -102,7 +104,7 @@ class SnapshotPage(Adw.BreakpointBin): return for folder in os.listdir(HostInfo.snapshots_path): - if folder.count('.') < 2 or ' ' in folder: + if folder.count(".") < 2 or " " in folder: bad_folders.append(folder) continue @@ -124,7 +126,7 @@ class SnapshotPage(Adw.BreakpointBin): for folder in bad_folders: try: - subprocess.run(['gio', 'trash', f'{HostInfo.snapshots_path}{folder}']) + subprocess.run(["gio", "trash", f"{HostInfo.snapshots_path}{folder}"]) except Exception: pass @@ -191,11 +193,11 @@ class SnapshotPage(Adw.BreakpointBin): if row.package is package: self.active_listbox.select_row(row) self.active_select_handler(None, row, True) - self.toast_overlay.add_toast(Adw.Toast(title=_("Showing snapshots for {}").format(package.info['name']))) + self.toast_overlay.add_toast(Adw.Toast(title=_("Showing snapshots for {}").format(package.info["name"]))) break else: dialog = NewSnapshotDialog(self, self.snapshotting_status, self.refresh, [package]) - toast = Adw.Toast(title=_("No snapshots for {}").format(package.info['name']), button_label=_("New")) + toast = Adw.Toast(title=_("No snapshots for {}").format(package.info["name"]), button_label=_("New")) toast.connect("button-clicked", lambda *_: dialog.present(HostInfo.main_window)) self.toast_overlay.add_toast(toast) @@ -225,7 +227,7 @@ class SnapshotPage(Adw.BreakpointBin): data_exists = False for package in HostInfo.flatpaks: - if package.info['id'] == "io.github.flattool.Warehouse": + if package.info["id"] == "io.github.flattool.Warehouse": continue if os.path.exists(package.data_path): @@ -299,7 +301,7 @@ class SnapshotPage(Adw.BreakpointBin): def sort_func(self, row1, row2): if type(row1) is AppRow: - return row1.package.info['name'].lower() > row2.package.info['name'].lower() + return row1.package.info["name"].lower() > row2.package.info["name"].lower() else: return row1.name.lower() > row2.name.lower() @@ -441,7 +443,7 @@ class SnapshotPage(Adw.BreakpointBin): app_ids = [] for row in self.selected_active_rows: - app_ids.append(row.package.info['id']) + app_ids.append(row.package.info["id"]) for row in self.selected_leftover_rows: app_ids.append(row.folder) @@ -450,7 +452,7 @@ class SnapshotPage(Adw.BreakpointBin): for app_id in id_to_tar: biggest = 0 for tar in id_to_tar[app_id]: - epoch = int(tar.split('_')[0]) + epoch = int(tar.split("_")[0]) if epoch > biggest: biggest = epoch @@ -489,10 +491,7 @@ class SnapshotPage(Adw.BreakpointBin): AttemptInstallDialog(package_names, lambda is_valid: self.select_button.set_active(not is_valid)) def selection_trash_handler(self): - if ( - len(self.selected_active_rows) + len(self.selected_leftover_rows) < 1 - or self.is_trash_dialog_open - ): + if len(self.selected_active_rows) + len(self.selected_leftover_rows) < 1 or self.is_trash_dialog_open: return def on_response(dialog, response): @@ -508,7 +507,7 @@ class SnapshotPage(Adw.BreakpointBin): to_trash.append(f"{HostInfo.snapshots_path}{row.folder}") try: - subprocess.run(['gio', 'trash'] + to_trash, check=True, text=True, capture_output=True) + subprocess.run(["gio", "trash"] + to_trash, check=True, text=True, capture_output=True) self.start_loading() self.end_loading() self.toast_overlay.add_toast(Adw.Toast(title=_("Trashed snapshots"))) diff --git a/src/snapshot_page/snapshots_list_page.py b/src/snapshot_page/snapshots_list_page.py index 8af676c..fb4f1eb 100644 --- a/src/snapshot_page/snapshots_list_page.py +++ b/src/snapshot_page/snapshots_list_page.py @@ -6,6 +6,7 @@ from .loading_status import LoadingStatus from .new_snapshot_dialog import NewSnapshotDialog import os + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/snapshot_page/snapshots_list_page.ui") class SnapshotsListPage(Adw.NavigationPage): __gtype_name__ = "SnapshotsListPage" diff --git a/src/snapshot_page/tar_worker.py b/src/snapshot_page/tar_worker.py index 971ef57..a6e3e08 100644 --- a/src/snapshot_page/tar_worker.py +++ b/src/snapshot_page/tar_worker.py @@ -3,30 +3,30 @@ from .host_info import HostInfo from .error_toast import ErrorToast import os, subprocess, json + class TarWorker: def compress_thread(self, *args): try: if not os.path.exists(self.new_path): os.makedirs(self.new_path) - self.total = int(subprocess.run(['du', '-s', self.existing_path], check=True, text=True, capture_output=True).stdout.split('\t')[0]) - self.total /= 2.2 # estimate for space savings - self.process = subprocess.Popen(['tar', 'cafv', f'{self.new_path}/{self.file_name}.tar.zst', '-C', self.existing_path, '.'], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE + self.total = int(subprocess.run(["du", "-s", self.existing_path], check=True, text=True, capture_output=True).stdout.split("\t")[0]) + self.total /= 2.2 # estimate for space savings + self.process = subprocess.Popen( + ["tar", "cafv", f"{self.new_path}/{self.file_name}.tar.zst", "-C", self.existing_path, "."], stdout=subprocess.PIPE, stderr=subprocess.PIPE ) stdout, stderr = self.process.communicate() if self.process.returncode != 0: raise subprocess.CalledProcessError(self.process.returncode, self.process.args, output=stdout, stderr=stderr) - with open(f"{self.new_path}/{self.file_name}.json", 'w') as file: + with open(f"{self.new_path}/{self.file_name}.json", "w") as file: data = { - 'snapshot_version': 1, - 'name': self.name, + "snapshot_version": 1, + "name": self.name, } json.dump(data, file, indent=4) - self.stop = True # tell the check timeout to stop, because we know the file is done being made + self.stop = True # tell the check timeout to stop, because we know the file is done being made HostInfo.main_window.remove_refresh_lockout("managing snapshot") except subprocess.CalledProcessError as cpe: @@ -38,21 +38,20 @@ class TarWorker: def extract_thread(self, *args): try: if os.path.exists(self.new_path): - subprocess.run(['gio', 'trash', self.new_path], capture_output=True, check=True) # trash the current user data, because new data will go in its place + subprocess.run( + ["gio", "trash", self.new_path], capture_output=True, check=True + ) # trash the current user data, because new data will go in its place - os.makedirs(self.new_path) # create the new user data path + os.makedirs(self.new_path) # create the new user data path - self.total = int(subprocess.run(['du', '-s', self.existing_path], check=True, text=True, capture_output=True).stdout.split('\t')[0]) - self.total *= 2.2 # estimate from space savings - self.process = subprocess.Popen(['tar', '--zstd', '-xvf', self.existing_path, '-C', self.new_path], - stdout=subprocess.PIPE, - stderr=subprocess.PIPE - ) + self.total = int(subprocess.run(["du", "-s", self.existing_path], check=True, text=True, capture_output=True).stdout.split("\t")[0]) + self.total *= 2.2 # estimate from space savings + self.process = subprocess.Popen(["tar", "--zstd", "-xvf", self.existing_path, "-C", self.new_path], stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout, stderr = self.process.communicate() if self.process.returncode != 0: raise subprocess.CalledProcessError(self.process.returncode, self.process.args, output=stdout, stderr=stderr) - self.stop = True # tell the check timeout to stop, because we know the file is done being made + self.stop = True # tell the check timeout to stop, because we know the file is done being made HostInfo.main_window.remove_refresh_lockout("managing snapshot") except subprocess.CalledProcessError as cpe: @@ -70,7 +69,7 @@ class TarWorker: self.process.wait() if len(self.files_to_trash_on_cancel) > 0: try: - subprocess.run(['gio', 'trash'] + self.files_to_trash_on_cancel, capture_output=True, check=True) + subprocess.run(["gio", "trash"] + self.files_to_trash_on_cancel, capture_output=True, check=True) except Exception: pass @@ -82,17 +81,17 @@ class TarWorker: def check_size(self, check_path): try: - output = subprocess.run(['du', '-s', check_path], check=True, text=True, capture_output=True).stdout.split('\t')[0] + output = subprocess.run(["du", "-s", check_path], check=True, text=True, capture_output=True).stdout.split("\t")[0] working_total = float(output) self.fraction = working_total / self.total return not self.stop - except subprocess.CalledProcessError as cpe: - return not self.stop # continue the timeout or stop the timeout + except subprocess.CalledProcessError: + return not self.stop # continue the timeout or stop the timeout def compress(self): self.stop = False - self.files_to_trash_on_cancel = [f'{self.new_path}/{self.file_name}.tar.zst', f'{self.new_path}/{self.file_name}.json'] + self.files_to_trash_on_cancel = [f"{self.new_path}/{self.file_name}.tar.zst", f"{self.new_path}/{self.file_name}.json"] HostInfo.main_window.add_refresh_lockout("managing snapshot") Gio.Task.new(None, None, None).run_in_thread(self.compress_thread) GLib.timeout_add(200, self.check_size, f"{self.new_path}/{self.file_name}.tar.zst") diff --git a/src/user_data_page/data_box.py b/src/user_data_page/data_box.py index 83f2b69..3631b11 100644 --- a/src/user_data_page/data_box.py +++ b/src/user_data_page/data_box.py @@ -4,9 +4,10 @@ from .error_toast import ErrorToast from .attempt_install_dialog import AttemptInstallDialog import subprocess + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/data_box.ui") class DataBox(Gtk.ListBox): - __gtype_name__ = 'DataBox' + __gtype_name__ = "DataBox" gtc = Gtk.Template.Child row = gtc() @@ -24,7 +25,7 @@ class DataBox(Gtk.ListBox): def human_readable_size(self): working_size = self.size - units = ['KB', 'MB', 'GB', 'TB'] + units = ["KB", "MB", "GB", "TB"] # size *= 1024 for unit in units: if working_size < 1024: @@ -33,7 +34,7 @@ class DataBox(Gtk.ListBox): return f"~ {round(working_size)} PB" def get_size(self, *args): - self.size = int(subprocess.run(['du', '-s', self.data_path], capture_output=True, text=True).stdout.split("\t")[0]) + self.size = int(subprocess.run(["du", "-s", self.data_path], capture_output=True, text=True).stdout.split("\t")[0]) def show_size(self): def callback(*args): @@ -68,6 +69,7 @@ class DataBox(Gtk.ListBox): def install_handler(self, *args): self.parent_page.should_rclick = False + def why_cant_this_just_be_a_lambda(*args): self.parent_page.should_rclick = True @@ -78,7 +80,7 @@ class DataBox(Gtk.ListBox): def thread(*args): try: - subprocess.run(['gio', 'trash', self.data_path], check=True, text=True, capture_output=True) + subprocess.run(["gio", "trash", self.data_path], check=True, text=True, capture_output=True) properties_page = HostInfo.main_window.pages[HostInfo.main_window.packages_row].properties_page properties_package = properties_page.package if not properties_package is None: diff --git a/src/user_data_page/data_subpage.py b/src/user_data_page/data_subpage.py index 833ec55..a193167 100644 --- a/src/user_data_page/data_subpage.py +++ b/src/user_data_page/data_subpage.py @@ -3,9 +3,10 @@ from .host_info import HostInfo from .data_box import DataBox from .loading_status import LoadingStatus + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/data_subpage.ui") class DataSubpage(Gtk.Stack): - __gtype_name__ = 'DataSubpage' + __gtype_name__ = "DataSubpage" gtc = Gtk.Template.Child scrolled_window = gtc() @@ -25,7 +26,7 @@ class DataSubpage(Gtk.Stack): def human_readable_size(self): working_size = self.total_size - units = ['KB', 'MB', 'GB', 'TB'] + units = ["KB", "MB", "GB", "TB"] # size *= 1024 for unit in units: if working_size < 1024: @@ -35,6 +36,7 @@ class DataSubpage(Gtk.Stack): def sort_func(self, box1, box2): import random + # print(random.randint(1, 100), self.sort_mode, self.sort_ascend) i1 = None i2 = None @@ -138,14 +140,34 @@ class DataSubpage(Gtk.Stack): self.should_rclick = True if flatpaks: for i, pak in enumerate(flatpaks): - box = DataBox(self, self.parent_page.toast_overlay, False, pak.info["name"], pak.info["id"], pak.data_path, pak.icon_path, self.box_size_callback, self.trash_handler) + box = DataBox( + self, + self.parent_page.toast_overlay, + False, + pak.info["name"], + pak.info["id"], + pak.data_path, + pak.icon_path, + self.box_size_callback, + self.trash_handler, + ) box.check_button.connect("toggled", lambda *_, box=box: self.box_select_handler(box)) self.boxes.append(box) self.flow_box.append(box) else: for i, folder in enumerate(data): - box = DataBox(self, self.parent_page.toast_overlay, True, folder.split('.')[-1], folder, f"{HostInfo.home}/.var/app/{folder}", None, self.box_size_callback, self.trash_handler) + box = DataBox( + self, + self.parent_page.toast_overlay, + True, + folder.split(".")[-1], + folder, + f"{HostInfo.home}/.var/app/{folder}", + None, + self.box_size_callback, + self.trash_handler, + ) box.check_button.connect("toggled", lambda *_, box=box: self.box_select_handler(box)) self.flow_box.append(box) diff --git a/src/user_data_page/user_data_page.py b/src/user_data_page/user_data_page.py index 2d98eb0..8db231e 100644 --- a/src/user_data_page/user_data_page.py +++ b/src/user_data_page/user_data_page.py @@ -7,9 +7,10 @@ from .loading_status import LoadingStatus from .attempt_install_dialog import AttemptInstallDialog import os, subprocess + @Gtk.Template(resource_path="/io/github/flattool/Warehouse/user_data_page/user_data_page.ui") class UserDataPage(Adw.BreakpointBin): - __gtype_name__ = 'UserDataPage' + __gtype_name__ = "UserDataPage" gtc = Gtk.Template.Child bpt = gtc() @@ -44,8 +45,8 @@ class UserDataPage(Adw.BreakpointBin): more_install = gtc() # Referred to in the main window - # It is used to determine if a new page should be made or not - # This must be set to the created object from within the class's __init__ method + # It is used to determine if a new page should be made or not + # This must be set to the created object from within the class's __init__ method instance = None page_name = "user-data" data_path = f"{HostInfo.home}/.var/app" @@ -158,7 +159,7 @@ class UserDataPage(Adw.BreakpointBin): child = self.stack.get_visible_child() def thread(path): - cmd = ['gio', 'trash'] + path + cmd = ["gio", "trash"] + path try: subprocess.run(cmd, check=True, capture_output=True, text=True) properties_page = HostInfo.main_window.pages[HostInfo.main_window.packages_row].properties_page