From 4d17504877efeef92eff8e98497a8cefd17a2a4a Mon Sep 17 00:00:00 2001 From: Nate Marti Date: Tue, 13 Aug 2024 08:43:15 -0500 Subject: [PATCH] Continued work fixing deps install - return install_deps func if no command to run - add error message box for GUI - exit on error if AppImageLauncher installed - add missing space - auto-remove AppImageLauncher if installed - fix appimagelauncher removal command - fix clobbered variable - ask user confirmation before removing AppImageLauncher - add secondary text to continue question - fix title and text for GUI question - add note about system reboot in log - use CLI continue question for removing appimagelauncher if not tk - add explanation to cli_question - use minimal set of arch deps - remove --overwrite from pacman command for arch - Revert "remove --overwrite from pacman command for arch" - This reverts commit 8cd077c26da216367609a02f95c8d38d21af2f2e. - return False for appimage wine version check if fuse not yet installed - Revert "return False for appimage wine version check if fuse not yet installed" - This reverts commit aefb28c5aaa2acc4de5fbe51a13ad5700c1e5a21. - use glob instead of rglob for listing appimages - escape '*' in pacman command - force non-sh pkexec for arch dep installs - Revert "escape '*' in pacman command" - This reverts commit ab2ec57882e9ffd648067fcc96c92fe2919aee73. - skip extra check for fuse package - fix variable definition - Revert "force non-sh pkexec for arch dep installs" - This reverts commit 470d198a50a1d58bf023067a491f0d450e5eebb5. - put quotes around command - use normal str instead of raw for '*' - double-escape asterisk - add error message for fedora and arch dep handling - clean up suggested dep install command - clean swap pkexec out for sudo - add detail text to GUI logos_error - log package status for debugging - add detail for general logos_error - simplify hasattr checks - build showerror parameters according to passed values - fix parent param - auto-add command to clipboard in GUI - destroy error window on exit - fix typo - various pep8 fixes - add debugging info to query_packages - add more debug output - move "break" statement - add some audio/video pkgs - update arch package list - remove extra debug logging - update fedora packages - use rpm command for dnf workaround --- control.py | 6 +-- gui.py | 33 ++++++++++++++--- gui_app.py | 7 ++-- main.py | 12 ++++++ msg.py | 49 +++++++++++++++++------- system.py | 107 +++++++++++++++++++++++++++++++++++++++++------------ utils.py | 2 +- wine.py | 20 ++++++---- 8 files changed, 179 insertions(+), 57 deletions(-) diff --git a/control.py b/control.py index fbe7677d..252a2d7e 100644 --- a/control.py +++ b/control.py @@ -20,7 +20,7 @@ import network import system import tui_curses -import tui_app +# import tui_app import utils # import wine @@ -252,7 +252,7 @@ def remove_all_index_files(app=None): logging.error(f"Error removing {file_to_remove}: {e}") msg.logos_msg("======= Removing all LogosBible index files done! =======") - if app and hasattr(app, 'status_evt'): + if hasattr(app, 'status_evt'): app.root.event_generate(app.status_evt) sys.exit(0) @@ -291,7 +291,7 @@ def set_winetricks(): "1: Use local winetricks.", "2: Download winetricks from the Internet" ] - winetricks_choice = tui_curses.menu(options, title, question_text) + winetricks_choice = tui_curses.menu(options, title, question_text) # noqa: E501 logging.debug(f"winetricks_choice: {winetricks_choice}") if winetricks_choice.startswith("1"): diff --git a/gui.py b/gui.py index a8d89378..716b16bb 100644 --- a/gui.py +++ b/gui.py @@ -2,6 +2,7 @@ from tkinter import BooleanVar from tkinter import font from tkinter import IntVar +from tkinter import messagebox from tkinter import simpledialog from tkinter import StringVar from tkinter.ttk import Button @@ -335,11 +336,6 @@ def hide_tooltip(self, event=None): self.tooltip_visible = False -def input_prompt(root, title, prompt): - # Prompt for the password - input = simpledialog.askstring(title, prompt, show='*', parent=root) - return input - class PromptGui(Frame): def __init__(self, root, title="", prompt="", **kwargs): super(PromptGui, self).__init__(root, **kwargs) @@ -350,5 +346,30 @@ def __init__(self, root, title="", prompt="", **kwargs): self.options['prompt'] = prompt def draw_prompt(self): - store_button = Button(self.root, text="Store Password", command=lambda: input_prompt(self.root, self.options)) + store_button = Button( + self.root, + text="Store Password", + command=lambda: input_prompt(self.root, self.options) + ) store_button.pack(pady=20) + + +def show_error(message, title="Fatal Error", detail=None, app=None, parent=None): # noqa: E501 + kwargs = {'message': message} + if parent and hasattr(app, parent): + kwargs['parent'] = app.__dict__.get(parent) + if detail: + kwargs['detail'] = detail + messagebox.showerror(title, **kwargs) + if hasattr(app, 'root'): + app.root.destroy() + + +def ask_question(question, secondary): + return messagebox.askquestion(question, secondary) + + +def input_prompt(root, title, prompt): + # Prompt for the password + input = simpledialog.askstring(title, prompt, show='*', parent=root) + return input diff --git a/gui_app.py b/gui_app.py index c7a0667e..88e00193 100644 --- a/gui_app.py +++ b/gui_app.py @@ -688,12 +688,13 @@ def configure_app_button(self, evt=None): def run_installer(self, evt=None): classname = "LogosLinuxInstaller" - self.new_win = Toplevel() - InstallerWindow(self.new_win, self.root, class_=classname) + self.installer_win = Toplevel() + InstallerWindow(self.installer_win, self.root, class_=classname) self.root.icon = config.LOGOS_ICON_URL def run_logos(self, evt=None): - #TODO: Add reference to App here so the status message is sent to the GUI? See msg.status and wine.run_logos + # TODO: Add reference to App here so the status message is sent to the + # GUI? See msg.status and wine.run_logos t = Thread(target=wine.run_logos) t.start() diff --git a/main.py b/main.py index 768b252e..92157bba 100755 --- a/main.py +++ b/main.py @@ -13,6 +13,7 @@ import msg import network import os +import shutil import sys import system import tui_app @@ -388,6 +389,17 @@ def main(): logging.info(f"{config.LLI_TITLE}, {config.LLI_CURRENT_VERSION} by {config.LLI_AUTHOR}.") # noqa: E501 logging.debug(f"Installer log file: {config.LOGOS_LOG}") + # Check for AppImageLauncher + if shutil.which('AppImageLauncher'): + question_text = "Remove AppImageLauncher?" + secondary = ( + "LogosLinuxInstaller is not compatible with AppImageLauncher.\n" + "Remove AppImageLauncher now? A reboot will be required." + ) + no_text = "User declined to remove AppImageLauncher." + msg.logos_continue_question(question_text, no_text, secondary) + system.remove_appimagelauncher() + network.check_for_updates() # Check if app is installed. diff --git a/msg.py b/msg.py index db2d6acd..74e8c416 100644 --- a/msg.py +++ b/msg.py @@ -10,6 +10,8 @@ from pathlib import Path import config +from gui import ask_question +from gui import show_error logging.console_log = [] @@ -142,17 +144,25 @@ def logos_warn(message): logos_msg(message) -def logos_error(message, secondary=None): +def logos_error(message, secondary=None, detail=None, app=None, parent=None): + if detail is None: + message = f"{message}\n{detail}" + logging.critical(message) WIKI_LINK = "https://github.com/FaithLife-Community/LogosLinuxInstaller/wiki" # noqa: E501 TELEGRAM_LINK = "https://t.me/linux_logos" MATRIX_LINK = "https://matrix.to/#/#logosbible:matrix.org" help_message = f"If you need help, please consult:\n{WIKI_LINK}\n{TELEGRAM_LINK}\n{MATRIX_LINK}" # noqa: E501 - if config.DIALOG == 'curses' and secondary != "info": - logging.critical(message) + if config.DIALOG == 'tk': + show_error( + message, + detail=f"{detail}\n{help_message}", + app=app, + parent=parent + ) + elif config.DIALOG == 'curses' and secondary != "info": status(message) status(help_message) elif secondary != "info": - logging.critical(message) logos_msg(message) else: logos_msg(message) @@ -163,13 +173,17 @@ def logos_error(message, secondary=None): except FileNotFoundError: # no pid file when testing functions pass os.kill(os.getpgid(os.getpid()), signal.SIGKILL) + + if hasattr(app, 'destroy'): + app.destroy() sys.exit(1) -def cli_question(QUESTION_TEXT): +def cli_question(question_text, secondary): while True: try: - yn = input(f"{QUESTION_TEXT} [Y/n]: ") + cli_msg(secondary) + yn = input(f"{question_text} [Y/n]: ") except KeyboardInterrupt: print() logos_error("Cancelled with Ctrl+C") @@ -182,9 +196,14 @@ def cli_question(QUESTION_TEXT): logos_msg("Type Y[es] or N[o].") -def cli_continue_question(QUESTION_TEXT, NO_TEXT, SECONDARY): - if not cli_question(QUESTION_TEXT): - logos_error(NO_TEXT, SECONDARY) +def cli_continue_question(question_text, no_text, secondary): + if not cli_question(question_text, secondary): + logos_error(no_text) + + +def gui_continue_question(question_text, no_text, secondary): + if ask_question(question_text, secondary) == 'no': + logos_error(no_text) def cli_acknowledge_question(QUESTION_TEXT, NO_TEXT): @@ -204,11 +223,15 @@ def cli_ask_filepath(question_text): return answer.strip('"').strip("'") -def logos_continue_question(QUESTION_TEXT, NO_TEXT, SECONDARY): - if config.DIALOG == 'curses': +def logos_continue_question(question_text, no_text, secondary, app=None): + if config.DIALOG == 'tk': + gui_continue_question(question_text, no_text, secondary) + elif app is None: + cli_continue_question(question_text, no_text, secondary) + elif config.DIALOG == 'curses': pass else: - cli_continue_question(QUESTION_TEXT, NO_TEXT, SECONDARY) + logos_error(f"Unhandled question: {question_text}") def logos_acknowledge_question(QUESTION_TEXT, NO_TEXT): @@ -249,7 +272,7 @@ def status(text, app=None): app.root.event_generate('<>') elif config.DIALOG == 'curses': app.status_q.put(f"{timestamp} {text}") - app.report_waiting(f"{app.status_q.get()}", dialog=config.use_python_dialog) + app.report_waiting(f"{app.status_q.get()}", dialog=config.use_python_dialog) # noqa: E501 logging.info(f"{text}") else: '''Prints message to stdout regardless of log level.''' diff --git a/system.py b/system.py index 071ce3d2..64a58418 100644 --- a/system.py +++ b/system.py @@ -52,7 +52,7 @@ def run_command(command, retries=1, delay=0, **kwargs): ) return result except subprocess.CalledProcessError as e: - logging.error(f"Error occurred while executing {command}: {e}") + logging.error(f"Error occurred while executing \"{command}\": {e}") if "lock" in str(e): logging.debug(f"Database appears to be locked. Retrying in {delay} seconds…") # noqa: E501 time.sleep(delay) @@ -151,16 +151,21 @@ def get_package_manager(): config.QUERY_PREFIX = '.i ' config.PACKAGES = "binutils cabextract fuse3 wget winbind" config.L9PACKAGES = "" # FIXME: Missing Logos 9 Packages - config.BADPACKAGES = "appimagelauncher" + config.BADPACKAGES = "" # appimagelauncher handled separately elif shutil.which('dnf') is not None: # rhel, fedora config.PACKAGE_MANAGER_COMMAND_INSTALL = ["dnf", "install", "-y"] config.PACKAGE_MANAGER_COMMAND_DOWNLOAD = ["dnf", "install", "--downloadonly", "-y"] # noqa: E501 config.PACKAGE_MANAGER_COMMAND_REMOVE = ["dnf", "remove", "-y"] - config.PACKAGE_MANAGER_COMMAND_QUERY = ["dnf", "list", "installed"] + # config.PACKAGE_MANAGER_COMMAND_QUERY = ["dnf", "list", "installed"] + config.PACKAGE_MANAGER_COMMAND_QUERY = ["rpm", "-qa"] # workaround config.QUERY_PREFIX = '' - config.PACKAGES = "patch fuse3 fuse3-libs mod_auth_ntlm_winbind samba-winbind samba-winbind-clients cabextract bc libxml2 curl" # noqa: E501 + # config.PACKAGES = "patch fuse3 fuse3-libs mod_auth_ntlm_winbind samba-winbind samba-winbind-clients cabextract bc libxml2 curl" # noqa: E501 + config.PACKAGES = ( + "fuse3 fuse3-libs " # appimages + "mod_auth_ntlm_winbind samba-winbind samba-winbind-clients cabextract " # wine # noqa: E501 + ) config.L9PACKAGES = "" # FIXME: Missing Logos 9 Packages - config.BADPACKAGES = "appiamgelauncher" + config.BADPACKAGES = "" # appimagelauncher handled separately elif shutil.which('pamac') is not None: # manjaro config.PACKAGE_MANAGER_COMMAND_INSTALL = ["pamac", "install", "--no-upgrade", "--no-confirm"] # noqa: E501 config.PACKAGE_MANAGER_COMMAND_DOWNLOAD = ["pamac", "install", "--no-upgrade", "--download-only", "--no-confirm"] # noqa: E501 @@ -169,9 +174,9 @@ def get_package_manager(): config.QUERY_PREFIX = '' config.PACKAGES = "patch wget sed grep gawk cabextract samba bc libxml2 curl" # noqa: E501 config.L9PACKAGES = "" # FIXME: Missing Logos 9 Packages - config.BADPACKAGES = "appimagelauncher" + config.BADPACKAGES = "" # appimagelauncher handled separately elif shutil.which('pacman') is not None: # arch, steamOS - config.PACKAGE_MANAGER_COMMAND_INSTALL = ["pacman", "-Syu", "--overwrite", r"*", "--noconfirm", "--needed"] # noqa: E501 + config.PACKAGE_MANAGER_COMMAND_INSTALL = ["pacman", "-Syu", "--overwrite", "\\*", "--noconfirm", "--needed"] # noqa: E501 config.PACKAGE_MANAGER_COMMAND_DOWNLOAD = ["pacman", "-Sw", "-y"] config.PACKAGE_MANAGER_COMMAND_REMOVE = ["pacman", "-R", "--no-confirm"] # noqa: E501 config.PACKAGE_MANAGER_COMMAND_QUERY = ["pacman", "-Q"] @@ -179,9 +184,18 @@ def get_package_manager(): if config.OS_NAME == "steamos": # steamOS config.PACKAGES = "patch wget sed grep gawk cabextract samba bc libxml2 curl print-manager system-config-printer cups-filters nss-mdns foomatic-db-engine foomatic-db-ppds foomatic-db-nonfree-ppds ghostscript glibc samba extra-rel/apparmor core-rel/libcurl-gnutls winetricks appmenu-gtk-module lib32-libjpeg-turbo qt5-virtualkeyboard wine-staging giflib lib32-giflib libpng lib32-libpng libldap lib32-libldap gnutls lib32-gnutls mpg123 lib32-mpg123 openal lib32-openal v4l-utils lib32-v4l-utils libpulse lib32-libpulse libgpg-error lib32-libgpg-error alsa-plugins lib32-alsa-plugins alsa-lib lib32-alsa-lib libjpeg-turbo lib32-libjpeg-turbo sqlite lib32-sqlite libxcomposite lib32-libxcomposite libxinerama lib32-libgcrypt libgcrypt lib32-libxinerama ncurses lib32-ncurses ocl-icd lib32-ocl-icd libxslt lib32-libxslt libva lib32-libva gtk3 lib32-gtk3 gst-plugins-base-libs lib32-gst-plugins-base-libs vulkan-icd-loader lib32-vulkan-icd-loader" # noqa: #E501 else: # arch - config.PACKAGES = "patch wget sed grep cabextract samba glibc samba apparmor libcurl-gnutls winetricks appmenu-gtk-module lib32-libjpeg-turbo wine giflib lib32-giflib libpng lib32-libpng libldap lib32-libldap gnutls lib32-gnutls mpg123 lib32-mpg123 openal lib32-openal v4l-utils lib32-v4l-utils libpulse lib32-libpulse libgpg-error lib32-libgpg-error alsa-plugins lib32-alsa-plugins alsa-lib lib32-alsa-lib libjpeg-turbo lib32-libjpeg-turbo sqlite lib32-sqlite libxcomposite lib32-libxcomposite libxinerama lib32-libgcrypt libgcrypt lib32-libxinerama ncurses lib32-ncurses ocl-icd lib32-ocl-icd libxslt lib32-libxslt libva lib32-libva gtk3 lib32-gtk3 gst-plugins-base-libs lib32-gst-plugins-base-libs vulkan-icd-loader lib32-vulkan-icd-loader" # noqa: E501 + # config.PACKAGES = "patch wget sed grep cabextract samba glibc samba apparmor libcurl-gnutls winetricks appmenu-gtk-module lib32-libjpeg-turbo wine giflib lib32-giflib libpng lib32-libpng libldap lib32-libldap gnutls lib32-gnutls mpg123 lib32-mpg123 openal lib32-openal v4l-utils lib32-v4l-utils libpulse lib32-libpulse libgpg-error lib32-libgpg-error alsa-plugins lib32-alsa-plugins alsa-lib lib32-alsa-lib libjpeg-turbo lib32-libjpeg-turbo sqlite lib32-sqlite libxcomposite lib32-libxcomposite libxinerama lib32-libgcrypt libgcrypt lib32-libxinerama ncurses lib32-ncurses ocl-icd lib32-ocl-icd libxslt lib32-libxslt libva lib32-libva gtk3 lib32-gtk3 gst-plugins-base-libs lib32-gst-plugins-base-libs vulkan-icd-loader lib32-vulkan-icd-loader" # noqa: E501 + config.PACKAGES = ( + "fuse2 fuse3 " # appimages + "binutils cabextract wget libwbclient " # wine + "openjpeg2 libxcomposite libxinerama " # display + "ocl-icd vulkan-icd-loader " # hardware + "alsa-plugins gst-plugins-base-libs libpulse openal " # audio + "libva mpg123 v4l-utils " # video + "libxslt sqlite " # misc + ) config.L9PACKAGES = "" # FIXME: Missing Logos 9 Packages - config.BADPACKAGES = "appimagelauncher" + config.BADPACKAGES = "" # appimagelauncher handled separately # Add more conditions for other package managers as needed # Add logging output. @@ -208,16 +222,18 @@ def query_packages(packages, mode="install", app=None): result = run_command(command) except Exception as e: logging.error(f"Error occurred while executing command: {e}") - logging.error(result.stderr) + logging.error(e.output) package_list = result.stdout + logging.debug(f"packages to check: {packages}") status = {package: "Unchecked" for package in packages} if app is not None: - for p in packages: + logging.debug(f"Checking for: {p}") l_num = 0 for line in package_list.split('\n'): + # logging.debug(f"{line=}") l_num += 1 if config.PACKAGE_MANAGER_COMMAND_QUERY[0] == 'dpkg': parts = line.strip().split() @@ -234,11 +250,13 @@ def query_packages(packages, mode="install", app=None): break else: if line.strip().startswith(f"{config.QUERY_PREFIX}{p}") and mode == "install": # noqa: E501 + logging.debug(f"'{p}' installed: {line}") status[p] = "Installed" + break elif line.strip().startswith(p) and mode == "remove": conflicting_packages.append(p) status[p] = "Conflicting" - break + break if status[p] == "Unchecked": if mode == "install": @@ -246,6 +264,9 @@ def query_packages(packages, mode="install", app=None): status[p] = "Missing" elif mode == "remove": status[p] = "Not Installed" + logging.debug(f"{p} status: {status.get(p)}") + + logging.debug(f"Packages status: {status}") if mode == "install": if missing_packages: @@ -302,6 +323,23 @@ def parse_date(version): return None +def remove_appimagelauncher(app=None): + pkg = "appimagelauncher" + cmd = [config.SUPERUSER_COMMAND, *config.PACKAGE_MANAGER_COMMAND_REMOVE] + cmd.append(pkg) + msg.status("Removing AppImageLauncher…", app) + try: + logging.debug(f"Running command: {cmd}") + run_command(cmd) + except subprocess.CalledProcessError as e: + logging.error(f"An error occurred: {e}") + logging.error(f"Command output: {e.output}") + msg.logos_error("Failed to uninstall AppImageLauncher.") + sys.exit(1) + logging.info("System reboot is required.") + sys.exit() + + def preinstall_dependencies_steamos(): logging.debug("Disabling read only, updating pacman keys…") command = [ @@ -407,9 +445,10 @@ def install_dependencies(packages, bad_packages, logos9_packages=None, app=None) else: fuse = "libfuse" - install_fuse = check_libs([f"{fuse}"], app=app) - if not install_fuse: - missing_packages.append(fuse) + fuse_lib_installed = check_libs([f"{fuse}"], app=app) + logging.debug(f"{fuse_lib_installed=}") + # if not fuse_lib_installed: + # missing_packages.append(fuse) if missing_packages: install_command = config.PACKAGE_MANAGER_COMMAND_INSTALL + missing_packages # noqa: E501 @@ -441,6 +480,8 @@ def install_dependencies(packages, bad_packages, logos9_packages=None, app=None) if command: command.append('&&') command.extend(postinstall_command) + if not command: # nothing to run; avoid running empty pkexec command + return if app and config.DIALOG == 'tk': app.root.event_generate('<>') @@ -448,13 +489,33 @@ def install_dependencies(packages, bad_packages, logos9_packages=None, app=None) final_command = [ f"{config.SUPERUSER_COMMAND}", 'sh', '-c', "'", *command, "'" ] - try: - command_str = ' '.join(final_command) - logging.debug(f"Attempting to run this command: {command_str}") - run_command(command_str, shell=True) - except subprocess.CalledProcessError as e: - logging.error(f"An error occurred: {e}") - logging.error(f"Command output: {e.output}") + command_str = ' '.join(final_command) + # TODO: Fix fedora/arch handling. + if config.OS_NAME in ['fedora', 'arch']: + sudo_command = command_str.replace("pkexec", "sudo") + message = "The system needs to install/remove packages." + detail = ( + "Please run the following command in a terminal, then restart " + f"LogosLinuxInstaller:\n{sudo_command}\n" + ) + if hasattr(app, 'root'): + detail += "\nThe command has been copied to the clipboard." + app.root.clipboard_clear() + app.root.clipboard_append(sudo_command) + app.root.update() + msg.logos_error( + message, + detail=detail, + app=app, + parent='installer_win' + ) + else: + try: + logging.debug(f"Attempting to run this command: {command_str}") + run_command(command_str, shell=True) + except subprocess.CalledProcessError as e: + logging.error(f"An error occurred: {e}") + logging.error(f"Command output: {e.output}") else: msg.logos_error( f"The script could not determine your {config.OS_NAME} install's package manager or it is unsupported. " # noqa: E501 @@ -464,7 +525,7 @@ def install_dependencies(packages, bad_packages, logos9_packages=None, app=None) # TODO: Verify with user before executing if config.REBOOT_REQUIRED: pass - #reboot() + # reboot() def have_lib(library, ld_library_path): diff --git a/utils.py b/utils.py index 48979538..36da8d8e 100644 --- a/utils.py +++ b/utils.py @@ -659,7 +659,7 @@ def find_appimage_files(release_version, app=None): raise RuntimeError("Python 3.12 or higher is required for .rglob() flag `case-sensitive` ") # noqa: E501 for d in directories: - appimage_paths = Path(d).rglob('wine*.appimage', case_sensitive=False) + appimage_paths = Path(d).glob('wine*.appimage', case_sensitive=False) for p in appimage_paths: if p is not None and check_appimage(p): output1, output2 = wine.check_wine_version_and_branch( diff --git a/wine.py b/wine.py index 9fab2a7e..05b80b6d 100644 --- a/wine.py +++ b/wine.py @@ -215,12 +215,16 @@ def run_wine_proc(winecmd, exe=None, exe_args=list()): env = get_wine_env() if config.WINECMD_ENCODING is None: # Get wine system's cmd.exe encoding for proper decoding to UTF8 later. - registry_value = get_registry_value('HKCU\\Software\\Wine\\Fonts', 'Codepages') + registry_value = get_registry_value( + 'HKCU\\Software\\Wine\\Fonts', + 'Codepages' + ) if registry_value is not None: codepages = registry_value.split(',') # noqa: E501 config.WINECMD_ENCODING = codepages[-1] else: - logging.error("wine.wine_proc: wine.get_registry_value returned None.") + m = "wine.wine_proc: wine.get_registry_value returned None." + logging.error(m) logging.debug(f"run_wine_proc: {winecmd}; {exe=}; {exe_args=}") wine_env_vars = {k: v for k, v in env.items() if k.startswith('WINE')} logging.debug(f"wine environment: {wine_env_vars}") @@ -252,7 +256,7 @@ def run_wine_proc(winecmd, exe=None, exe_args=list()): if config.WINECMD_ENCODING is not None: logging.info(line.decode(config.WINECMD_ENCODING).rstrip()) # noqa: E501 else: - logging.error("wine.run_wine_proc: Error while decoding: WINECMD_ENCODING is None.") + logging.error("wine.run_wine_proc: Error while decoding: WINECMD_ENCODING is None.") # noqa: E501 returncode = process.wait() if returncode != 0: @@ -320,7 +324,7 @@ def installICUDataFiles(app=None): os.makedirs(icu_win_dir) shutil.copytree(icu_win_dir, f"{drive_c}/windows", dirs_exist_ok=True) - if app and hasattr(app, 'status_evt'): + if hasattr(app, 'status_evt'): app.status_q.put("ICU files copied.") app.root.event_generate(app.status_evt) @@ -485,9 +489,9 @@ def get_wine_env(): def run_logos(app=None): logos_release = utils.convert_logos_release(config.current_logos_version) wine_release, _ = get_wine_release(config.WINE_EXE) - - #TODO: Find a way to incorporate check_wine_version_and_branch() - if 30 > logos_release[0] > 9 and (wine_release[0] < 7 or (wine_release[0] == 7 and wine_release[1] < 18)): + + # TODO: Find a way to incorporate check_wine_version_and_branch() + if 30 > logos_release[0] > 9 and (wine_release[0] < 7 or (wine_release[0] == 7 and wine_release[1] < 18)): # noqa: E501 txt = "Can't run Logos 10+ with Wine below 7.18." logging.critical(txt) msg.status(txt, app) @@ -515,7 +519,7 @@ def run_indexing(): def end_wine_processes(): for process_name, process in processes.items(): if isinstance(process, subprocess.Popen): - logging.debug(f"Found {process_name} in Processes. Attempting to close {process}.") + logging.debug(f"Found {process_name} in Processes. Attempting to close {process}.") # noqa: E501 try: process.terminate() process.wait(timeout=10)