Compare commits

..

1 Commits

Author SHA1 Message Date
dw-0
0d7074f86f Merge e50ce1fc71 into f2691f33d3 2024-03-31 18:58:07 +02:00
7 changed files with 64 additions and 159 deletions

View File

@@ -7,7 +7,7 @@
# This file may be distributed under the terms of the GNU GPLv3 license #
# ======================================================================= #
from dataclasses import field
from dataclasses import field, dataclass
from enum import Enum
from typing import Union, List
@@ -28,14 +28,15 @@ class ConnectionType(Enum):
UART = "UART"
@dataclass
class FlashOptions:
_instance = None
_flash_method: Union[FlashMethod, None] = None
_flash_command: Union[FlashCommand, None] = None
_connection_type: Union[ConnectionType, None] = None
_mcu_list: List[str] = field(default_factory=list)
_selected_mcu: str = ""
_selected_board: str = ""
flash_method: Union[FlashMethod, None] = None
flash_command: Union[FlashCommand, None] = None
connection_type: Union[ConnectionType, None] = None
mcu_list: List[str] = field(default_factory=list)
selected_mcu: str = ""
selected_board: str = ""
def __new__(cls, *args, **kwargs):
if not cls._instance:
@@ -45,51 +46,3 @@ class FlashOptions:
@classmethod
def destroy(cls):
cls._instance = None
@property
def flash_method(self) -> Union[FlashMethod, None]:
return self._flash_method
@flash_method.setter
def flash_method(self, value: Union[FlashMethod, None]):
self._flash_method = value
@property
def flash_command(self) -> Union[FlashCommand, None]:
return self._flash_command
@flash_command.setter
def flash_command(self, value: Union[FlashCommand, None]):
self._flash_command = value
@property
def connection_type(self) -> Union[ConnectionType, None]:
return self._connection_type
@connection_type.setter
def connection_type(self, value: Union[ConnectionType, None]):
self._connection_type = value
@property
def mcu_list(self) -> List[str]:
return self._mcu_list
@mcu_list.setter
def mcu_list(self, value: List[str]) -> None:
self._mcu_list = value
@property
def selected_mcu(self) -> str:
return self._selected_mcu
@selected_mcu.setter
def selected_mcu(self, value: str) -> None:
self._selected_mcu = value
@property
def selected_board(self) -> str:
return self._selected_board
@selected_board.setter
def selected_board(self, value: str) -> None:
self._selected_board = value

View File

@@ -39,7 +39,7 @@ class KlipperFlashMethodMenu(BaseMenu):
self.options = {
"1": self.select_regular,
"2": self.select_sdcard,
"h": self.help_menu,
"h": lambda: KlipperFlashMethodHelpMenu(self).run(),
}
self.input_label_txt = "Select flash method"
self.footer_type = FooterType.BACK_HELP
@@ -78,9 +78,6 @@ class KlipperFlashMethodMenu(BaseMenu):
def goto_next_menu(self, **kwargs):
KlipperFlashCommandMenu(previous_menu=self).run()
def help_menu(self, **kwargs):
KlipperFlashMethodHelpMenu(previous_menu=self).run()
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
@@ -92,7 +89,7 @@ class KlipperFlashCommandMenu(BaseMenu):
self.options = {
"1": self.select_flash,
"2": self.select_serialflash,
"h": self.help_menu,
"h": lambda: KlipperFlashCommandHelpMenu(previous_menu=self).run(),
}
self.default_option = self.select_flash
self.input_label_txt = "Select flash command"
@@ -124,9 +121,6 @@ class KlipperFlashCommandMenu(BaseMenu):
def goto_next_menu(self, **kwargs):
KlipperSelectMcuConnectionMenu(previous_menu=self).run()
def help_menu(self, **kwargs):
KlipperFlashCommandHelpMenu(previous_menu=self).run()
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
@@ -139,7 +133,7 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
"1": self.select_usb,
"2": self.select_dfu,
"3": self.select_usb_dfu,
"h": self.help_menu,
"h": lambda: KlipperMcuConnectionHelpMenu(previous_menu=self).run(),
}
self.input_label_txt = "Select connection type"
self.footer_type = FooterType.BACK_HELP
@@ -190,6 +184,8 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
Logger.print_status("Identifying MCU connected via USB in DFU mode ...")
self.flash_options.mcu_list = find_usb_dfu_device()
print(self.flash_options.mcu_list)
if len(self.flash_options.mcu_list) < 1:
Logger.print_warn("No MCUs found!")
Logger.print_warn("Make sure they are connected and repeat this step.")
@@ -199,9 +195,6 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
def goto_next_menu(self, **kwargs):
KlipperSelectMcuIdMenu(previous_menu=self).run()
def help_menu(self, **kwargs):
KlipperMcuConnectionHelpMenu(previous_menu=self).run()
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
@@ -212,6 +205,7 @@ class KlipperSelectMcuIdMenu(BaseMenu):
self.previous_menu: BaseMenu = previous_menu
self.flash_options = FlashOptions()
self.mcu_list = self.flash_options.mcu_list
print(self.mcu_list)
options = {f"{index}": self.flash_mcu for index in range(len(self.mcu_list))}
self.options = options
self.input_label_txt = "Select MCU to flash"

