feat: implement optional extension update entry point

Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
dw-0
2024-04-07 19:35:26 +02:00
parent 44301c0c87
commit 0b41d63496
6 changed files with 38 additions and 19 deletions

View File

@@ -1,30 +0,0 @@
# ======================================================================= #
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
# #
# 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 #
# ======================================================================= #
from abc import abstractmethod, ABC
from typing import Dict
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
class BaseExtension(ABC):
def __init__(self, metadata: Dict[str, str]):
self.metadata = metadata
@abstractmethod
def install_extension(self, **kwargs) -> None:
raise NotImplementedError(
"Subclasses must implement the install_extension method"
)
@abstractmethod
def remove_extension(self, **kwargs) -> None:
raise NotImplementedError(
"Subclasses must implement the remove_extension method"
)

View File

@@ -1,133 +0,0 @@
# ======================================================================= #
# Copyright (C) 2020 - 2024 Dominik Willner <th33xitus@gmail.com> #
# #
# 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 importlib
import inspect
import json
import textwrap
from pathlib import Path
from typing import Type, Dict
from core.base_extension import BaseExtension
from core.menus.base_menu import BaseMenu
from utils.constants import RESET_FORMAT, COLOR_CYAN, COLOR_YELLOW
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
class ExtensionsMenu(BaseMenu):
def __init__(self, previous_menu: BaseMenu):
super().__init__()
self.previous_menu: BaseMenu = previous_menu
self.extensions = self.discover_extensions()
self.options = {ext: self.extension_submenu for ext in self.extensions}
def discover_extensions(self) -> Dict[str, BaseExtension]:
ext_dict = {}
extensions_dir = Path(__file__).resolve().parents[2].joinpath("extensions")
for ext in extensions_dir.iterdir():
metadata_json = Path(ext).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),
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
except (IOError, json.JSONDecodeError, ImportError) as e:
print(f"Failed loading extension {ext}: {e}")
return ext_dict
def extension_submenu(self, **kwargs):
extension = self.extensions.get(kwargs.get("opt_index"))
ExtensionSubmenu(self, extension).run()
def print_menu(self):
header = " [ Extensions Menu ] "
color = COLOR_CYAN
line1 = f"{COLOR_YELLOW}Available Extensions:{RESET_FORMAT}"
count = 62 - len(color) - len(RESET_FORMAT)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
| {line1:<62} |
| |
"""
)[1:]
print(menu, end="")
for extension in self.extensions.values():
index = extension.metadata.get("index")
name = extension.metadata.get("display_name")
row = f"{index}) {name}"
print(f"| {row:<53} |")
# noinspection PyUnusedLocal
# noinspection PyMethodMayBeStatic
class ExtensionSubmenu(BaseMenu):
def __init__(self, previous_menu: BaseMenu, extension: BaseExtension):
super().__init__()
self.previous_menu = previous_menu
self.options = {
"1": extension.install_extension,
"2": extension.remove_extension,
}
self.extension = extension
self.extension_name = extension.metadata.get("display_name")
self.extension_desc = extension.metadata.get("description")
def print_menu(self) -> None:
header = f" [ {self.extension_name} ] "
color = COLOR_YELLOW
count = 62 - len(color) - len(RESET_FORMAT)
wrapper = textwrap.TextWrapper(55, initial_indent="| ", subsequent_indent="| ")
lines = wrapper.wrap(self.extension_desc)
formatted_lines = [f"{line:<55} |" for line in lines]
description_text = "\n".join(formatted_lines)
menu = textwrap.dedent(
f"""
/=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------|
"""
)[1:]
menu += f"{description_text}\n"
menu += textwrap.dedent(
"""
|-------------------------------------------------------|
| 1) Install |
| 2) Remove |
"""
)[1:]
print(menu, end="")

View File

@@ -22,7 +22,7 @@ from core.menus import FooterType
from core.menus.advanced_menu import AdvancedMenu
from core.menus.backup_menu import BackupMenu
from core.menus.base_menu import BaseMenu
from core.menus.extensions_menu import ExtensionsMenu
from extensions.extensions_menu import ExtensionsMenu
from core.menus.install_menu import InstallMenu
from core.menus.remove_menu import RemoveMenu
from core.menus.settings_menu import SettingsMenu