Compare commits

...

5 Commits

Author SHA1 Message Date
dw-0
6225ee59d0 fix: add sysd_dir to base_folders
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-31 08:18:22 +02:00
dw-0
535c50a3ac fix: better check for still existing services during removal
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-31 08:17:59 +02:00
dw-0
e26315f469 chore: remove unused menu attribute from Option class
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-25 20:25:12 +02:00
dw-0
b77f1356bf chore(extension): update print menu to use new style
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-25 20:07:13 +02:00
dw-0
d201f54cee refactor(extension): fix typing
Signed-off-by: Dominik Willner <th33xitus@gmail.com>
2024-08-25 20:03:56 +02:00
19 changed files with 139 additions and 123 deletions

View File

@@ -18,6 +18,7 @@ from core.logger import Logger
from utils.fs_utils import run_remove_routines from utils.fs_utils import run_remove_routines
from utils.input_utils import get_selection_input from utils.input_utils import get_selection_input
from utils.instance_utils import get_instances from utils.instance_utils import get_instances
from utils.sys_utils import unit_file_exists
def run_klipper_removal( def run_klipper_removal(
@@ -35,7 +36,7 @@ def run_klipper_removal(
else: else:
Logger.print_info("No Klipper Services installed! Skipped ...") Logger.print_info("No Klipper Services installed! Skipped ...")
if (remove_dir or remove_env) and klipper_instances: if (remove_dir or remove_env) and unit_file_exists("klipper", suffix="service"):
Logger.print_info("There are still other Klipper services installed:") Logger.print_info("There are still other Klipper services installed:")
Logger.print_info(f"'{KLIPPER_DIR}' was not removed.", prefix=False) Logger.print_info(f"'{KLIPPER_DIR}' was not removed.", prefix=False)
Logger.print_info(f"'{KLIPPER_ENV_DIR}' was not removed.", prefix=False) Logger.print_info(f"'{KLIPPER_ENV_DIR}' was not removed.", prefix=False)

View File

@@ -35,11 +35,11 @@ class KlipperRemoveMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"a": Option(method=self.toggle_all, menu=False), "a": Option(method=self.toggle_all),
"1": Option(method=self.toggle_remove_klipper_service, menu=False), "1": Option(method=self.toggle_remove_klipper_service),
"2": Option(method=self.toggle_remove_klipper_dir, menu=False), "2": Option(method=self.toggle_remove_klipper_dir),
"3": Option(method=self.toggle_remove_klipper_env, menu=False), "3": Option(method=self.toggle_remove_klipper_env),
"c": Option(method=self.run_removal_process, menu=False), "c": Option(method=self.run_removal_process),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -47,10 +47,10 @@ class KlipperBuildFirmwareMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
if len(self.missing_deps) == 0: if len(self.missing_deps) == 0:
self.input_label_txt = "Press ENTER to continue" self.input_label_txt = "Press ENTER to continue"
self.default_option = Option(method=self.start_build_process, menu=False) self.default_option = Option(method=self.start_build_process)
else: else:
self.input_label_txt = "Press ENTER to install dependencies" self.input_label_txt = "Press ENTER to install dependencies"
self.default_option = Option(method=self.install_missing_deps, menu=False) self.default_option = Option(method=self.install_missing_deps)
def print_menu(self) -> None: def print_menu(self) -> None:
header = " [ Build Firmware Menu ] " header = " [ Build Firmware Menu ] "

View File

@@ -61,8 +61,8 @@ class KlipperFlashMethodMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"1": Option(self.select_regular, menu=False), "1": Option(self.select_regular),
"2": Option(self.select_sdcard, menu=False), "2": Option(self.select_sdcard),
} }
def print_menu(self) -> None: def print_menu(self) -> None:
@@ -123,10 +123,10 @@ class KlipperFlashCommandMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"1": Option(self.select_flash, menu=False), "1": Option(self.select_flash),
"2": Option(self.select_serialflash, menu=False), "2": Option(self.select_serialflash),
} }
self.default_option = Option(self.select_flash, menu=False) self.default_option = Option(self.select_flash)
def print_menu(self) -> None: def print_menu(self) -> None:
menu = textwrap.dedent( menu = textwrap.dedent(
@@ -174,9 +174,9 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"1": Option(method=self.select_usb, menu=False), "1": Option(method=self.select_usb),
"2": Option(method=self.select_dfu, menu=False), "2": Option(method=self.select_dfu),
"3": Option(method=self.select_usb_dfu, menu=False), "3": Option(method=self.select_usb_dfu),
} }
def print_menu(self) -> None: def print_menu(self) -> None:
@@ -393,11 +393,11 @@ class KlipperFlashOverviewMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"Y": Option(self.execute_flash, menu=False), "Y": Option(self.execute_flash),
"N": Option(self.abort_process, menu=False), "N": Option(self.abort_process),
} }
self.default_option = Option(self.execute_flash, menu=False) self.default_option = Option(self.execute_flash)
def print_menu(self) -> None: def print_menu(self) -> None:
header = "!!! ATTENTION !!!" header = "!!! ATTENTION !!!"

