mirror of
https://github.com/dw-0/kiauh.git
synced 2025-12-23 15:53:36 +05:00
Compare commits
6 Commits
d6d5109dea
...
8f793bbfd8
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8f793bbfd8 | ||
|
|
5ace920d3e | ||
|
|
2f34253bad | ||
|
|
0447bc4405 | ||
|
|
7cb2231584 | ||
|
|
5a3d21c40b |
@@ -14,7 +14,7 @@ from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from kiauh.core.instance_manager.base_instance import BaseInstance
|
||||
from kiauh.modules.klipper import KLIPPER_DIR, KLIPPER_ENV_DIR, MODULE_PATH
|
||||
from kiauh.components.klipper import KLIPPER_DIR, KLIPPER_ENV_DIR, MODULE_PATH
|
||||
from kiauh.utils.constants import SYSTEMD
|
||||
from kiauh.utils.logger import Logger
|
||||
|
||||
@@ -52,10 +52,10 @@ class Klipper(BaseInstance):
|
||||
|
||||
def create(self) -> None:
|
||||
Logger.print_status("Creating new Klipper Instance ...")
|
||||
service_template_path = MODULE_PATH.joinpath("res/klipper.service")
|
||||
service_template_path = MODULE_PATH.joinpath("assets/klipper.service")
|
||||
service_file_name = self.get_service_file_name(extension=True)
|
||||
service_file_target = SYSTEMD.joinpath(service_file_name)
|
||||
env_template_file_path = MODULE_PATH.joinpath("res/klipper.env")
|
||||
env_template_file_path = MODULE_PATH.joinpath("assets/klipper.env")
|
||||
env_file_target = self.sysd_dir.joinpath("klipper.env")
|
||||
|
||||
try:
|
||||
@@ -13,9 +13,9 @@ 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.components.klipper import KLIPPER_DIR, KLIPPER_ENV_DIR
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.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
|
||||
@@ -15,16 +15,16 @@ from kiauh import KIAUH_CFG
|
||||
from kiauh.core.backup_manager.backup_manager import BackupManager
|
||||
from kiauh.core.config_manager.config_manager import ConfigManager
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.modules.klipper import (
|
||||
from kiauh.components.klipper import (
|
||||
EXIT_KLIPPER_SETUP,
|
||||
DEFAULT_KLIPPER_REPO_URL,
|
||||
KLIPPER_DIR,
|
||||
KLIPPER_ENV_DIR,
|
||||
KLIPPER_REQUIREMENTS_TXT,
|
||||
)
|
||||
from kiauh.modules.klipper.klipper import Klipper
|
||||
from kiauh.modules.klipper.klipper_dialogs import print_update_warn_dialog
|
||||
from kiauh.modules.klipper.klipper_utils import (
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.klipper.klipper_dialogs import print_update_warn_dialog
|
||||
from kiauh.components.klipper.klipper_utils import (
|
||||
handle_disruptive_system_packages,
|
||||
check_user_groups,
|
||||
handle_to_multi_instance_conversion,
|
||||
@@ -37,7 +37,7 @@ from kiauh.modules.klipper.klipper_utils import (
|
||||
handle_instance_naming,
|
||||
)
|
||||
from kiauh.core.repo_manager.repo_manager import RepoManager
|
||||
from kiauh.modules.moonraker.moonraker import Moonraker
|
||||
from kiauh.components.moonraker.moonraker import Moonraker
|
||||
from kiauh.utils.input_utils import get_confirm
|
||||
from kiauh.utils.logger import Logger
|
||||
from kiauh.utils.system_utils import (
|
||||
@@ -24,16 +24,16 @@ from kiauh.core.instance_manager.base_instance import BaseInstance
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.core.instance_manager.name_scheme import NameScheme
|
||||
from kiauh.core.repo_manager.repo_manager import RepoManager
|
||||
from kiauh.modules.klipper import MODULE_PATH, KLIPPER_DIR, KLIPPER_ENV_DIR
|
||||
from kiauh.modules.klipper.klipper import Klipper
|
||||
from kiauh.modules.klipper.klipper_dialogs import (
|
||||
from kiauh.components.klipper import MODULE_PATH, KLIPPER_DIR, KLIPPER_ENV_DIR
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.klipper.klipper_dialogs import (
|
||||
print_missing_usergroup_dialog,
|
||||
print_instance_overview,
|
||||
print_select_instance_count_dialog,
|
||||
print_select_custom_name_dialog,
|
||||
)
|
||||
from kiauh.modules.moonraker.moonraker import Moonraker
|
||||
from kiauh.modules.moonraker.moonraker_utils import moonraker_to_multi_conversion
|
||||
from kiauh.components.moonraker.moonraker import Moonraker
|
||||
from kiauh.components.moonraker.moonraker_utils import moonraker_to_multi_conversion
|
||||
from kiauh.utils.common import get_install_status_common
|
||||
from kiauh.utils.constants import CURRENT_USER
|
||||
from kiauh.utils.input_utils import get_confirm, get_string_input, get_number_input
|
||||
@@ -264,7 +264,7 @@ def create_example_printer_cfg(instance: Klipper) -> None:
|
||||
Logger.print_info(f"'{instance.cfg_file}' already exists.")
|
||||
return
|
||||
|
||||
source = MODULE_PATH.joinpath("res/printer.cfg")
|
||||
source = MODULE_PATH.joinpath("assets/printer.cfg")
|
||||
target = instance.cfg_file
|
||||
try:
|
||||
shutil.copy(source, target)
|
||||
@@ -13,8 +13,7 @@ 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.components.klipper import klipper_remove
|
||||
from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
|
||||
|
||||
|
||||
@@ -24,12 +23,12 @@ class KlipperRemoveMenu(BaseMenu):
|
||||
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,
|
||||
"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,
|
||||
)
|
||||
@@ -15,8 +15,8 @@ from pathlib import Path
|
||||
import urllib.request
|
||||
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.modules.klipper.klipper import Klipper
|
||||
from kiauh.modules.log_uploads import LogFile
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.log_uploads import LogFile
|
||||
from kiauh.utils.logger import Logger
|
||||
|
||||
|
||||
@@ -13,8 +13,8 @@ import textwrap
|
||||
|
||||
from kiauh.core.menus import BACK_FOOTER
|
||||
from kiauh.core.menus.base_menu import BaseMenu
|
||||
from kiauh.modules.log_uploads.log_upload_utils import upload_logfile
|
||||
from kiauh.modules.log_uploads.log_upload_utils import get_logfile_list
|
||||
from kiauh.components.log_uploads.log_upload_utils import upload_logfile
|
||||
from kiauh.components.log_uploads.log_upload_utils import get_logfile_list
|
||||
from kiauh.utils.constants import RESET_FORMAT, COLOR_YELLOW
|
||||
|
||||
|
||||
@@ -17,10 +17,10 @@ from typing import List
|
||||
|
||||
from kiauh.core.config_manager.config_manager import ConfigManager
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.modules.klipper.klipper import Klipper
|
||||
from kiauh.modules.mainsail import MAINSAIL_DIR, MAINSAIL_CONFIG_DIR
|
||||
from kiauh.modules.mainsail.mainsail_utils import backup_config_json
|
||||
from kiauh.modules.moonraker.moonraker import Moonraker
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.mainsail import MAINSAIL_DIR, MAINSAIL_CONFIG_DIR
|
||||
from kiauh.components.mainsail.mainsail_utils import backup_config_json
|
||||
from kiauh.components.moonraker.moonraker import Moonraker
|
||||
from kiauh.utils import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
||||
from kiauh.utils.filesystem_utils import remove_file
|
||||
from kiauh.utils.logger import Logger
|
||||
@@ -17,27 +17,27 @@ from kiauh import KIAUH_CFG
|
||||
from kiauh.core.config_manager.config_manager import ConfigManager
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.core.repo_manager.repo_manager import RepoManager
|
||||
from kiauh.modules.klipper.klipper import Klipper
|
||||
from kiauh.modules.mainsail import (
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.mainsail import (
|
||||
MAINSAIL_URL,
|
||||
MAINSAIL_DIR,
|
||||
MAINSAIL_CONFIG_DIR,
|
||||
MAINSAIL_CONFIG_REPO_URL,
|
||||
MODULE_PATH,
|
||||
)
|
||||
from kiauh.modules.mainsail.mainsail_dialogs import (
|
||||
from kiauh.components.mainsail.mainsail_dialogs import (
|
||||
print_moonraker_not_found_dialog,
|
||||
print_mainsail_already_installed_dialog,
|
||||
print_install_mainsail_config_dialog,
|
||||
print_mainsail_port_select_dialog,
|
||||
)
|
||||
from kiauh.modules.mainsail.mainsail_utils import (
|
||||
from kiauh.components.mainsail.mainsail_utils import (
|
||||
restore_config_json,
|
||||
enable_mainsail_remotemode,
|
||||
backup_config_json,
|
||||
symlink_webui_nginx_log,
|
||||
)
|
||||
from kiauh.modules.moonraker.moonraker import Moonraker
|
||||
from kiauh.components.moonraker.moonraker import Moonraker
|
||||
from kiauh.utils import NGINX_SITES_AVAILABLE, NGINX_SITES_ENABLED
|
||||
from kiauh.utils.common import check_install_dependencies
|
||||
from kiauh.utils.filesystem_utils import (
|
||||
@@ -229,7 +229,7 @@ def patch_moonraker_conf(
|
||||
Logger.print_info("Section already exist. Skipped ...")
|
||||
return
|
||||
|
||||
template = MODULE_PATH.joinpath("res", template_file)
|
||||
template = MODULE_PATH.joinpath("assets", template_file)
|
||||
with open(template, "r") as t:
|
||||
template_content = "\n"
|
||||
template_content += t.read()
|
||||
@@ -16,8 +16,8 @@ from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
from kiauh.core.backup_manager.backup_manager import BackupManager
|
||||
from kiauh.modules.klipper.klipper import Klipper
|
||||
from kiauh.modules.mainsail import MAINSAIL_CONFIG_JSON, MAINSAIL_DIR
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.mainsail import MAINSAIL_CONFIG_JSON, MAINSAIL_DIR
|
||||
from kiauh.utils import NGINX_SITES_AVAILABLE, NGINX_CONFD
|
||||
from kiauh.utils.common import get_install_status_webui
|
||||
from kiauh.utils.logger import Logger
|
||||
@@ -13,7 +13,7 @@ import textwrap
|
||||
|
||||
from kiauh.core.menus import BACK_HELP_FOOTER
|
||||
from kiauh.core.menus.base_menu import BaseMenu
|
||||
from kiauh.modules.mainsail import mainsail_remove
|
||||
from kiauh.components.mainsail import mainsail_remove
|
||||
from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
|
||||
|
||||
|
||||
@@ -23,13 +23,13 @@ class MainsailRemoveMenu(BaseMenu):
|
||||
super().__init__(
|
||||
header=False,
|
||||
options={
|
||||
0: self.toggle_all,
|
||||
1: self.toggle_remove_mainsail,
|
||||
2: self.toggle_remove_ms_config,
|
||||
3: self.toggle_backup_config_json,
|
||||
4: self.toggle_remove_updater_section,
|
||||
5: self.toggle_remove_printer_cfg_include,
|
||||
6: self.run_removal_process,
|
||||
"0": self.toggle_all,
|
||||
"1": self.toggle_remove_mainsail,
|
||||
"2": self.toggle_remove_ms_config,
|
||||
"3": self.toggle_backup_config_json,
|
||||
"4": self.toggle_remove_updater_section,
|
||||
"5": self.toggle_remove_printer_cfg_include,
|
||||
"6": self.run_removal_process,
|
||||
},
|
||||
footer_type=BACK_HELP_FOOTER,
|
||||
)
|
||||
@@ -13,7 +13,7 @@ import textwrap
|
||||
|
||||
from kiauh.core.menus import BACK_HELP_FOOTER
|
||||
from kiauh.core.menus.base_menu import BaseMenu
|
||||
from kiauh.modules.moonraker import moonraker_remove
|
||||
from kiauh.components.moonraker import moonraker_remove
|
||||
from kiauh.utils.constants import RESET_FORMAT, COLOR_RED, COLOR_CYAN
|
||||
|
||||
|
||||
@@ -23,13 +23,13 @@ class MoonrakerRemoveMenu(BaseMenu):
|
||||
super().__init__(
|
||||
header=False,
|
||||
options={
|
||||
0: self.toggle_all,
|
||||
1: self.toggle_remove_moonraker_service,
|
||||
2: self.toggle_remove_moonraker_dir,
|
||||
3: self.toggle_remove_moonraker_env,
|
||||
4: self.toggle_remove_moonraker_polkit,
|
||||
5: self.toggle_delete_moonraker_logs,
|
||||
6: self.run_removal_process,
|
||||
"0": self.toggle_all,
|
||||
"1": self.toggle_remove_moonraker_service,
|
||||
"2": self.toggle_remove_moonraker_dir,
|
||||
"3": self.toggle_remove_moonraker_env,
|
||||
"4": self.toggle_remove_moonraker_polkit,
|
||||
"5": self.toggle_delete_moonraker_logs,
|
||||
"6": self.run_removal_process,
|
||||
},
|
||||
footer_type=BACK_HELP_FOOTER,
|
||||
)
|
||||
@@ -15,7 +15,7 @@ from typing import List, Union
|
||||
|
||||
from kiauh.core.config_manager.config_manager import ConfigManager
|
||||
from kiauh.core.instance_manager.base_instance import BaseInstance
|
||||
from kiauh.modules.moonraker import MOONRAKER_DIR, MOONRAKER_ENV_DIR, MODULE_PATH
|
||||
from kiauh.components.moonraker import MOONRAKER_DIR, MOONRAKER_ENV_DIR, MODULE_PATH
|
||||
from kiauh.utils.constants import SYSTEMD
|
||||
from kiauh.utils.logger import Logger
|
||||
|
||||
@@ -39,8 +39,8 @@ class Moonraker(BaseInstance):
|
||||
|
||||
def create(self, create_example_cfg: bool = False) -> None:
|
||||
Logger.print_status("Creating new Moonraker Instance ...")
|
||||
service_template_path = MODULE_PATH.joinpath("res/moonraker.service")
|
||||
env_template_file_path = MODULE_PATH.joinpath("res/moonraker.env")
|
||||
service_template_path = MODULE_PATH.joinpath("assets/moonraker.service")
|
||||
env_template_file_path = MODULE_PATH.joinpath("assets/moonraker.env")
|
||||
service_file_name = self.get_service_file_name(extension=True)
|
||||
service_file_target = SYSTEMD.joinpath(service_file_name)
|
||||
env_file_target = self.sysd_dir.joinpath("moonraker.env")
|
||||
@@ -13,8 +13,8 @@ import textwrap
|
||||
from typing import List
|
||||
|
||||
from kiauh.core.menus.base_menu import print_back_footer
|
||||
from kiauh.modules.klipper.klipper import Klipper
|
||||
from kiauh.modules.moonraker.moonraker import Moonraker
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.moonraker.moonraker import Moonraker
|
||||
from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT, COLOR_YELLOW, COLOR_CYAN
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ import subprocess
|
||||
from typing import List, Union
|
||||
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.modules.klipper.klipper_dialogs import print_instance_overview
|
||||
from kiauh.modules.moonraker import MOONRAKER_DIR, MOONRAKER_ENV_DIR
|
||||
from kiauh.modules.moonraker.moonraker import Moonraker
|
||||
from kiauh.components.klipper.klipper_dialogs import print_instance_overview
|
||||
from kiauh.components.moonraker import MOONRAKER_DIR, MOONRAKER_ENV_DIR
|
||||
from kiauh.components.moonraker.moonraker import Moonraker
|
||||
from kiauh.utils.filesystem_utils import remove_file
|
||||
from kiauh.utils.input_utils import get_selection_input
|
||||
from kiauh.utils.logger import Logger
|
||||
@@ -18,12 +18,12 @@ from kiauh import KIAUH_CFG
|
||||
from kiauh.core.backup_manager.backup_manager import BackupManager
|
||||
from kiauh.core.config_manager.config_manager import ConfigManager
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.modules.klipper.klipper import Klipper
|
||||
from kiauh.modules.klipper.klipper_dialogs import print_instance_overview
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.components.klipper.klipper_dialogs import print_instance_overview
|
||||
from kiauh.core.repo_manager.repo_manager import RepoManager
|
||||
from kiauh.modules.mainsail import MAINSAIL_DIR
|
||||
from kiauh.modules.mainsail.mainsail_utils import enable_mainsail_remotemode
|
||||
from kiauh.modules.moonraker import (
|
||||
from kiauh.components.mainsail import MAINSAIL_DIR
|
||||
from kiauh.components.mainsail.mainsail_utils import enable_mainsail_remotemode
|
||||
from kiauh.components.moonraker import (
|
||||
EXIT_MOONRAKER_SETUP,
|
||||
DEFAULT_MOONRAKER_REPO_URL,
|
||||
MOONRAKER_DIR,
|
||||
@@ -34,9 +34,9 @@ from kiauh.modules.moonraker import (
|
||||
POLKIT_USR_FILE,
|
||||
POLKIT_SCRIPT,
|
||||
)
|
||||
from kiauh.modules.moonraker.moonraker import Moonraker
|
||||
from kiauh.modules.moonraker.moonraker_dialogs import print_moonraker_overview
|
||||
from kiauh.modules.moonraker.moonraker_utils import create_example_moonraker_conf
|
||||
from kiauh.components.moonraker.moonraker import Moonraker
|
||||
from kiauh.components.moonraker.moonraker_dialogs import print_moonraker_overview
|
||||
from kiauh.components.moonraker.moonraker_utils import create_example_moonraker_conf
|
||||
from kiauh.utils.filesystem_utils import check_file_exist
|
||||
from kiauh.utils.input_utils import (
|
||||
get_confirm,
|
||||
@@ -15,15 +15,15 @@ from typing import Dict, Literal, List, Union
|
||||
from kiauh.core.config_manager.config_manager import ConfigManager
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.core.repo_manager.repo_manager import RepoManager
|
||||
from kiauh.modules.mainsail import MAINSAIL_DIR
|
||||
from kiauh.modules.mainsail.mainsail_utils import enable_mainsail_remotemode
|
||||
from kiauh.modules.moonraker import (
|
||||
from kiauh.components.mainsail import MAINSAIL_DIR
|
||||
from kiauh.components.mainsail.mainsail_utils import enable_mainsail_remotemode
|
||||
from kiauh.components.moonraker import (
|
||||
DEFAULT_MOONRAKER_PORT,
|
||||
MODULE_PATH,
|
||||
MOONRAKER_DIR,
|
||||
MOONRAKER_ENV_DIR,
|
||||
)
|
||||
from kiauh.modules.moonraker.moonraker import Moonraker
|
||||
from kiauh.components.moonraker.moonraker import Moonraker
|
||||
from kiauh.utils.common import get_install_status_common
|
||||
from kiauh.utils.logger import Logger
|
||||
from kiauh.utils.system_utils import (
|
||||
@@ -56,7 +56,7 @@ def create_example_moonraker_conf(
|
||||
Logger.print_info(f"'{instance.cfg_file}' already exists.")
|
||||
return
|
||||
|
||||
source = MODULE_PATH.joinpath("res/moonraker.conf")
|
||||
source = MODULE_PATH.joinpath("assets/moonraker.conf")
|
||||
target = instance.cfg_file
|
||||
try:
|
||||
shutil.copy(source, target)
|
||||
32
kiauh/core/base_extension.py
Normal file
32
kiauh/core/base_extension.py
Normal file
@@ -0,0 +1,32 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ======================================================================= #
|
||||
# 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"
|
||||
)
|
||||
@@ -13,7 +13,7 @@ import subprocess
|
||||
import sys
|
||||
import textwrap
|
||||
from abc import abstractmethod, ABC
|
||||
from typing import Dict, Any, Literal
|
||||
from typing import Dict, Any, Literal, Union, Callable, Type
|
||||
|
||||
from kiauh.core.menus import QUIT_FOOTER, BACK_FOOTER, BACK_HELP_FOOTER
|
||||
from kiauh.utils.constants import (
|
||||
@@ -97,23 +97,24 @@ class BaseMenu(ABC):
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
options: Dict[int, Any],
|
||||
options: Dict[str, Union[Callable, Any]],
|
||||
options_offset: int = 0,
|
||||
header: bool = True,
|
||||
footer_type: Literal[
|
||||
"QUIT_FOOTER", "BACK_FOOTER", "BACK_HELP_FOOTER"
|
||||
] = QUIT_FOOTER,
|
||||
):
|
||||
self.previous_menu = None
|
||||
self.options = options
|
||||
self.options_offset = options_offset
|
||||
self.header = header
|
||||
self.footer_type = footer_type
|
||||
|
||||
@abstractmethod
|
||||
def print_menu(self):
|
||||
def print_menu(self) -> None:
|
||||
raise NotImplementedError("Subclasses must implement the print_menu method")
|
||||
|
||||
def print_footer(self):
|
||||
def print_footer(self) -> None:
|
||||
footer_type_map = {
|
||||
QUIT_FOOTER: print_quit_footer,
|
||||
BACK_FOOTER: print_back_footer,
|
||||
@@ -122,33 +123,29 @@ class BaseMenu(ABC):
|
||||
footer_function = footer_type_map.get(self.footer_type, print_quit_footer)
|
||||
footer_function()
|
||||
|
||||
def display(self):
|
||||
def display(self) -> None:
|
||||
# clear()
|
||||
if self.header:
|
||||
print_header()
|
||||
self.print_menu()
|
||||
self.print_footer()
|
||||
|
||||
def handle_user_input(self):
|
||||
def handle_user_input(self) -> str:
|
||||
while True:
|
||||
choice = input(f"{COLOR_CYAN}###### Perform action: {RESET_FORMAT}")
|
||||
choice = input(f"{COLOR_CYAN}###### Perform action: {RESET_FORMAT}").lower()
|
||||
option = self.options.get(choice, None)
|
||||
|
||||
if choice.isdigit() and 0 <= int(choice) < len(self.options):
|
||||
has_navi_option = self.footer_type in self.NAVI_OPTIONS
|
||||
user_navigated = choice in self.NAVI_OPTIONS[self.footer_type]
|
||||
if has_navi_option and user_navigated:
|
||||
return choice
|
||||
elif choice.isalpha() and (
|
||||
self.footer_type in self.NAVI_OPTIONS
|
||||
and choice.lower() in self.NAVI_OPTIONS[self.footer_type]
|
||||
):
|
||||
|
||||
if option is not None:
|
||||
return choice
|
||||
else:
|
||||
error_msg = (
|
||||
"Invalid input!"
|
||||
if choice.isalpha() or (not self.options and len(self.options) < 1)
|
||||
else f"Invalid input! Select a number between {min(self.options)} and {max(self.options)}."
|
||||
)
|
||||
Logger.print_error(error_msg, False)
|
||||
Logger.print_error("Invalid input!", False)
|
||||
|
||||
def start(self):
|
||||
def start(self) -> None:
|
||||
while True:
|
||||
self.display()
|
||||
choice = self.handle_user_input()
|
||||
@@ -158,16 +155,18 @@ class BaseMenu(ABC):
|
||||
sys.exit(0)
|
||||
elif choice == "b":
|
||||
return
|
||||
elif choice == "p":
|
||||
elif choice == "h":
|
||||
print("help!")
|
||||
else:
|
||||
self.execute_option(int(choice))
|
||||
self.execute_option(choice)
|
||||
|
||||
def execute_option(self, choice):
|
||||
def execute_option(self, choice: str) -> None:
|
||||
option = self.options.get(choice, None)
|
||||
|
||||
if isinstance(option, type) and issubclass(option, BaseMenu):
|
||||
self.navigate_to_submenu(option)
|
||||
self.navigate_to_menu(option, True)
|
||||
elif isinstance(option, BaseMenu):
|
||||
self.navigate_to_menu(option, False)
|
||||
elif callable(option):
|
||||
option(opt_index=choice)
|
||||
elif option is None:
|
||||
@@ -177,7 +176,14 @@ class BaseMenu(ABC):
|
||||
f"Type {type(option)} of option {choice} not of type BaseMenu or Method"
|
||||
)
|
||||
|
||||
def navigate_to_submenu(self, submenu_class):
|
||||
submenu = submenu_class()
|
||||
submenu.previous_menu = self
|
||||
submenu.start()
|
||||
def navigate_to_menu(self, menu, instantiate: bool) -> None:
|
||||
"""
|
||||
Method for handling the actual menu switch. Can either take in a menu type or an already
|
||||
instantiated menu class. Use instantiated menu classes only if the menu requires specific input parameters
|
||||
:param menu: A menu type or menu instance
|
||||
:param instantiate: Specify if the menu requires instantiation
|
||||
:return: None
|
||||
"""
|
||||
menu = menu() if instantiate else menu
|
||||
menu.previous_menu = self
|
||||
menu.start()
|
||||
|
||||
135
kiauh/core/menus/extensions_menu.py
Normal file
135
kiauh/core/menus/extensions_menu.py
Normal file
@@ -0,0 +1,135 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ======================================================================= #
|
||||
# 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 json
|
||||
import textwrap
|
||||
import importlib
|
||||
import inspect
|
||||
from pathlib import Path
|
||||
from typing import List, Dict
|
||||
|
||||
from kiauh.core.base_extension import BaseExtension
|
||||
from kiauh.core.menus import BACK_FOOTER
|
||||
from kiauh.core.menus.base_menu import BaseMenu
|
||||
from kiauh.utils.constants import RESET_FORMAT, COLOR_CYAN, COLOR_YELLOW
|
||||
|
||||
|
||||
# noinspection PyUnusedLocal
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class ExtensionsMenu(BaseMenu):
|
||||
def __init__(self):
|
||||
self.extensions = self.discover_extensions()
|
||||
super().__init__(
|
||||
header=True,
|
||||
options=self.get_options(),
|
||||
footer_type=BACK_FOOTER,
|
||||
)
|
||||
|
||||
def discover_extensions(self) -> List[BaseExtension]:
|
||||
extensions = []
|
||||
extensions_dir = Path(__file__).resolve().parents[2].joinpath("extensions")
|
||||
|
||||
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:
|
||||
metadata = json.load(m).get("metadata")
|
||||
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]
|
||||
extensions.append(extension(metadata))
|
||||
except (IOError, json.JSONDecodeError, ImportError) as e:
|
||||
print(f"Failed loading extension {extension}: {e}")
|
||||
|
||||
return sorted(extensions, key=lambda ex: ex.metadata.get("index"))
|
||||
|
||||
def get_options(self) -> Dict[str, BaseMenu]:
|
||||
options = {}
|
||||
for extension in self.extensions:
|
||||
index = extension.metadata.get("index")
|
||||
options[f"{index}"] = ExtensionSubmenu(extension)
|
||||
|
||||
return options
|
||||
|
||||
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:
|
||||
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, extension: BaseExtension):
|
||||
self.extension = extension
|
||||
self.extension_name = extension.metadata.get("display_name")
|
||||
self.extension_desc = extension.metadata.get("description")
|
||||
super().__init__(
|
||||
header=False,
|
||||
options={
|
||||
"1": extension.install_extension,
|
||||
"2": extension.remove_extension,
|
||||
},
|
||||
footer_type=BACK_FOOTER,
|
||||
)
|
||||
|
||||
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="")
|
||||
@@ -13,9 +13,9 @@ 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.mainsail import mainsail_setup
|
||||
from kiauh.modules.moonraker import moonraker_setup
|
||||
from kiauh.components.klipper import klipper_setup
|
||||
from kiauh.components.mainsail import mainsail_setup
|
||||
from kiauh.components.moonraker import moonraker_setup
|
||||
from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT
|
||||
|
||||
|
||||
@@ -26,17 +26,17 @@ class InstallMenu(BaseMenu):
|
||||
super().__init__(
|
||||
header=True,
|
||||
options={
|
||||
1: self.install_klipper,
|
||||
2: self.install_moonraker,
|
||||
3: self.install_mainsail,
|
||||
4: self.install_fluidd,
|
||||
5: self.install_klipperscreen,
|
||||
6: self.install_pretty_gcode,
|
||||
7: self.install_telegram_bot,
|
||||
8: self.install_obico,
|
||||
9: self.install_octoeverywhere,
|
||||
10: self.install_mobileraker,
|
||||
11: self.install_crowsnest,
|
||||
"1": self.install_klipper,
|
||||
"2": self.install_moonraker,
|
||||
"3": self.install_mainsail,
|
||||
"4": self.install_fluidd,
|
||||
"5": self.install_klipperscreen,
|
||||
"6": self.install_pretty_gcode,
|
||||
"7": self.install_telegram_bot,
|
||||
"8": self.install_obico,
|
||||
"9": self.install_octoeverywhere,
|
||||
"10": self.install_mobileraker,
|
||||
"11": self.install_crowsnest,
|
||||
},
|
||||
footer_type=BACK_FOOTER,
|
||||
)
|
||||
|
||||
@@ -14,14 +14,15 @@ import textwrap
|
||||
from kiauh.core.menus import QUIT_FOOTER
|
||||
from kiauh.core.menus.advanced_menu import AdvancedMenu
|
||||
from kiauh.core.menus.base_menu import BaseMenu
|
||||
from kiauh.core.menus.extensions_menu import ExtensionsMenu
|
||||
from kiauh.core.menus.install_menu import InstallMenu
|
||||
from kiauh.core.menus.remove_menu import RemoveMenu
|
||||
from kiauh.core.menus.settings_menu import SettingsMenu
|
||||
from kiauh.core.menus.update_menu import UpdateMenu
|
||||
from kiauh.modules.klipper.klipper_utils import get_klipper_status
|
||||
from kiauh.modules.log_uploads.menus.log_upload_menu import LogUploadMenu
|
||||
from kiauh.modules.mainsail.mainsail_utils import get_mainsail_status
|
||||
from kiauh.modules.moonraker.moonraker_utils import get_moonraker_status
|
||||
from kiauh.components.klipper.klipper_utils import get_klipper_status
|
||||
from kiauh.components.log_uploads.menus.log_upload_menu import LogUploadMenu
|
||||
from kiauh.components.mainsail.mainsail_utils import get_mainsail_status
|
||||
from kiauh.components.moonraker.moonraker_utils import get_moonraker_status
|
||||
from kiauh.utils.constants import (
|
||||
COLOR_MAGENTA,
|
||||
COLOR_CYAN,
|
||||
@@ -37,13 +38,14 @@ class MainMenu(BaseMenu):
|
||||
super().__init__(
|
||||
header=True,
|
||||
options={
|
||||
0: LogUploadMenu,
|
||||
1: InstallMenu,
|
||||
2: UpdateMenu,
|
||||
3: RemoveMenu,
|
||||
4: AdvancedMenu,
|
||||
5: None,
|
||||
6: SettingsMenu,
|
||||
"0": LogUploadMenu,
|
||||
"1": InstallMenu,
|
||||
"2": UpdateMenu,
|
||||
"3": RemoveMenu,
|
||||
"4": AdvancedMenu,
|
||||
"5": None,
|
||||
"e": ExtensionsMenu,
|
||||
"s": SettingsMenu,
|
||||
},
|
||||
footer_type=QUIT_FOOTER,
|
||||
)
|
||||
@@ -113,13 +115,13 @@ class MainMenu(BaseMenu):
|
||||
| 4) [Advanced] |------------------------------------|
|
||||
| 5) [Backup] | Mainsail: {self.ms_status:<26} |
|
||||
| | Fluidd: {self.fl_status:<26} |
|
||||
| 6) [Settings] | KlipperScreen: {self.ks_status:<26} |
|
||||
| E) [Extensions] | KlipperScreen: {self.ks_status:<26} |
|
||||
| | Mobileraker: {self.mb_status:<26} |
|
||||
| | |
|
||||
| | Crowsnest: {self.cn_status:<26} |
|
||||
| | Telegram Bot: {self.tg_status:<26} |
|
||||
| | Obico: {self.ob_status:<26} |
|
||||
| | OctoEverywhere: {self.oe_status:<26} |
|
||||
| S) [Settings] | OctoEverywhere: {self.oe_status:<26} |
|
||||
|-------------------------------------------------------|
|
||||
| {COLOR_CYAN}{footer1:^16}{RESET_FORMAT} | {footer2:^43} |
|
||||
"""
|
||||
|
||||
@@ -13,9 +13,9 @@ import textwrap
|
||||
|
||||
from kiauh.core.menus import BACK_FOOTER
|
||||
from kiauh.core.menus.base_menu import BaseMenu
|
||||
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.components.klipper.menus.klipper_remove_menu import KlipperRemoveMenu
|
||||
from kiauh.components.mainsail.menus.mainsail_remove_menu import MainsailRemoveMenu
|
||||
from kiauh.components.moonraker.menus.moonraker_remove_menu import MoonrakerRemoveMenu
|
||||
from kiauh.utils.constants import COLOR_RED, RESET_FORMAT
|
||||
|
||||
|
||||
@@ -26,19 +26,19 @@ class RemoveMenu(BaseMenu):
|
||||
super().__init__(
|
||||
header=True,
|
||||
options={
|
||||
1: KlipperRemoveMenu,
|
||||
2: MoonrakerRemoveMenu,
|
||||
3: MainsailRemoveMenu,
|
||||
5: self.remove_fluidd,
|
||||
6: self.remove_klipperscreen,
|
||||
7: self.remove_crowsnest,
|
||||
8: self.remove_mjpgstreamer,
|
||||
9: self.remove_pretty_gcode,
|
||||
10: self.remove_telegram_bot,
|
||||
11: self.remove_obico,
|
||||
12: self.remove_octoeverywhere,
|
||||
13: self.remove_mobileraker,
|
||||
14: self.remove_nginx,
|
||||
"1": KlipperRemoveMenu,
|
||||
"2": MoonrakerRemoveMenu,
|
||||
"3": MainsailRemoveMenu,
|
||||
"5": self.remove_fluidd,
|
||||
"6": self.remove_klipperscreen,
|
||||
"7": self.remove_crowsnest,
|
||||
"8": self.remove_mjpgstreamer,
|
||||
"9": self.remove_pretty_gcode,
|
||||
"10": self.remove_telegram_bot,
|
||||
"11": self.remove_obico,
|
||||
"12": self.remove_octoeverywhere,
|
||||
"13": self.remove_mobileraker,
|
||||
"14": self.remove_nginx,
|
||||
},
|
||||
footer_type=BACK_FOOTER,
|
||||
)
|
||||
|
||||
@@ -13,17 +13,17 @@ import textwrap
|
||||
|
||||
from kiauh.core.menus import BACK_FOOTER
|
||||
from kiauh.core.menus.base_menu import BaseMenu
|
||||
from kiauh.modules.klipper.klipper_setup import update_klipper
|
||||
from kiauh.modules.klipper.klipper_utils import (
|
||||
from kiauh.components.klipper.klipper_setup import update_klipper
|
||||
from kiauh.components.klipper.klipper_utils import (
|
||||
get_klipper_status,
|
||||
)
|
||||
from kiauh.modules.mainsail.mainsail_setup import update_mainsail
|
||||
from kiauh.modules.mainsail.mainsail_utils import (
|
||||
from kiauh.components.mainsail.mainsail_setup import update_mainsail
|
||||
from kiauh.components.mainsail.mainsail_utils import (
|
||||
get_mainsail_local_version,
|
||||
get_mainsail_remote_version,
|
||||
)
|
||||
from kiauh.modules.moonraker.moonraker_setup import update_moonraker
|
||||
from kiauh.modules.moonraker.moonraker_utils import get_moonraker_status
|
||||
from kiauh.components.moonraker.moonraker_setup import update_moonraker
|
||||
from kiauh.components.moonraker.moonraker_utils import get_moonraker_status
|
||||
from kiauh.utils.constants import COLOR_GREEN, RESET_FORMAT, COLOR_YELLOW, COLOR_WHITE
|
||||
|
||||
|
||||
@@ -34,19 +34,19 @@ class UpdateMenu(BaseMenu):
|
||||
super().__init__(
|
||||
header=True,
|
||||
options={
|
||||
0: self.update_all,
|
||||
1: self.update_klipper,
|
||||
2: self.update_moonraker,
|
||||
3: self.update_mainsail,
|
||||
4: self.update_fluidd,
|
||||
5: self.update_klipperscreen,
|
||||
6: self.update_pgc_for_klipper,
|
||||
7: self.update_telegram_bot,
|
||||
8: self.update_moonraker_obico,
|
||||
9: self.update_octoeverywhere,
|
||||
10: self.update_mobileraker,
|
||||
11: self.update_crowsnest,
|
||||
12: self.upgrade_system_packages,
|
||||
"0": self.update_all,
|
||||
"1": self.update_klipper,
|
||||
"2": self.update_moonraker,
|
||||
"3": self.update_mainsail,
|
||||
"4": self.update_fluidd,
|
||||
"5": self.update_klipperscreen,
|
||||
"6": self.update_pgc_for_klipper,
|
||||
"7": self.update_telegram_bot,
|
||||
"8": self.update_moonraker_obico,
|
||||
"9": self.update_octoeverywhere,
|
||||
"10": self.update_mobileraker,
|
||||
"11": self.update_crowsnest,
|
||||
"12": self.upgrade_system_packages,
|
||||
},
|
||||
footer_type=BACK_FOOTER,
|
||||
)
|
||||
|
||||
0
kiauh/extensions/__init__.py
Normal file
0
kiauh/extensions/__init__.py
Normal file
22
kiauh/extensions/gcode_shell_cmd/__init__.py
Normal file
22
kiauh/extensions/gcode_shell_cmd/__init__.py
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ======================================================================= #
|
||||
# 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 pathlib import Path
|
||||
|
||||
|
||||
EXT_MODULE_NAME = "gcode_shell_command.py"
|
||||
MODULE_PATH = Path(__file__).resolve().parent
|
||||
MODULE_ASSETS = MODULE_PATH.joinpath("assets")
|
||||
KLIPPER_DIR = Path.home().joinpath("klipper")
|
||||
KLIPPER_EXTRAS = KLIPPER_DIR.joinpath("klippy/extras")
|
||||
EXTENSION_SRC = MODULE_ASSETS.joinpath(EXT_MODULE_NAME)
|
||||
EXTENSION_TARGET_PATH = KLIPPER_EXTRAS.joinpath(EXT_MODULE_NAME)
|
||||
EXAMPLE_CFG_SRC = MODULE_ASSETS.joinpath("shell_command.cfg")
|
||||
@@ -0,0 +1,87 @@
|
||||
# Run a shell command via gcode
|
||||
#
|
||||
# Copyright (C) 2019 Eric Callahan <arksine.code@gmail.com>
|
||||
#
|
||||
# This file may be distributed under the terms of the GNU GPLv3 license.
|
||||
import os
|
||||
import shlex
|
||||
import subprocess
|
||||
import logging
|
||||
|
||||
class ShellCommand:
|
||||
def __init__(self, config):
|
||||
self.name = config.get_name().split()[-1]
|
||||
self.printer = config.get_printer()
|
||||
self.gcode = self.printer.lookup_object('gcode')
|
||||
cmd = config.get('command')
|
||||
cmd = os.path.expanduser(cmd)
|
||||
self.command = shlex.split(cmd)
|
||||
self.timeout = config.getfloat('timeout', 2., above=0.)
|
||||
self.verbose = config.getboolean('verbose', True)
|
||||
self.proc_fd = None
|
||||
self.partial_output = ""
|
||||
self.gcode.register_mux_command(
|
||||
"RUN_SHELL_COMMAND", "CMD", self.name,
|
||||
self.cmd_RUN_SHELL_COMMAND,
|
||||
desc=self.cmd_RUN_SHELL_COMMAND_help)
|
||||
|
||||
def _process_output(self, eventime):
|
||||
if self.proc_fd is None:
|
||||
return
|
||||
try:
|
||||
data = os.read(self.proc_fd, 4096)
|
||||
except Exception:
|
||||
pass
|
||||
data = self.partial_output + data.decode()
|
||||
if '\n' not in data:
|
||||
self.partial_output = data
|
||||
return
|
||||
elif data[-1] != '\n':
|
||||
split = data.rfind('\n') + 1
|
||||
self.partial_output = data[split:]
|
||||
data = data[:split]
|
||||
else:
|
||||
self.partial_output = ""
|
||||
self.gcode.respond_info(data)
|
||||
|
||||
cmd_RUN_SHELL_COMMAND_help = "Run a linux shell command"
|
||||
def cmd_RUN_SHELL_COMMAND(self, params):
|
||||
gcode_params = params.get('PARAMS','')
|
||||
gcode_params = shlex.split(gcode_params)
|
||||
reactor = self.printer.get_reactor()
|
||||
try:
|
||||
proc = subprocess.Popen(
|
||||
self.command + gcode_params, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||
except Exception:
|
||||
logging.exception(
|
||||
"shell_command: Command {%s} failed" % (self.name))
|
||||
raise self.gcode.error("Error running command {%s}" % (self.name))
|
||||
if self.verbose:
|
||||
self.proc_fd = proc.stdout.fileno()
|
||||
self.gcode.respond_info("Running Command {%s}...:" % (self.name))
|
||||
hdl = reactor.register_fd(self.proc_fd, self._process_output)
|
||||
eventtime = reactor.monotonic()
|
||||
endtime = eventtime + self.timeout
|
||||
complete = False
|
||||
while eventtime < endtime:
|
||||
eventtime = reactor.pause(eventtime + .05)
|
||||
if proc.poll() is not None:
|
||||
complete = True
|
||||
break
|
||||
if not complete:
|
||||
proc.terminate()
|
||||
if self.verbose:
|
||||
if self.partial_output:
|
||||
self.gcode.respond_info(self.partial_output)
|
||||
self.partial_output = ""
|
||||
if complete:
|
||||
msg = "Command {%s} finished\n" % (self.name)
|
||||
else:
|
||||
msg = "Command {%s} timed out" % (self.name)
|
||||
self.gcode.respond_info(msg)
|
||||
reactor.unregister_fd(hdl)
|
||||
self.proc_fd = None
|
||||
|
||||
|
||||
def load_config_prefix(config):
|
||||
return ShellCommand(config)
|
||||
@@ -0,0 +1,7 @@
|
||||
[gcode_shell_command hello_world]
|
||||
command: echo hello world
|
||||
timeout: 2.
|
||||
verbose: True
|
||||
[gcode_macro HELLO_WORLD]
|
||||
gcode:
|
||||
RUN_SHELL_COMMAND CMD=hello_world
|
||||
127
kiauh/extensions/gcode_shell_cmd/gcode_shell_cmd_extension.py
Normal file
127
kiauh/extensions/gcode_shell_cmd/gcode_shell_cmd_extension.py
Normal file
@@ -0,0 +1,127 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# ======================================================================= #
|
||||
# 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 os
|
||||
import shutil
|
||||
from typing import List
|
||||
|
||||
from kiauh.components.klipper.klipper import Klipper
|
||||
from kiauh.core.backup_manager.backup_manager import BackupManager
|
||||
from kiauh.core.base_extension import BaseExtension
|
||||
from kiauh.core.config_manager.config_manager import ConfigManager
|
||||
from kiauh.core.instance_manager.instance_manager import InstanceManager
|
||||
from kiauh.extensions.gcode_shell_cmd import (
|
||||
EXTENSION_TARGET_PATH,
|
||||
EXTENSION_SRC,
|
||||
KLIPPER_DIR,
|
||||
EXAMPLE_CFG_SRC,
|
||||
KLIPPER_EXTRAS,
|
||||
)
|
||||
from kiauh.utils.filesystem_utils import check_file_exist
|
||||
from kiauh.utils.input_utils import get_confirm
|
||||
from kiauh.utils.logger import Logger
|
||||
|
||||
|
||||
# noinspection PyMethodMayBeStatic
|
||||
class GcodeShellCmdExtension(BaseExtension):
|
||||
def install_extension(self, **kwargs) -> None:
|
||||
install_example = get_confirm("Create an example shell command?", False, False)
|
||||
|
||||
klipper_dir_exists = check_file_exist(KLIPPER_DIR)
|
||||
if not klipper_dir_exists:
|
||||
Logger.print_warn(
|
||||
"No Klipper directory found! Unable to install extension."
|
||||
)
|
||||
return
|
||||
|
||||
extension_installed = check_file_exist(EXTENSION_TARGET_PATH)
|
||||
overwrite = True
|
||||
if extension_installed:
|
||||
overwrite = get_confirm(
|
||||
"Extension seems to be installed already. Overwrite?", True, False
|
||||
)
|
||||
|
||||
if not overwrite:
|
||||
Logger.print_warn("Installation aborted due to user request.")
|
||||
return
|
||||
|
||||
im = InstanceManager(Klipper)
|
||||
im.stop_all_instance()
|
||||
|
||||
try:
|
||||
Logger.print_status(f"Copy extension to '{KLIPPER_EXTRAS}' ...")
|
||||
shutil.copy(EXTENSION_SRC, EXTENSION_TARGET_PATH)
|
||||
except OSError as e:
|
||||
Logger.print_error(f"Unable to install extension: {e}")
|
||||
return
|
||||
|
||||
if install_example:
|
||||
self.install_example_cfg(im.instances)
|
||||
|
||||
im.start_all_instance()
|
||||
|
||||
Logger.print_ok("Installing G-Code Shell Command extension successfull!")
|
||||
|
||||
def remove_extension(self, **kwargs) -> None:
|
||||
extension_installed = check_file_exist(EXTENSION_TARGET_PATH)
|
||||
if not extension_installed:
|
||||
Logger.print_info("Extension does not seem to be installed! Skipping ...")
|
||||
return
|
||||
|
||||
question = "Do you really want to remove the extension?"
|
||||
if get_confirm(question, True, False):
|
||||
try:
|
||||
Logger.print_status(f"Removing '{EXTENSION_TARGET_PATH}' ...")
|
||||
os.remove(EXTENSION_TARGET_PATH)
|
||||
Logger.print_ok("Extension successfully removed!")
|
||||
except OSError as e:
|
||||
Logger.print_error(f"Unable to remove extension: {e}")
|
||||
|
||||
Logger.print_warn("PLEASE NOTE:")
|
||||
Logger.print_warn(
|
||||
"Remaining gcode shell command will cause Klipper to throw an error."
|
||||
)
|
||||
Logger.print_warn("Make sure to remove them from the printer.cfg!")
|
||||
|
||||
def install_example_cfg(self, instances: List[Klipper]):
|
||||
cfg_dirs = [instance.cfg_dir for instance in instances]
|
||||
# copy extension to klippy/extras
|
||||
for cfg_dir in cfg_dirs:
|
||||
Logger.print_status(f"Create shell_command.cfg in '{cfg_dir}' ...")
|
||||
if check_file_exist(cfg_dir.joinpath("shell_command.cfg")):
|
||||
Logger.print_info("File already exists! Skipping ...")
|
||||
continue
|
||||
try:
|
||||
shutil.copy(EXAMPLE_CFG_SRC, cfg_dir)
|
||||
Logger.print_ok("Done!")
|
||||
except OSError as e:
|
||||
Logger.warn(f"Unable to create example config: {e}")
|
||||
|
||||
# backup each printer.cfg before modification
|
||||
bm = BackupManager()
|
||||
for instance in instances:
|
||||
bm.backup_file(
|
||||
[instance.cfg_file],
|
||||
custom_filename=f"{instance.suffix}.printer.cfg",
|
||||
)
|
||||
|
||||
# add section to printer.cfg if not already defined
|
||||
section = "include shell_command.cfg"
|
||||
cfg_files = [instance.cfg_file for instance in instances]
|
||||
for cfg_file in cfg_files:
|
||||
Logger.print_status(f"Include shell_command.cfg in '{cfg_file}' ...")
|
||||
cm = ConfigManager(cfg_file)
|
||||
if cm.config.has_section(section):
|
||||
Logger.print_info("Section already defined! Skipping ...")
|
||||
continue
|
||||
cm.config.add_section(section)
|
||||
cm.write_config()
|
||||
Logger.print_ok("Done!")
|
||||
9
kiauh/extensions/gcode_shell_cmd/metadata.json
Normal file
9
kiauh/extensions/gcode_shell_cmd/metadata.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"metadata": {
|
||||
"index": 1,
|
||||
"module": "gcode_shell_cmd_extension",
|
||||
"maintained_by": "dw-0",
|
||||
"display_name": "G-Code Shell Command",
|
||||
"description": "Allows to run a shell command from gcode."
|
||||
}
|
||||
}
|
||||
@@ -79,7 +79,7 @@ def copy_upstream_nginx_cfg() -> None:
|
||||
Creates an upstream.conf in /etc/nginx/conf.d
|
||||
:return: None
|
||||
"""
|
||||
source = MODULE_PATH.joinpath("res/upstreams.conf")
|
||||
source = MODULE_PATH.joinpath("assets/upstreams.conf")
|
||||
target = NGINX_CONFD.joinpath("upstreams.conf")
|
||||
try:
|
||||
command = ["sudo", "cp", source, target]
|
||||
@@ -95,7 +95,7 @@ def copy_common_vars_nginx_cfg() -> None:
|
||||
Creates a common_vars.conf in /etc/nginx/conf.d
|
||||
:return: None
|
||||
"""
|
||||
source = MODULE_PATH.joinpath("res/common_vars.conf")
|
||||
source = MODULE_PATH.joinpath("assets/common_vars.conf")
|
||||
target = NGINX_CONFD.joinpath("common_vars.conf")
|
||||
try:
|
||||
command = ["sudo", "cp", source, target]
|
||||
@@ -115,7 +115,7 @@ def create_nginx_cfg(name: str, port: int, root_dir: Path) -> None:
|
||||
:return: None
|
||||
"""
|
||||
tmp = Path.home().joinpath(f"{name}.tmp")
|
||||
shutil.copy(MODULE_PATH.joinpath("res/nginx_cfg"), tmp)
|
||||
shutil.copy(MODULE_PATH.joinpath("assets/nginx_cfg"), tmp)
|
||||
with open(tmp, "r+") as f:
|
||||
content = f.read()
|
||||
content = content.replace("%NAME%", name)
|
||||
|
||||
Reference in New Issue
Block a user