View File

@@ -17,7 +17,6 @@ from core.menus.base_menu import BaseMenu
from utils.constants import COLOR_YELLOW, RESET_FORMAT
# noinspection PyUnusedLocal
class AdvancedMenu(BaseMenu):
def __init__(self, previous_menu: BaseMenu):
super().__init__()
@@ -27,9 +26,9 @@ class AdvancedMenu(BaseMenu):
"1": None,
"2": None,
"3": None,
"4": self.flash,
"4": lambda: KlipperFlashMethodMenu(previous_menu=self).run(),
"5": None,
"6": self.get_id,
"6": lambda: KlipperSelectMcuConnectionMenu(previous_menu=self).run(),
}
def print_menu(self):
@@ -53,9 +52,3 @@ class AdvancedMenu(BaseMenu):
"""
)[1:]
print(menu, end="")
def flash(self, **kwargs):
KlipperFlashMethodMenu(previous_menu=self).run()
def get_id(self, **kwargs):
KlipperSelectMcuConnectionMenu(previous_menu=self).run()

View File

@@ -13,7 +13,7 @@ import subprocess
import sys
import textwrap
from abc import abstractmethod, ABC
from typing import Dict, Union, Callable, Type, Tuple
from typing import Dict, Union, Callable, Type
from core.menus import FooterType, NAVI_OPTIONS, ExitAppException, GoBackException
from utils.constants import (
@@ -129,7 +129,7 @@ class BaseMenu(ABC):
self.print_menu()
self.print_footer()
def validate_user_input(self, usr_input: str) -> Tuple[Callable, str]:
def validate_user_input(self, usr_input: str) -> Callable:
"""
Validate the user input and either return an Option, a string or None
:param usr_input: The user input in form of a string
@@ -148,16 +148,16 @@ class BaseMenu(ABC):
elif usr_input == "b":
raise GoBackException()
elif usr_input == "h":
return option, usr_input
return option
# if usr_input is None or an empty string, we execute the menues default option if specified
if usr_input == "" and self.default_option is not None:
return self.default_option, usr_input
return self.default_option
# user selected a regular option
return option, usr_input
return option
def handle_user_input(self) -> Tuple[Callable, str]:
def handle_user_input(self) -> Callable:
"""Handle the user input, return the validated input or print an error."""
while True:
print(f"{COLOR_CYAN}###### {self.input_label_txt}: {RESET_FORMAT}", end="")
@@ -173,8 +173,7 @@ class BaseMenu(ABC):
while True:
try:
self.display_menu()
option = self.handle_user_input()
option[0](opt_index=option[1])
self.handle_user_input()()
except GoBackException:
return
except ExitAppException:

View File

@@ -12,10 +12,10 @@ import inspect
import json
import textwrap
from pathlib import Path
from typing import Type, Dict
from typing import List
from core.base_extension import BaseExtension
from core.menus.base_menu import BaseMenu
from core.menus.base_menu import BaseMenu, Options
from utils.constants import RESET_FORMAT, COLOR_CYAN, COLOR_YELLOW
@@ -27,44 +27,42 @@ class ExtensionsMenu(BaseMenu):
self.previous_menu: BaseMenu = previous_menu
self.extensions = self.discover_extensions()
self.options = {ext: self.extension_submenu for ext in self.extensions}
self.options: Options = self.get_options(self.extensions)
def discover_extensions(self) -> Dict[str, BaseExtension]:
ext_dict = {}
def discover_extensions(self) -> List[BaseExtension]:
extensions = []
extensions_dir = Path(__file__).resolve().parents[2].joinpath("extensions")
for ext in extensions_dir.iterdir():
metadata_json = Path(ext).joinpath("metadata.json")
for extension in extensions_dir.iterdir():
metadata_json = Path(extension).joinpath("metadata.json")
if not metadata_json.exists():
continue
try:
with open(metadata_json, "r") as m:
# read extension metadata from json
metadata = json.load(m).get("metadata")
module_name = metadata.get("module")
module_path = f"kiauh.extensions.{ext.name}.{module_name}"
# get the class name of the extension
ext_class: Type[BaseExtension] = inspect.getmembers(
importlib.import_module(module_path),
module_name = (
f"kiauh.extensions.{extension.name}.{metadata.get('module')}"
)
name, extension = inspect.getmembers(
importlib.import_module(module_name),
predicate=lambda o: inspect.isclass(o)
and issubclass(o, BaseExtension)
and o != BaseExtension,
)[0][1]
# instantiate the extension with its metadata and add to dict
ext_instance: BaseExtension = ext_class(metadata)
ext_dict[f"{metadata.get('index')}"] = ext_instance
)[0]
extensions.append(extension(metadata))
except (IOError, json.JSONDecodeError, ImportError) as e:
print(f"Failed loading extension {ext}: {e}")
print(f"Failed loading extension {extension}: {e}")
return ext_dict
return sorted(extensions, key=lambda ex: ex.metadata.get("index"))
def extension_submenu(self, **kwargs):
extension = self.extensions.get(kwargs.get("opt_index"))
ExtensionSubmenu(self, extension).run()
def get_options(self, extensions: List[BaseExtension]) -> Options:
options: Options = {}
for extension in extensions:
index = extension.metadata.get("index")
options[f"{index}"] = lambda: ExtensionSubmenu(self, extension).run()
return options
def print_menu(self):
header = " [ Extensions Menu ] "
@@ -82,7 +80,7 @@ class ExtensionsMenu(BaseMenu):
)[1:]
print(menu, end="")
for extension in self.extensions.values():
for extension in self.extensions:
index = extension.metadata.get("index")
name = extension.metadata.get("display_name")
row = f"{index}) {name}"