View File

@@ -35,12 +35,12 @@ class MoonrakerRemoveMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"a": Option(method=self.toggle_all, menu=False), "a": Option(method=self.toggle_all),
"1": Option(method=self.toggle_remove_moonraker_service, menu=False), "1": Option(method=self.toggle_remove_moonraker_service),
"2": Option(method=self.toggle_remove_moonraker_dir, menu=False), "2": Option(method=self.toggle_remove_moonraker_dir),
"3": Option(method=self.toggle_remove_moonraker_env, menu=False), "3": Option(method=self.toggle_remove_moonraker_env),
"4": Option(method=self.toggle_remove_moonraker_polkit, menu=False), "4": Option(method=self.toggle_remove_moonraker_polkit),
"c": Option(method=self.run_removal_process, menu=False), "c": Option(method=self.run_removal_process),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -19,6 +19,7 @@ from core.logger import Logger
from utils.fs_utils import run_remove_routines from utils.fs_utils import run_remove_routines
from utils.input_utils import get_selection_input from utils.input_utils import get_selection_input
from utils.instance_utils import get_instances from utils.instance_utils import get_instances
from utils.sys_utils import unit_file_exists
def run_moonraker_removal( def run_moonraker_removal(
@@ -37,7 +38,8 @@ def run_moonraker_removal(
else: else:
Logger.print_info("No Moonraker Services installed! Skipped ...") Logger.print_info("No Moonraker Services installed! Skipped ...")
if (remove_polkit or remove_dir or remove_env) and instances: delete_remaining: bool = remove_polkit or remove_dir or remove_env
if delete_remaining and unit_file_exists("moonraker", suffix="service"):
Logger.print_info("There are still other Moonraker services installed") Logger.print_info("There are still other Moonraker services installed")
Logger.print_info( Logger.print_info(
"● Moonraker PolicyKit rules were not removed.", prefix=False "● Moonraker PolicyKit rules were not removed.", prefix=False

View File

@@ -38,11 +38,11 @@ class ClientRemoveMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"a": Option(method=self.toggle_all, menu=False), "a": Option(method=self.toggle_all),
"1": Option(method=self.toggle_rm_client, menu=False), "1": Option(method=self.toggle_rm_client),
"2": Option(method=self.toggle_rm_client_config, menu=False), "2": Option(method=self.toggle_rm_client_config),
"3": Option(method=self.toggle_backup_config_json, menu=False), "3": Option(method=self.toggle_backup_config_json),
"c": Option(method=self.run_removal_process, menu=False), "c": Option(method=self.run_removal_process),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -48,6 +48,7 @@ class BaseInstance:
self.log_dir, self.log_dir,
self.gcodes_dir, self.gcodes_dir,
self.comms_dir, self.comms_dir,
self.sysd_dir,
] ]
def _set_is_legacy_instance(self) -> bool: def _set_is_legacy_instance(self) -> bool:

View File

@@ -18,13 +18,11 @@ class Option:
""" """
Represents a menu option. Represents a menu option.
:param method: Method that will be used to call the menu option :param method: Method that will be used to call the menu option
:param menu: Flag for singaling that another menu will be opened
:param opt_index: Can be used to pass the user input to the menu option :param opt_index: Can be used to pass the user input to the menu option
:param opt_data: Can be used to pass any additional data to the menu option :param opt_data: Can be used to pass any additional data to the menu option
""" """
method: Callable | None = None method: Callable | None = None
menu: bool = False
opt_index: str = "" opt_index: str = ""
opt_data: Any = None opt_data: Any = None

View File

@@ -43,13 +43,13 @@ class AdvancedMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"1": Option(method=self.build, menu=True), "1": Option(method=self.build),
"2": Option(method=self.flash, menu=False), "2": Option(method=self.flash),
"3": Option(method=self.build_flash, menu=False), "3": Option(method=self.build_flash),
"4": Option(method=self.get_id, menu=False), "4": Option(method=self.get_id),
"5": Option(method=self.klipper_rollback, menu=True), "5": Option(method=self.klipper_rollback),
"6": Option(method=self.moonraker_rollback, menu=True), "6": Option(method=self.moonraker_rollback),
"7": Option(method=self.change_hostname, menu=True), "7": Option(method=self.change_hostname),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -43,15 +43,15 @@ class BackupMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"1": Option(method=self.backup_klipper, menu=False), "1": Option(method=self.backup_klipper),
"2": Option(method=self.backup_moonraker, menu=False), "2": Option(method=self.backup_moonraker),
"3": Option(method=self.backup_printer_config, menu=False), "3": Option(method=self.backup_printer_config),
"4": Option(method=self.backup_moonraker_db, menu=False), "4": Option(method=self.backup_moonraker_db),
"5": Option(method=self.backup_mainsail, menu=False), "5": Option(method=self.backup_mainsail),
"6": Option(method=self.backup_fluidd, menu=False), "6": Option(method=self.backup_fluidd),
"7": Option(method=self.backup_mainsail_config, menu=False), "7": Option(method=self.backup_mainsail_config),
"8": Option(method=self.backup_fluidd_config, menu=False), "8": Option(method=self.backup_fluidd_config),
"9": Option(method=self.backup_klipperscreen, menu=False), "9": Option(method=self.backup_klipperscreen),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -123,12 +123,12 @@ class BaseMenu(metaclass=PostInitCaller):
# conditionally add options based on footer type # conditionally add options based on footer type
if self.footer_type is FooterType.QUIT: if self.footer_type is FooterType.QUIT:
self.options["q"] = Option(method=self.__exit, menu=False) self.options["q"] = Option(method=self.__exit)
if self.footer_type is FooterType.BACK: if self.footer_type is FooterType.BACK:
self.options["b"] = Option(method=self.__go_back, menu=False) self.options["b"] = Option(method=self.__go_back)
if self.footer_type is FooterType.BACK_HELP: if self.footer_type is FooterType.BACK_HELP:
self.options["b"] = Option(method=self.__go_back, menu=False) self.options["b"] = Option(method=self.__go_back)
self.options["h"] = Option(method=self.__go_to_help, menu=False) self.options["h"] = Option(method=self.__go_to_help)
# if defined, add the default option to the options dict # if defined, add the default option to the options dict
if self.default_option is not None: if self.default_option is not None:
self.options[""] = self.default_option self.options[""] = self.default_option
@@ -184,7 +184,10 @@ class BaseMenu(metaclass=PostInitCaller):
:return: Option, str or None :return: Option, str or None
""" """
usr_input = usr_input.lower() usr_input = usr_input.lower()
option = self.options.get(usr_input, Option(None, False, "", None)) option = self.options.get(
usr_input,
Option(method=None, opt_index="", opt_data=None),
)
# if option/usr_input is None/empty string, we execute the menus default option if specified # if option/usr_input is None/empty string, we execute the menus default option if specified
if (option is None or usr_input == "") and self.default_option is not None: if (option is None or usr_input == "") and self.default_option is not None:

View File

@@ -40,16 +40,16 @@ class InstallMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"1": Option(method=self.install_klipper, menu=False), "1": Option(method=self.install_klipper),
"2": Option(method=self.install_moonraker, menu=False), "2": Option(method=self.install_moonraker),
"3": Option(method=self.install_mainsail, menu=False), "3": Option(method=self.install_mainsail),
"4": Option(method=self.install_fluidd, menu=False), "4": Option(method=self.install_fluidd),
"5": Option(method=self.install_mainsail_config, menu=False), "5": Option(method=self.install_mainsail_config),
"6": Option(method=self.install_fluidd_config, menu=False), "6": Option(method=self.install_fluidd_config),
"7": Option(method=self.install_klipperscreen, menu=False), "7": Option(method=self.install_klipperscreen),
"8": Option(method=self.install_mobileraker, menu=False), "8": Option(method=self.install_mobileraker),
"9": Option(method=self.install_crowsnest, menu=False), "9": Option(method=self.install_crowsnest),
"10": Option(method=self.install_octoeverywhere, menu=False), "10": Option(method=self.install_octoeverywhere),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -66,14 +66,14 @@ class MainMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"0": Option(method=self.log_upload_menu, menu=True), "0": Option(method=self.log_upload_menu),
"1": Option(method=self.install_menu, menu=True), "1": Option(method=self.install_menu),
"2": Option(method=self.update_menu, menu=True), "2": Option(method=self.update_menu),
"3": Option(method=self.remove_menu, menu=True), "3": Option(method=self.remove_menu),
"4": Option(method=self.advanced_menu, menu=True), "4": Option(method=self.advanced_menu),
"5": Option(method=self.backup_menu, menu=True), "5": Option(method=self.backup_menu),
"e": Option(method=self.extension_menu, menu=True), "e": Option(method=self.extension_menu),
"s": Option(method=self.settings_menu, menu=True), "s": Option(method=self.settings_menu),
} }
def _init_status(self) -> None: def _init_status(self) -> None:

View File

@@ -41,14 +41,14 @@ class RemoveMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"1": Option(method=self.remove_klipper, menu=True), "1": Option(method=self.remove_klipper),
"2": Option(method=self.remove_moonraker, menu=True), "2": Option(method=self.remove_moonraker),
"3": Option(method=self.remove_mainsail, menu=True), "3": Option(method=self.remove_mainsail),
"4": Option(method=self.remove_fluidd, menu=True), "4": Option(method=self.remove_fluidd),
"5": Option(method=self.remove_klipperscreen, menu=True), "5": Option(method=self.remove_klipperscreen),
"6": Option(method=self.remove_mobileraker, menu=True), "6": Option(method=self.remove_mobileraker),
"7": Option(method=self.remove_crowsnest, menu=True), "7": Option(method=self.remove_crowsnest),
"8": Option(method=self.remove_octoeverywhere, menu=True), "8": Option(method=self.remove_octoeverywhere),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -48,11 +48,11 @@ class SettingsMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"1": Option(method=self.set_klipper_repo, menu=True), "1": Option(method=self.set_klipper_repo),
"2": Option(method=self.set_moonraker_repo, menu=True), "2": Option(method=self.set_moonraker_repo),
"3": Option(method=self.toggle_mainsail_release, menu=True), "3": Option(method=self.toggle_mainsail_release),
"4": Option(method=self.toggle_fluidd_release, menu=False), "4": Option(method=self.toggle_fluidd_release),
"5": Option(method=self.toggle_backup_before_update, menu=False), "5": Option(method=self.toggle_backup_before_update),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -50,13 +50,13 @@ from core.logger import DialogType, Logger
from core.menus import Option from core.menus import Option
from core.menus.base_menu import BaseMenu from core.menus.base_menu import BaseMenu
from core.spinner import Spinner from core.spinner import Spinner
from core.types import ComponentStatus
from utils.input_utils import get_confirm from utils.input_utils import get_confirm
from utils.sys_utils import ( from utils.sys_utils import (
get_upgradable_packages, get_upgradable_packages,
update_system_package_lists, update_system_package_lists,
upgrade_system_packages, upgrade_system_packages,
) )
from core.types import ComponentStatus
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@@ -102,18 +102,18 @@ class UpdateMenu(BaseMenu):
def set_options(self) -> None: def set_options(self) -> None:
self.options = { self.options = {
"a": Option(self.update_all, menu=False), "a": Option(self.update_all),
"1": Option(self.update_klipper, menu=False), "1": Option(self.update_klipper),
"2": Option(self.update_moonraker, menu=False), "2": Option(self.update_moonraker),
"3": Option(self.update_mainsail, menu=False), "3": Option(self.update_mainsail),
"4": Option(self.update_fluidd, menu=False), "4": Option(self.update_fluidd),
"5": Option(self.update_mainsail_config, menu=False), "5": Option(self.update_mainsail_config),
"6": Option(self.update_fluidd_config, menu=False), "6": Option(self.update_fluidd_config),
"7": Option(self.update_klipperscreen, menu=False), "7": Option(self.update_klipperscreen),
"8": Option(self.update_mobileraker, menu=False), "8": Option(self.update_mobileraker),
"9": Option(self.update_crowsnest, menu=False), "9": Option(self.update_crowsnest),
"10": Option(self.update_octoeverywhere, menu=False), "10": Option(self.update_octoeverywhere),
"11": Option(self.upgrade_system_packages, menu=False), "11": Option(self.upgrade_system_packages),
} }
def print_menu(self) -> None: def print_menu(self) -> None:

View File

@@ -119,12 +119,12 @@ class ExtensionSubmenu(BaseMenu):
) )
def set_options(self) -> None: def set_options(self) -> None:
self.options["1"] = Option(self.extension.install_extension, menu=False) self.options["1"] = Option(self.extension.install_extension)
if self.extension.metadata.get("updates"): if self.extension.metadata.get("updates"):
self.options["2"] = Option(self.extension.update_extension, menu=False) self.options["2"] = Option(self.extension.update_extension)
self.options["3"] = Option(self.extension.remove_extension, menu=False) self.options["3"] = Option(self.extension.remove_extension)
else: else:
self.options["2"] = Option(self.extension.remove_extension, menu=False) self.options["2"] = Option(self.extension.remove_extension)
def print_menu(self) -> None: def print_menu(self) -> None:
header = f" [ {self.extension.metadata.get('display_name')} ] " header = f" [ {self.extension.metadata.get('display_name')} ] "

