From 88ba20f6f707522a117c422cf2681a6acd2de48b Mon Sep 17 00:00:00 2001 From: dw-0 Date: Mon, 25 Dec 2023 15:35:13 +0100 Subject: [PATCH] refactor(Klipper): rework remove process Signed-off-by: Dominik Willner --- kiauh/core/menus/remove_menu.py | 6 +- kiauh/modules/klipper/klipper.py | 19 +-- kiauh/modules/klipper/klipper_remove.py | 133 ++++++++++++++++++ kiauh/modules/klipper/menus/__init__.py | 0 .../klipper/menus/klipper_remove_menu.py | 109 ++++++++++++++ 5 files changed, 245 insertions(+), 22 deletions(-) create mode 100644 kiauh/modules/klipper/klipper_remove.py create mode 100644 kiauh/modules/klipper/menus/__init__.py create mode 100644 kiauh/modules/klipper/menus/klipper_remove_menu.py diff --git a/kiauh/core/menus/remove_menu.py b/kiauh/core/menus/remove_menu.py index 5526406..863dda1 100644 --- a/kiauh/core/menus/remove_menu.py +++ b/kiauh/core/menus/remove_menu.py @@ -14,6 +14,7 @@ import textwrap from kiauh.core.menus import BACK_FOOTER from kiauh.core.menus.base_menu import BaseMenu from kiauh.modules.klipper import klipper_setup +from kiauh.modules.klipper.menus.klipper_remove_menu import KlipperRemoveMenu from kiauh.modules.mainsail.menus.mainsail_remove_menu import MainsailRemoveMenu from kiauh.modules.moonraker.menus.moonraker_remove_menu import MoonrakerRemoveMenu from kiauh.utils.constants import COLOR_RED, RESET_FORMAT @@ -25,7 +26,7 @@ class RemoveMenu(BaseMenu): super().__init__( header=True, options={ - 1: self.remove_klipper, + 1: KlipperRemoveMenu, 2: MoonrakerRemoveMenu, 3: MainsailRemoveMenu, 5: self.remove_fluidd, @@ -69,9 +70,6 @@ class RemoveMenu(BaseMenu): )[1:] print(menu, end="") - def remove_klipper(self): - klipper_setup.run_klipper_setup(install=False) - def remove_fluidd(self): print("remove_fluidd") diff --git a/kiauh/modules/klipper/klipper.py b/kiauh/modules/klipper/klipper.py index ef064a8..71eb435 100644 --- a/kiauh/modules/klipper/klipper.py +++ b/kiauh/modules/klipper/klipper.py @@ -75,7 +75,7 @@ class Klipper(BaseInstance): Logger.print_error(f"Error creating env file {env_file_target}: {e}") raise - def delete(self, del_remnants: bool) -> None: + def delete(self) -> None: service_file = self.get_service_file_name(extension=True) service_file_path = self.get_service_file_path() @@ -89,9 +89,6 @@ class Klipper(BaseInstance): Logger.print_error(f"Error deleting service file: {e}") raise - if del_remnants: - self._delete_klipper_remnants() - def write_service_file( self, service_template_path: Path, @@ -118,20 +115,6 @@ class Klipper(BaseInstance): env_file.write(env_file_content) Logger.print_ok(f"Env file created: {env_file_target}") - def _delete_klipper_remnants(self) -> None: - try: - Logger.print_status(f"Delete {self.klipper_dir} ...") - shutil.rmtree(Path(self.klipper_dir)) - Logger.print_status(f"Delete {self.env_dir} ...") - shutil.rmtree(Path(self.env_dir)) - except FileNotFoundError: - Logger.print_status("Cannot delete Klipper directories. Not found.") - except PermissionError as e: - Logger.print_error(f"Error deleting Klipper directories: {e}") - raise - - Logger.print_ok("Directories successfully deleted.") - def _prep_service_file( self, service_template_path: Path, env_file_path: Path ) -> str: diff --git a/kiauh/modules/klipper/klipper_remove.py b/kiauh/modules/klipper/klipper_remove.py new file mode 100644 index 0000000..07f2fe9 --- /dev/null +++ b/kiauh/modules/klipper/klipper_remove.py @@ -0,0 +1,133 @@ +#!/usr/bin/env python3 + +# ======================================================================= # +# Copyright (C) 2020 - 2023 Dominik Willner # +# # +# This file is part of KIAUH - Klipper Installation And Update Helper # +# https://github.com/dw-0/kiauh # +# # +# This file may be distributed under the terms of the GNU GPLv3 license # +# ======================================================================= # + +import shutil +from typing import List, Union + +from kiauh.core.instance_manager.instance_manager import InstanceManager +from kiauh.modules.klipper import KLIPPER_DIR, KLIPPER_ENV_DIR +from kiauh.modules.klipper.klipper import Klipper +from kiauh.modules.klipper.klipper_dialogs import print_instance_overview +from kiauh.utils.filesystem_utils import remove_file +from kiauh.utils.input_utils import get_selection_input +from kiauh.utils.logger import Logger + + +def run_klipper_removal( + remove_service: bool, + remove_dir: bool, + remove_env: bool, + delete_logs: bool, +) -> None: + im = InstanceManager(Klipper) + + if remove_service: + Logger.print_status("Removing Klipper instances ...") + if im.instances: + instances_to_remove = select_instances_to_remove(im.instances) + remove_instances(im, instances_to_remove) + else: + Logger.print_info("No Klipper Services installed! Skipped ...") + + im.find_instances() + if (remove_dir or remove_env) and im.instances: + Logger.print_warn("There are still other Klipper services installed!") + Logger.print_warn("Therefor the following parts cannot be removed:") + Logger.print_warn( + """ + ● Klipper local repository + ● Klipper Python environment + """, + False, + ) + else: + if remove_dir: + Logger.print_status("Removing Klipper local repository ...") + remove_klipper_dir() + if remove_env: + Logger.print_status("Removing Klipper Python environment ...") + remove_klipper_env() + + # delete klipper logs of all instances + if delete_logs: + Logger.print_status("Removing all Klipper logs ...") + delete_klipper_logs(im.instances) + + +def select_instances_to_remove( + instances: List[Klipper], +) -> Union[List[Klipper], None]: + print_instance_overview(instances, True, True) + + options = [str(i) for i in range(len(instances))] + options.extend(["a", "A", "b", "B"]) + + selection = get_selection_input("Select Klipper instance to remove", options) + + instances_to_remove = [] + if selection == "b".lower(): + return None + elif selection == "a".lower(): + instances_to_remove.extend(instances) + else: + instance = instances[int(selection)] + instances_to_remove.append(instance) + + return instances_to_remove + + +def remove_instances( + instance_manager: InstanceManager, + instance_list: List[Klipper], +) -> None: + for instance in instance_list: + Logger.print_status(f"Removing instance {instance.get_service_file_name()} ...") + instance_manager.current_instance = instance + instance_manager.stop_instance() + instance_manager.disable_instance() + instance_manager.delete_instance() + + instance_manager.reload_daemon() + + +def remove_klipper_dir() -> None: + if not KLIPPER_DIR.exists(): + Logger.print_info(f"'{KLIPPER_DIR}' does not exist. Skipped ...") + return + + try: + shutil.rmtree(KLIPPER_DIR) + except OSError as e: + Logger.print_error(f"Unable to delete '{KLIPPER_DIR}':\n{e}") + + +def remove_klipper_env() -> None: + if not KLIPPER_ENV_DIR.exists(): + Logger.print_info(f"'{KLIPPER_ENV_DIR}' does not exist. Skipped ...") + return + + try: + shutil.rmtree(KLIPPER_ENV_DIR) + except OSError as e: + Logger.print_error(f"Unable to delete '{KLIPPER_ENV_DIR}':\n{e}") + + +def delete_klipper_logs(instances: List[Klipper]) -> None: + all_logfiles = [] + for instance in instances: + all_logfiles = list(instance.log_dir.glob("klippy.log*")) + if not all_logfiles: + Logger.print_info("No Klipper logs found. Skipped ...") + return + + for log in all_logfiles: + Logger.print_status(f"Remove '{log}'") + remove_file(log) diff --git a/kiauh/modules/klipper/menus/__init__.py b/kiauh/modules/klipper/menus/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/kiauh/modules/klipper/menus/klipper_remove_menu.py b/kiauh/modules/klipper/menus/klipper_remove_menu.py new file mode 100644 index 0000000..ed9740f --- /dev/null +++ b/kiauh/modules/klipper/menus/klipper_remove_menu.py @@ -0,0 +1,109 @@ +#!/usr/bin/env python3 + +# ======================================================================= # +# Copyright (C) 2020 - 2023 Dominik Willner # +# # +# This file is part of KIAUH - Klipper Installation And Update Helper # +# https://github.com/dw-0/kiauh # +# # +# This file may be distributed under the terms of the GNU GPLv3 license # +# ======================================================================= # + +import textwrap + +from kiauh.core.menus import BACK_HELP_FOOTER +from kiauh.core.menus.base_menu import BaseMenu +from kiauh.modules.klipper import klipper_remove +from kiauh.modules.moonraker import moonraker_remove +from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN + + +class KlipperRemoveMenu(BaseMenu): + def __init__(self): + super().__init__( + header=False, + options={ + 0: self.toggle_all, + 1: self.toggle_remove_klipper_service, + 2: self.toggle_remove_klipper_dir, + 3: self.toggle_remove_klipper_env, + 4: self.toggle_delete_klipper_logs, + 5: self.run_removal_process, + }, + footer_type=BACK_HELP_FOOTER, + ) + self.remove_klipper_service = False + self.remove_klipper_dir = False + self.remove_klipper_env = False + self.delete_klipper_logs = False + + def print_menu(self) -> None: + header = " [ Remove Klipper ] " + color = COLOR_RED + count = 62 - len(color) - len(RESET_FORMAT) + checked = f"[{COLOR_CYAN}x{RESET_FORMAT}]" + unchecked = "[ ]" + o1 = checked if self.remove_klipper_service else unchecked + o2 = checked if self.remove_klipper_dir else unchecked + o3 = checked if self.remove_klipper_env else unchecked + o4 = checked if self.delete_klipper_logs else unchecked + menu = textwrap.dedent( + f""" + /=======================================================\\ + | {color}{header:~^{count}}{RESET_FORMAT} | + |-------------------------------------------------------| + | Enter a number and hit enter to select / deselect | + | the specific option for removal. | + |-------------------------------------------------------| + | 0) Select everything | + |-------------------------------------------------------| + | 1) {o1} Remove Service | + | 2) {o2} Remove Local Repository | + | 3) {o3} Remove Python Environment | + | 4) {o4} Delete all Log-Files | + |-------------------------------------------------------| + | 5) Continue | + """ + )[1:] + print(menu, end="") + + def toggle_all(self) -> None: + self.remove_klipper_service = True + self.remove_klipper_dir = True + self.remove_klipper_env = True + self.delete_klipper_logs = True + + def toggle_remove_klipper_service(self) -> None: + self.remove_klipper_service = not self.remove_klipper_service + + def toggle_remove_klipper_dir(self) -> None: + self.remove_klipper_dir = not self.remove_klipper_dir + + def toggle_remove_klipper_env(self) -> None: + self.remove_klipper_env = not self.remove_klipper_env + + def toggle_delete_klipper_logs(self) -> None: + self.delete_klipper_logs = not self.delete_klipper_logs + + def run_removal_process(self) -> None: + if ( + not self.remove_klipper_service + and not self.remove_klipper_dir + and not self.remove_klipper_env + and not self.delete_klipper_logs + ): + error = f"{COLOR_RED}Nothing selected! Select options to remove first.{RESET_FORMAT}" + print(error) + return + + klipper_remove.run_klipper_removal( + self.remove_klipper_service, + self.remove_klipper_dir, + self.remove_klipper_env, + self.delete_klipper_logs, + ) + + self.remove_klipper_service = False + self.remove_klipper_dir = False + self.remove_klipper_env = False + self.delete_klipper_logs = False