fix: hitting 'b' or 'h' in main menu raises exception

Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
dw-0
2024-04-10 22:41:02 +02:00
parent 409aa3da25
commit bb769fdf6d
4 changed files with 45 additions and 45 deletions

View File

@@ -21,8 +21,7 @@ class KlipperNoFirmwareErrorMenu(BaseMenu):
super().__init__()
self.flash_options = FlashOptions()
self.options = {"": self.go_back}
self.default_options = self.go_back
self.default_option = self.go_back
self.footer_type = FooterType.BLANK
self.input_label_txt = "Press ENTER to go back to [Advanced Menu]"
@@ -64,8 +63,7 @@ class KlipperNoBoardTypesErrorMenu(BaseMenu):
def __init__(self):
super().__init__()
self.options = {"": self.go_back}
self.default_options = self.go_back
self.default_option = self.go_back
self.footer_type = FooterType.BLANK
self.input_label_txt = "Press ENTER to go back to [Main Menu]"

View File

@@ -48,10 +48,10 @@ class KlipperFlashMethodMenu(BaseMenu):
super().__init__()
self.previous_menu: BaseMenu = previous_menu
self.help_menu = KlipperFlashMethodHelpMenu
self.options = {
"1": self.select_regular,
"2": self.select_sdcard,
"h": self.help_menu,
}
self.input_label_txt = "Select flash method"
self.footer_type = FooterType.BACK_HELP
@@ -99,9 +99,6 @@ class KlipperFlashMethodMenu(BaseMenu):
else:
KlipperNoFirmwareErrorMenu().run()
def help_menu(self, **kwargs):
KlipperFlashMethodHelpMenu(previous_menu=self).run()
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
@@ -110,10 +107,10 @@ class KlipperFlashCommandMenu(BaseMenu):
super().__init__()
self.previous_menu: BaseMenu = previous_menu
self.help_menu = KlipperFlashCommandHelpMenu
self.options = {
"1": self.select_flash,
"2": self.select_serialflash,
"h": self.help_menu,
}
self.default_option = self.select_flash
self.input_label_txt = "Select flash command"
@@ -145,9 +142,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
@@ -157,11 +151,11 @@ class KlipperSelectMcuConnectionMenu(BaseMenu):
self.__standalone = standalone
self.previous_menu: BaseMenu = previous_menu
self.help_menu = KlipperMcuConnectionHelpMenu
self.options = {
"1": self.select_usb,
"2": self.select_dfu,
"3": self.select_usb_dfu,
"h": self.help_menu,
}
self.input_label_txt = "Select connection type"
self.footer_type = FooterType.BACK_HELP
@@ -229,9 +223,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

View File

@@ -17,14 +17,6 @@ class FooterType(Enum):
BLANK = "BLANK"
NAVI_OPTIONS = {
FooterType.QUIT: ["q"],
FooterType.BACK: ["b"],
FooterType.BACK_HELP: ["b", "h"],
FooterType.BLANK: [],
}
class ExitAppException(Exception):
pass

View File

@@ -12,10 +12,10 @@ from __future__ import annotations
import subprocess
import sys
import textwrap
from abc import abstractmethod, ABC
from abc import abstractmethod
from typing import Dict, Union, Callable, Type, Tuple
from core.menus import FooterType, NAVI_OPTIONS, ExitAppException, GoBackException
from core.menus import FooterType, ExitAppException, GoBackException
from utils.constants import (
COLOR_GREEN,
COLOR_YELLOW,
@@ -96,22 +96,51 @@ def print_blank_footer():
print("\=======================================================/")
Options = Dict[str, Callable]
class PostInitCaller(type):
def __call__(cls, *args, **kwargs):
obj = type.__call__(cls, *args, **kwargs)
obj.__post_init__()
return obj
class BaseMenu(ABC):
options: Options = {}
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
class BaseMenu(metaclass=PostInitCaller):
options: Dict[str, Callable] = {}
options_offset: int = 0
default_option: Union[Callable, None] = None
input_label_txt: str = "Perform action"
header: bool = False
previous_menu: Union[Type[BaseMenu], BaseMenu] = None
help_menu: Type[BaseMenu] = None
footer_type: FooterType = FooterType.BACK
def __init__(self):
def __init__(self, **kwargs):
if type(self) is BaseMenu:
raise NotImplementedError("BaseMenu cannot be instantiated directly.")
def __post_init__(self):
# conditionally add options based on footer type
if self.footer_type is FooterType.QUIT:
self.options["q"] = self.__exit
if self.footer_type is FooterType.BACK:
self.options["b"] = self.__go_back
if self.footer_type is FooterType.BACK_HELP:
self.options["b"] = self.__go_back
self.options["h"] = self.__go_to_help
# if defined, add the default option to the options dict
if self.default_option is not None:
self.options[""] = self.default_option
def __go_back(self, **kwargs):
raise GoBackException()
def __go_to_help(self, **kwargs):
self.help_menu(previous_menu=self).run()
def __exit(self, **kwargs):
raise ExitAppException()
@abstractmethod
def print_menu(self) -> None:
raise NotImplementedError("Subclasses must implement the print_menu method")
@@ -144,20 +173,8 @@ class BaseMenu(ABC):
usr_input = usr_input.lower()
option = self.options.get(usr_input, None)
# check if usr_input contains a character used for basic navigation, e.g. b, h or q
# and if the current menu has the appropriate footer to allow for that action
is_valid_navigation = self.footer_type in NAVI_OPTIONS
user_navigated = usr_input in NAVI_OPTIONS[self.footer_type]
if is_valid_navigation and user_navigated:
if usr_input == "q":
raise ExitAppException()
elif usr_input == "b":
raise GoBackException()
elif usr_input == "h":
return option, usr_input
# 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:
# 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:
return self.default_option, usr_input
# user selected a regular option
@@ -168,8 +185,10 @@ class BaseMenu(ABC):
while True:
print(f"{COLOR_CYAN}###### {self.input_label_txt}: {RESET_FORMAT}", end="")
usr_input = input().lower()
validated_input = self.validate_user_input(usr_input)
method_to_call = validated_input[0]
if (validated_input := self.validate_user_input(usr_input)) is not None:
if method_to_call is not None:
return validated_input
else:
Logger.print_error("Invalid input!", False)