View File

@@ -12,7 +12,8 @@ import csv
import shutil import shutil
import textwrap import textwrap
import urllib.request import urllib.request
from typing import List, Type, TypedDict, Union from dataclasses import dataclass
from typing import Any, Dict, List, Type, Union
from components.klipper.klipper import Klipper from components.klipper.klipper import Klipper
from components.klipper.klipper_dialogs import ( from components.klipper.klipper_dialogs import (
@@ -31,7 +32,8 @@ from utils.input_utils import get_selection_input
from utils.instance_utils import get_instances from utils.instance_utils import get_instances
class ThemeData(TypedDict): @dataclass
class ThemeData:
name: str name: str
short_note: str short_note: str
author: str author: str
@@ -102,36 +104,45 @@ class MainsailThemeInstallMenu(BaseMenu):
count = 62 - len(color) - len(RESET_FORMAT) count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent( menu = textwrap.dedent(
f""" f"""
/=======================================================\\ ╔═══════════════════════════════════════════════════════╗
| {color}{header:~^{count}}{RESET_FORMAT} | {color}{header:~^{count}}{RESET_FORMAT}
|-------------------------------------------------------| ╟───────────────────────────────────────────────────────╢
| {line1:<62} | {line1:<62}
| https://docs.mainsail.xyz/theming/themes | https://docs.mainsail.xyz/theming/themes
|-------------------------------------------------------| ╟───────────────────────────────────────────────────────╢
""" """
)[1:] )[1:]
for i, theme in enumerate(self.themes): for i, theme in enumerate(self.themes):
i = f" {i}" if i < 10 else f"{i}" j: str = f" {i}" if i < 10 else f"{i}"
row = f"{i}) [{theme.get('name')}]" row: str = f"{j}) [{theme.name}]"
menu += f"| {row:<53} |\n" menu += f" {row:<53} \n"
print(menu, end="") print(menu, end="")
def load_themes(self) -> List[ThemeData]: def load_themes(self) -> List[ThemeData]:
with urllib.request.urlopen(self.THEMES_URL) as response: with urllib.request.urlopen(self.THEMES_URL) as response:
themes: List[ThemeData] = [] themes: List[ThemeData] = []
csv_data: str = response.read().decode().splitlines() content: str = response.read().decode()
csv_reader = csv.DictReader(csv_data, delimiter=",") csv_data: List[str] = content.splitlines()
fieldnames = ["name", "short_note", "author", "repo"]
csv_reader = csv.DictReader(csv_data, fieldnames=fieldnames, delimiter=",")
next(csv_reader) # skip the header of the csv file
for row in csv_reader: for row in csv_reader:
row: ThemeData = row row: Dict[str, str] # type: ignore
themes.append(row) theme: ThemeData = ThemeData(**row)
themes.append(theme)
return themes return themes
def install_theme(self, **kwargs): def install_theme(self, **kwargs: Any):
index = int(kwargs.get("opt_index")) opt_index: str | None = kwargs.get("opt_index", None)
if not opt_index:
raise ValueError("No option index provided")
index: int = int(opt_index)
theme_data: ThemeData = self.themes[index] theme_data: ThemeData = self.themes[index]
theme_author: str = theme_data.get("author") theme_author: str = theme_data.author
theme_repo: str = theme_data.get("repo") theme_repo: str = theme_data.repo
theme_repo_url: str = f"https://github.com/{theme_author}/{theme_repo}" theme_repo_url: str = f"https://github.com/{theme_author}/{theme_repo}"
print_instance_overview( print_instance_overview(
@@ -149,9 +160,9 @@ class MainsailThemeInstallMenu(BaseMenu):
for printer in printer_list: for printer in printer_list:
git_clone_wrapper(theme_repo_url, printer.cfg_dir.joinpath(".theme")) git_clone_wrapper(theme_repo_url, printer.cfg_dir.joinpath(".theme"))
if len(theme_data.get("short_note", "")) > 1: if len(theme_data.short_note) > 1:
Logger.print_warn("Info from the creator:", prefix=False, start="\n") Logger.print_warn("Info from the creator:", prefix=False, start="\n")
Logger.print_info(theme_data.get("short_note"), prefix=False, end="\n\n") Logger.print_info(theme_data.short_note, prefix=False, end="\n\n")
def get_printer_selection( def get_printer_selection(