View File

@@ -36,21 +36,21 @@ from utils.constants import (
)
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
class MainMenu(BaseMenu):
def __init__(self):
super().__init__()
self.options = {
"0": self.log_upload_menu,
"1": self.install_menu,
"2": self.update_menu,
"3": self.remove_menu,
"4": self.advanced_menu,
"5": self.backup_menu,
"e": self.extension_menu,
"s": self.settings_menu,
"0": lambda: LogUploadMenu(previous_menu=self).run(),
"1": lambda: InstallMenu(previous_menu=self).run(),
"2": lambda: UpdateMenu(previous_menu=self).run(),
"3": lambda: RemoveMenu(previous_menu=self).run(),
"4": lambda: AdvancedMenu(previous_menu=self).run(),
"5": lambda: BackupMenu(previous_menu=self).run(),
"6": None,
"e": lambda: ExtensionsMenu(previous_menu=self).run(),
"s": lambda: SettingsMenu(previous_menu=self).run(),
}
self.header = True
self.footer_type = FooterType.QUIT
@@ -141,27 +141,3 @@ class MainMenu(BaseMenu):
"""
)[1:]
print(menu, end="")
def log_upload_menu(self, **kwargs):
LogUploadMenu(previous_menu=self).run()
def install_menu(self, **kwargs):
InstallMenu(previous_menu=self).run()
def update_menu(self, **kwargs):
UpdateMenu(previous_menu=self).run()
def remove_menu(self, **kwargs):
RemoveMenu(previous_menu=self).run()
def advanced_menu(self, **kwargs):
AdvancedMenu(previous_menu=self).run()
def backup_menu(self, **kwargs):
BackupMenu(previous_menu=self).run()
def settings_menu(self, **kwargs):
SettingsMenu(previous_menu=self).run()
def extension_menu(self, **kwargs):
ExtensionsMenu(previous_menu=self).run()

View File

@@ -27,10 +27,14 @@ class RemoveMenu(BaseMenu):
self.previous_menu: BaseMenu = previous_menu
self.options = {
"1": self.remove_klipper,
"2": self.remove_moonraker,
"3": self.remove_mainsail,
"4": self.remove_fluidd,
"1": lambda: KlipperRemoveMenu(previous_menu=self).run(),
"2": lambda: MoonrakerRemoveMenu(previous_menu=self).run(),
"3": lambda: ClientRemoveMenu(
previous_menu=self, client=load_client_data("mainsail")
).run(),
"4": lambda: ClientRemoveMenu(
previous_menu=self, client=load_client_data("fluidd")
).run(),
"5": None,
"6": None,
"7": None,
@@ -68,15 +72,3 @@ class RemoveMenu(BaseMenu):
"""
)[1:]
print(menu, end="")
def remove_klipper(self, **kwargs):
KlipperRemoveMenu(previous_menu=self).run()
def remove_moonraker(self, **kwargs):
MoonrakerRemoveMenu(previous_menu=self).run()
def remove_mainsail(self, **kwargs):
ClientRemoveMenu(previous_menu=self, client=load_client_data("mainsail")).run()
def remove_fluidd(self, **kwargs):
ClientRemoveMenu(previous_menu=self, client=load_client_data("fluidd")).run()