refactor: more robust type hinting

Signed-off-by: Dominik Willner <th33xitus@gmail.com>
This commit is contained in:
dw-0
2024-05-19 18:41:29 +02:00
parent 6eb06772b4
commit ac0478b062
10 changed files with 167 additions and 235 deletions

View File

@@ -12,19 +12,19 @@ import shutil
import time import time
from pathlib import Path from pathlib import Path
from subprocess import CalledProcessError, run from subprocess import CalledProcessError, run
from typing import Dict, List, Literal, Union from typing import List
from components.crowsnest import CROWSNEST_BACKUP_DIR, CROWSNEST_DIR, CROWSNEST_REPO from components.crowsnest import CROWSNEST_BACKUP_DIR, CROWSNEST_DIR, CROWSNEST_REPO
from components.klipper.klipper import Klipper from components.klipper.klipper import Klipper
from core.backup_manager.backup_manager import BackupManager from core.backup_manager.backup_manager import BackupManager
from core.instance_manager.instance_manager import InstanceManager from core.instance_manager.instance_manager import InstanceManager
from core.settings.kiauh_settings import KiauhSettings from core.settings.kiauh_settings import KiauhSettings
from utils.common import check_install_dependencies, get_install_status from utils.common import (
check_install_dependencies,
get_install_status,
)
from utils.constants import CURRENT_USER from utils.constants import CURRENT_USER
from utils.git_utils import ( from utils.git_utils import (
get_local_commit,
get_remote_commit,
get_repo_name,
git_clone_wrapper, git_clone_wrapper,
git_pull_wrapper, git_pull_wrapper,
) )
@@ -34,6 +34,7 @@ from utils.sys_utils import (
cmd_sysctl_service, cmd_sysctl_service,
parse_packages_from_file, parse_packages_from_file,
) )
from utils.types import ComponentStatus
def install_crowsnest() -> None: def install_crowsnest() -> None:
@@ -142,25 +143,13 @@ def update_crowsnest() -> None:
return return
def get_crowsnest_status() -> ( def get_crowsnest_status() -> ComponentStatus:
Dict[
Literal["status", "status_code", "repo", "local", "remote"],
Union[str, int],
]
):
files = [ files = [
Path("/usr/local/bin/crowsnest"), Path("/usr/local/bin/crowsnest"),
Path("/etc/logrotate.d/crowsnest"), Path("/etc/logrotate.d/crowsnest"),
Path("/etc/systemd/system/crowsnest.service"), Path("/etc/systemd/system/crowsnest.service"),
] ]
status = get_install_status(CROWSNEST_DIR, files) return get_install_status(CROWSNEST_DIR, files=files)
return {
"status": status.get("status"),
"status_code": status.get("status_code"),
"repo": get_repo_name(CROWSNEST_DIR),
"local": get_local_commit(CROWSNEST_DIR),
"remote": get_remote_commit(CROWSNEST_DIR),
}
def remove_crowsnest() -> None: def remove_crowsnest() -> None:

View File

@@ -12,7 +12,7 @@ import os
import re import re
import shutil import shutil
from subprocess import CalledProcessError, run from subprocess import CalledProcessError, run
from typing import Dict, List, Literal, Optional, Union from typing import Dict, List, Optional, Union
from components.klipper import ( from components.klipper import (
KLIPPER_BACKUP_DIR, KLIPPER_BACKUP_DIR,
@@ -39,29 +39,16 @@ from core.instance_manager.base_instance import BaseInstance
from core.instance_manager.instance_manager import InstanceManager from core.instance_manager.instance_manager import InstanceManager
from core.instance_manager.name_scheme import NameScheme from core.instance_manager.name_scheme import NameScheme
from utils import PRINTER_CFG_BACKUP_DIR from utils import PRINTER_CFG_BACKUP_DIR
from utils.common import get_install_status_common from utils.common import get_install_status
from utils.constants import CURRENT_USER from utils.constants import CURRENT_USER
from utils.git_utils import get_local_commit, get_remote_commit, get_repo_name
from utils.input_utils import get_confirm, get_number_input, get_string_input from utils.input_utils import get_confirm, get_number_input, get_string_input
from utils.logger import DialogType, Logger from utils.logger import DialogType, Logger
from utils.sys_utils import cmd_sysctl_service from utils.sys_utils import cmd_sysctl_service
from utils.types import ComponentStatus
def get_klipper_status() -> ( def get_klipper_status() -> ComponentStatus:
Dict[ return get_install_status(KLIPPER_DIR, KLIPPER_ENV_DIR, Klipper)
Literal["status", "status_code", "instances", "repo", "local", "remote"],
Union[str, int],
]
):
status = get_install_status_common(Klipper, KLIPPER_DIR, KLIPPER_ENV_DIR)
return {
"status": status.get("status"),
"status_code": status.get("status_code"),
"instances": status.get("instances"),
"repo": get_repo_name(KLIPPER_DIR),
"local": get_local_commit(KLIPPER_DIR),
"remote": get_remote_commit(KLIPPER_DIR),
}
def check_is_multi_install( def check_is_multi_install(

View File

@@ -8,39 +8,40 @@
# ======================================================================= # # ======================================================================= #
import shutil import shutil
from pathlib import Path from pathlib import Path
from subprocess import run, CalledProcessError from subprocess import CalledProcessError, run
from typing import List, Dict, Literal, Union from typing import List
from components.klipper.klipper import Klipper from components.klipper.klipper import Klipper
from components.klipperscreen import ( from components.klipperscreen import (
KLIPPERSCREEN_DIR,
KLIPPERSCREEN_REPO,
KLIPPERSCREEN_ENV,
KLIPPERSCREEN_BACKUP_DIR, KLIPPERSCREEN_BACKUP_DIR,
KLIPPERSCREEN_DIR,
KLIPPERSCREEN_ENV,
KLIPPERSCREEN_REPO,
) )
from components.moonraker.moonraker import Moonraker from components.moonraker.moonraker import Moonraker
from core.backup_manager.backup_manager import BackupManager from core.backup_manager.backup_manager import BackupManager
from core.instance_manager.instance_manager import InstanceManager from core.instance_manager.instance_manager import InstanceManager
from core.settings.kiauh_settings import KiauhSettings from core.settings.kiauh_settings import KiauhSettings
from utils.common import get_install_status, check_install_dependencies from utils.common import (
check_install_dependencies,
get_install_status,
)
from utils.config_utils import add_config_section, remove_config_section from utils.config_utils import add_config_section, remove_config_section
from utils.constants import SYSTEMD from utils.constants import SYSTEMD
from utils.fs_utils import remove_with_sudo from utils.fs_utils import remove_with_sudo
from utils.git_utils import ( from utils.git_utils import (
git_clone_wrapper, git_clone_wrapper,
git_pull_wrapper, git_pull_wrapper,
get_repo_name,
get_local_commit,
get_remote_commit,
) )
from utils.input_utils import get_confirm from utils.input_utils import get_confirm
from utils.logger import Logger, DialogType from utils.logger import DialogType, Logger
from utils.sys_utils import ( from utils.sys_utils import (
check_python_version, check_python_version,
cmd_sysctl_manage,
cmd_sysctl_service, cmd_sysctl_service,
install_python_requirements, install_python_requirements,
cmd_sysctl_manage,
) )
from utils.types import ComponentStatus
def install_klipperscreen() -> None: def install_klipperscreen() -> None:
@@ -141,25 +142,12 @@ def update_klipperscreen() -> None:
return return
def get_klipperscreen_status() -> ( def get_klipperscreen_status() -> ComponentStatus:
Dict[ return get_install_status(
Literal["status", "status_code", "repo", "local", "remote"],
Union[str, int],
]
):
files = [
KLIPPERSCREEN_DIR, KLIPPERSCREEN_DIR,
KLIPPERSCREEN_ENV, KLIPPERSCREEN_ENV,
SYSTEMD.joinpath("KlipperScreen.service"), files=[SYSTEMD.joinpath("KlipperScreen.service")],
] )
status = get_install_status(KLIPPERSCREEN_DIR, files)
return {
"status": status.get("status"),
"status_code": status.get("status_code"),
"repo": get_repo_name(KLIPPERSCREEN_DIR),
"local": get_local_commit(KLIPPERSCREEN_DIR),
"remote": get_remote_commit(KLIPPERSCREEN_DIR),
}
def remove_klipperscreen() -> None: def remove_klipperscreen() -> None:

View File

@@ -9,7 +9,7 @@
import shutil import shutil
from pathlib import Path from pathlib import Path
from subprocess import CalledProcessError, run from subprocess import CalledProcessError, run
from typing import Dict, List, Literal, Union from typing import List
from components.klipper.klipper import Klipper from components.klipper.klipper import Klipper
from components.mobileraker import ( from components.mobileraker import (
@@ -27,9 +27,6 @@ from utils.config_utils import add_config_section, remove_config_section
from utils.constants import SYSTEMD from utils.constants import SYSTEMD
from utils.fs_utils import remove_with_sudo from utils.fs_utils import remove_with_sudo
from utils.git_utils import ( from utils.git_utils import (
get_local_commit,
get_remote_commit,
get_repo_name,
git_clone_wrapper, git_clone_wrapper,
git_pull_wrapper, git_pull_wrapper,
) )
@@ -41,6 +38,7 @@ from utils.sys_utils import (
cmd_sysctl_service, cmd_sysctl_service,
install_python_requirements, install_python_requirements,
) )
from utils.types import ComponentStatus
def install_mobileraker() -> None: def install_mobileraker() -> None:
@@ -138,25 +136,12 @@ def update_mobileraker() -> None:
return return
def get_mobileraker_status() -> ( def get_mobileraker_status() -> ComponentStatus:
Dict[ return get_install_status(
Literal["status", "status_code", "repo", "local", "remote"],
Union[str, int],
]
):
files = [
MOBILERAKER_DIR, MOBILERAKER_DIR,
MOBILERAKER_ENV, MOBILERAKER_ENV,
SYSTEMD.joinpath("mobileraker.service"), files=[SYSTEMD.joinpath("mobileraker.service")],
] )
status = get_install_status(MOBILERAKER_DIR, files)
return {
"status": status.get("status"),
"status_code": status.get("status_code"),
"repo": get_repo_name(MOBILERAKER_DIR),
"local": get_local_commit(MOBILERAKER_DIR),
"remote": get_remote_commit(MOBILERAKER_DIR),
}
def remove_mobileraker() -> None: def remove_mobileraker() -> None:

View File

@@ -8,15 +8,15 @@
# ======================================================================= # # ======================================================================= #
import shutil import shutil
from typing import Dict, Literal, List, Union, Optional from typing import Dict, List, Optional
from components.moonraker import ( from components.moonraker import (
DEFAULT_MOONRAKER_PORT, DEFAULT_MOONRAKER_PORT,
MODULE_PATH, MODULE_PATH,
MOONRAKER_DIR,
MOONRAKER_ENV_DIR,
MOONRAKER_BACKUP_DIR, MOONRAKER_BACKUP_DIR,
MOONRAKER_DB_BACKUP_DIR, MOONRAKER_DB_BACKUP_DIR,
MOONRAKER_DIR,
MOONRAKER_ENV_DIR,
) )
from components.moonraker.moonraker import Moonraker from components.moonraker.moonraker import Moonraker
from components.webui_client.base_data import BaseWebClient from components.webui_client.base_data import BaseWebClient
@@ -25,29 +25,16 @@ from components.webui_client.mainsail_data import MainsailData
from core.backup_manager.backup_manager import BackupManager from core.backup_manager.backup_manager import BackupManager
from core.config_manager.config_manager import ConfigManager from core.config_manager.config_manager import ConfigManager
from core.instance_manager.instance_manager import InstanceManager from core.instance_manager.instance_manager import InstanceManager
from utils.common import get_install_status_common from utils.common import get_install_status
from utils.git_utils import get_repo_name, get_local_commit, get_remote_commit
from utils.logger import Logger from utils.logger import Logger
from utils.sys_utils import ( from utils.sys_utils import (
get_ipv4_addr, get_ipv4_addr,
) )
from utils.types import ComponentStatus
def get_moonraker_status() -> ( def get_moonraker_status() -> ComponentStatus:
Dict[ return get_install_status(MOONRAKER_DIR, MOONRAKER_ENV_DIR, Moonraker)
Literal["status", "status_code", "instances", "repo", "local", "remote"],
Union[str, int],
]
):
status = get_install_status_common(Moonraker, MOONRAKER_DIR, MOONRAKER_ENV_DIR)
return {
"status": status.get("status"),
"status_code": status.get("status_code"),
"instances": status.get("instances"),
"repo": get_repo_name(MOONRAKER_DIR),
"local": get_local_commit(MOONRAKER_DIR),
"remote": get_remote_commit(MOONRAKER_DIR),
}
def create_example_moonraker_conf( def create_example_moonraker_conf(

View File

@@ -7,61 +7,53 @@
# This file may be distributed under the terms of the GNU GPLv3 license # # This file may be distributed under the terms of the GNU GPLv3 license #
# ======================================================================= # # ======================================================================= #
import json import json # noqa: I001
import shutil import shutil
from pathlib import Path from pathlib import Path
from typing import List, Dict, Literal, Union, get_args from typing import List, get_args
from components.klipper.klipper import Klipper from components.klipper.klipper import Klipper
from components.webui_client.base_data import ( from components.webui_client.base_data import (
WebClientType,
BaseWebClient, BaseWebClient,
BaseWebClientConfig, BaseWebClientConfig,
WebClientType,
) )
from components.webui_client.mainsail_data import MainsailData from components.webui_client.mainsail_data import MainsailData
from core.backup_manager.backup_manager import BackupManager from core.backup_manager.backup_manager import BackupManager
from core.settings.kiauh_settings import KiauhSettings from core.settings.kiauh_settings import KiauhSettings
from utils import NGINX_SITES_AVAILABLE, NGINX_CONFD from utils import NGINX_CONFD, NGINX_SITES_AVAILABLE
from utils.common import get_install_status_webui from utils.common import get_install_status
from utils.constants import COLOR_CYAN, RESET_FORMAT, COLOR_YELLOW from utils.constants import COLOR_CYAN, COLOR_YELLOW, RESET_FORMAT
from utils.git_utils import ( from utils.git_utils import (
get_latest_tag, get_latest_tag,
get_latest_unstable_tag, get_latest_unstable_tag,
get_repo_name,
get_local_commit,
get_remote_commit,
) )
from utils.logger import Logger from utils.logger import Logger
from utils.types import ComponentStatus, InstallStatus
def get_client_status( def get_client_status(
client: BaseWebClient, fetch_remote: bool = False client: BaseWebClient, fetch_remote: bool = False
) -> Dict[Literal["status", "local", "remote"], str]: ) -> ComponentStatus:
status = get_install_status_webui( files = [
client.client_dir,
NGINX_SITES_AVAILABLE.joinpath(client.name), NGINX_SITES_AVAILABLE.joinpath(client.name),
NGINX_CONFD.joinpath("upstreams.conf"), NGINX_CONFD.joinpath("upstreams.conf"),
NGINX_CONFD.joinpath("common_vars.conf"), NGINX_CONFD.joinpath("common_vars.conf"),
) ]
local = get_local_client_version(client) status = get_install_status(client.client_dir, files=files)
remote = get_remote_client_version(client) if fetch_remote else None
return {"status": status, "local": local, "remote": remote} # if the client dir does not exist, set the status to not
# installed even if the other files are present
if not client.client_dir.exists():
status["status"] = InstallStatus.NOT_INSTALLED
status["local"] = get_local_client_version(client)
status["remote"] = get_remote_client_version(client) if fetch_remote else None
return status
def get_client_config_status( def get_client_config_status(client: BaseWebClient) -> ComponentStatus:
client: BaseWebClient, return get_install_status(client.client_config.config_dir)
) -> Dict[
Literal["repo", "local", "remote"],
Union[str, int],
]:
client_config = client.client_config.config_dir
return {
"repo": get_repo_name(client_config),
"local": get_local_commit(client_config),
"remote": get_remote_commit(client_config),
}
def get_current_client_config(clients: List[BaseWebClient]) -> str: def get_current_client_config(clients: List[BaseWebClient]) -> str:

View File

@@ -8,7 +8,7 @@
# ======================================================================= # # ======================================================================= #
import textwrap import textwrap
from typing import Type, Optional from typing import Optional, Type
from components.crowsnest.crowsnest import get_crowsnest_status from components.crowsnest.crowsnest import get_crowsnest_status
from components.klipper.klipper_utils import get_klipper_status from components.klipper.klipper_utils import get_klipper_status
@@ -26,19 +26,20 @@ from core.menus import FooterType
from core.menus.advanced_menu import AdvancedMenu from core.menus.advanced_menu import AdvancedMenu
from core.menus.backup_menu import BackupMenu from core.menus.backup_menu import BackupMenu
from core.menus.base_menu import BaseMenu, Option from core.menus.base_menu import BaseMenu, Option
from extensions.extensions_menu import ExtensionsMenu
from core.menus.install_menu import InstallMenu from core.menus.install_menu import InstallMenu
from core.menus.remove_menu import RemoveMenu from core.menus.remove_menu import RemoveMenu
from core.menus.settings_menu import SettingsMenu from core.menus.settings_menu import SettingsMenu
from core.menus.update_menu import UpdateMenu from core.menus.update_menu import UpdateMenu
from extensions.extensions_menu import ExtensionsMenu
from utils.constants import ( from utils.constants import (
COLOR_MAGENTA,
COLOR_CYAN, COLOR_CYAN,
RESET_FORMAT,
COLOR_RED,
COLOR_GREEN, COLOR_GREEN,
COLOR_MAGENTA,
COLOR_RED,
COLOR_YELLOW, COLOR_YELLOW,
RESET_FORMAT,
) )
from utils.types import ComponentStatus
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@@ -91,18 +92,17 @@ class MainMenu(BaseMenu):
self._get_component_status("cn", get_crowsnest_status) self._get_component_status("cn", get_crowsnest_status)
def _get_component_status(self, name: str, status_fn: callable, *args) -> None: def _get_component_status(self, name: str, status_fn: callable, *args) -> None:
status_data = status_fn(*args) status_data: ComponentStatus = status_fn(*args)
status = status_data.get("status") code: int = status_data.get("status").value.code
code = status_data.get("status_code") status: str = status_data.get("status").value.txt
repo = status_data.get("repo") repo: str = status_data.get("repo")
instance_count: int = status_data.get("instances")
instance_count = status_data.get("instances") count_txt: str = ""
if instance_count > 0 and code == 1:
count_txt = f": {instance_count}"
count: str = "" setattr(self, f"{name}_status", self._format_by_code(code, status, count_txt))
if instance_count and code == 1:
count = f" {instance_count}"
setattr(self, f"{name}_status", self._format_by_code(code, status, count))
setattr(self, f"{name}_repo", f"{COLOR_CYAN}{repo}{RESET_FORMAT}") setattr(self, f"{name}_repo", f"{COLOR_CYAN}{repo}{RESET_FORMAT}")
def _format_by_code(self, code: int, status: str, count: str) -> str: def _format_by_code(self, code: int, status: str, count: str) -> str:
@@ -121,24 +121,26 @@ class MainMenu(BaseMenu):
footer2 = f"Changelog: {COLOR_MAGENTA}https://git.io/JnmlX{RESET_FORMAT}" footer2 = f"Changelog: {COLOR_MAGENTA}https://git.io/JnmlX{RESET_FORMAT}"
color = COLOR_CYAN color = COLOR_CYAN
count = 62 - len(color) - len(RESET_FORMAT) count = 62 - len(color) - len(RESET_FORMAT)
pad1 = 32
pad2 = 26
menu = textwrap.dedent( menu = textwrap.dedent(
f""" f"""
/=======================================================\\ /=======================================================\\
| {color}{header:~^{count}}{RESET_FORMAT} | | {color}{header:~^{count}}{RESET_FORMAT} |
|-------------------------------------------------------| |-------------------------------------------------------|
| 0) [Log-Upload] | Klipper: {self.kl_status:<32} | | 0) [Log-Upload] | Klipper: {self.kl_status:<{pad1}} |
| | Repo: {self.kl_repo:<32} | | | Repo: {self.kl_repo:<{pad1}} |
| 1) [Install] |------------------------------------| | 1) [Install] |------------------------------------|
| 2) [Update] | Moonraker: {self.mr_status:<32} | | 2) [Update] | Moonraker: {self.mr_status:<{pad1}} |
| 3) [Remove] | Repo: {self.mr_repo:<32} | | 3) [Remove] | Repo: {self.mr_repo:<{pad1}} |
| 4) [Advanced] |------------------------------------| | 4) [Advanced] |------------------------------------|
| 5) [Backup] | Mainsail: {self.ms_status:<35} | | 5) [Backup] | Mainsail: {self.ms_status:<{pad2}} |
| | Fluidd: {self.fl_status:<35} | | | Fluidd: {self.fl_status:<{pad2}} |
| S) [Settings] | Client-Config: {self.cc_status:<26} | | S) [Settings] | Client-Config: {self.cc_status:<{pad2}} |
| | | | | |
| Community: | KlipperScreen: {self.ks_status:<26} | | Community: | KlipperScreen: {self.ks_status:<{pad2}} |
| E) [Extensions] | Mobileraker: {self.mb_status:<26} | | E) [Extensions] | Mobileraker: {self.mb_status:<{pad2}} |
| | Crowsnest: {self.cn_status:<26} | | | Crowsnest: {self.cn_status:<{pad2}} |
|-------------------------------------------------------| |-------------------------------------------------------|
| {COLOR_CYAN}{footer1:^16}{RESET_FORMAT} | {footer2:^43} | | {COLOR_CYAN}{footer1:^16}{RESET_FORMAT} | {footer2:^43} |
""" """

View File

@@ -8,7 +8,7 @@
# ======================================================================= # # ======================================================================= #
import textwrap import textwrap
from typing import Type, Optional from typing import Optional, Type
from components.crowsnest.crowsnest import get_crowsnest_status, update_crowsnest from components.crowsnest.crowsnest import get_crowsnest_status, update_crowsnest
from components.klipper.klipper_setup import update_klipper from components.klipper.klipper_setup import update_klipper
@@ -16,12 +16,12 @@ from components.klipper.klipper_utils import (
get_klipper_status, get_klipper_status,
) )
from components.klipperscreen.klipperscreen import ( from components.klipperscreen.klipperscreen import (
update_klipperscreen,
get_klipperscreen_status, get_klipperscreen_status,
update_klipperscreen,
) )
from components.mobileraker.mobileraker import ( from components.mobileraker.mobileraker import (
update_mobileraker,
get_mobileraker_status, get_mobileraker_status,
update_mobileraker,
) )
from components.moonraker.moonraker_setup import update_moonraker from components.moonraker.moonraker_setup import update_moonraker
from components.moonraker.moonraker_utils import get_moonraker_status from components.moonraker.moonraker_utils import get_moonraker_status
@@ -39,10 +39,11 @@ from core.menus import Option
from core.menus.base_menu import BaseMenu from core.menus.base_menu import BaseMenu
from utils.constants import ( from utils.constants import (
COLOR_GREEN, COLOR_GREEN,
RESET_FORMAT,
COLOR_YELLOW,
COLOR_RED, COLOR_RED,
COLOR_YELLOW,
RESET_FORMAT,
) )
from utils.types import ComponentStatus
# noinspection PyUnusedLocal # noinspection PyUnusedLocal
@@ -177,7 +178,7 @@ class UpdateMenu(BaseMenu):
return f"{COLOR_YELLOW}{local_version}{RESET_FORMAT}" return f"{COLOR_YELLOW}{local_version}{RESET_FORMAT}"
def _get_update_status(self, name: str, status_fn: callable, *args) -> None: def _get_update_status(self, name: str, status_fn: callable, *args) -> None:
status_data = status_fn(*args) status_data: ComponentStatus = status_fn(*args)
local_ver = status_data.get("local") local_ver = status_data.get("local")
remote_ver = status_data.get("remote") remote_ver = status_data.get("remote")
color = COLOR_GREEN if remote_ver != "ERROR" else COLOR_RED color = COLOR_GREEN if remote_ver != "ERROR" else COLOR_RED

View File

@@ -9,7 +9,7 @@
import re import re
from datetime import datetime from datetime import datetime
from pathlib import Path from pathlib import Path
from typing import Dict, Literal, List, Type, Union from typing import Dict, List, Literal, Optional, Type
from components.klipper.klipper import Klipper from components.klipper.klipper import Klipper
from core.instance_manager.base_instance import BaseInstance from core.instance_manager.base_instance import BaseInstance
@@ -18,16 +18,15 @@ from utils import PRINTER_CFG_BACKUP_DIR
from utils.constants import ( from utils.constants import (
COLOR_CYAN, COLOR_CYAN,
RESET_FORMAT, RESET_FORMAT,
COLOR_YELLOW,
COLOR_GREEN,
COLOR_RED,
) )
from utils.git_utils import get_local_commit, get_remote_commit, get_repo_name
from utils.logger import Logger from utils.logger import Logger
from utils.sys_utils import ( from utils.sys_utils import (
check_package_install, check_package_install,
install_system_packages, install_system_packages,
update_system_package_lists, update_system_package_lists,
) )
from utils.types import ComponentStatus, InstallStatus
def convert_camelcase_to_kebabcase(name: str) -> str: def convert_camelcase_to_kebabcase(name: str) -> str:
@@ -64,78 +63,50 @@ def check_install_dependencies(deps: List[str]) -> None:
def get_install_status( def get_install_status(
repo_dir: Path, opt_files: List[Path] repo_dir: Path,
) -> Dict[Literal["status", "status_code", "instances"], Union[str, int]]: env_dir: Optional[Path] = None,
status = [repo_dir.exists()] instance_type: Optional[Type[BaseInstance]] = None,
files: Optional[List[Path]] = None,
for f in opt_files: ) -> ComponentStatus:
status.append(f.exists())
if all(status):
return {"status": "Installed!", "status_code": 1}
elif not any(status):
return {"status": "Not installed!", "status_code": 2}
else:
return {"status": "Incomplete!", "status_code": 3}
def get_install_status_common(
instance_type: Type[BaseInstance], repo_dir: Path, env_dir: Path
) -> Dict[Literal["status", "status_code", "instances"], Union[str, int]]:
""" """
Helper method to get the installation status of software components, Helper method to get the installation status of software components
which only consist of 3 major parts and if those parts exist, the
component can be considered as "installed". Typically, Klipper or
Moonraker match that criteria.
:param instance_type: The component type
:param repo_dir: the repository directory :param repo_dir: the repository directory
:param env_dir: the python environment directory :param env_dir: the python environment directory
:param instance_type: The component type
:param files: List of optional files to check for existence
:return: Dictionary with status string, statuscode and instance count :return: Dictionary with status string, statuscode and instance count
""" """
checks = [repo_dir.exists()]
if env_dir is not None:
checks.append(env_dir.exists())
im = InstanceManager(instance_type) im = InstanceManager(instance_type)
instances_exist = len(im.instances) > 0 instances = 0
status = [repo_dir.exists(), env_dir.exists(), instances_exist] if instance_type is not None:
if all(status): instances = len(im.instances)
return { checks.append(instances > 0)
"status": "Installed:",
"status_code": 1, if files is not None:
"instances": len(im.instances), for f in files:
} checks.append(f.exists())
elif not any(status):
return { if all(checks):
"status": "Not installed!", status = InstallStatus.INSTALLED
"status_code": 2,
"instances": len(im.instances), elif not any(checks):
} status = InstallStatus.NOT_INSTALLED
else: else:
return { status = InstallStatus.INCOMPLETE
"status": "Incomplete!",
"status_code": 3,
"instances": len(im.instances),
}
return ComponentStatus(
def get_install_status_webui( status=status,
install_dir: Path, nginx_cfg: Path, upstreams_cfg: Path, common_cfg: Path instances=instances,
) -> str: repo=get_repo_name(repo_dir),
""" local=get_local_commit(repo_dir),
Helper method to get the installation status of webuis remote=get_remote_commit(repo_dir),
like Mainsail or Fluidd | )
:param install_dir: folder of the static webui files
:param nginx_cfg: the webuis NGINX config
:param upstreams_cfg: the required upstreams.conf
:param common_cfg: the required common_vars.conf
:return: formatted string, containing the status
"""
status = [install_dir.exists(), nginx_cfg.exists()]
general_nginx_status = [upstreams_cfg.exists(), common_cfg.exists()]
if all(status) and all(general_nginx_status):
return f"{COLOR_GREEN}Installed!{RESET_FORMAT}"
elif not all(status):
return f"{COLOR_RED}Not installed!{RESET_FORMAT}"
else:
return f"{COLOR_YELLOW}Incomplete!{RESET_FORMAT}"
def backup_printer_config_dir(): def backup_printer_config_dir():

30
kiauh/utils/types.py Normal file
View File

@@ -0,0 +1,30 @@
# ======================================================================= #
# 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 enum import Enum
from typing import Optional, TypedDict
class StatusInfo:
def __init__(self, txt: str, code: int):
self.txt: str = txt
self.code: int = code
class InstallStatus(Enum):
INSTALLED = StatusInfo("Installed", 1)
NOT_INSTALLED = StatusInfo("Not installed", 2)
INCOMPLETE = StatusInfo("Incomplete", 3)
class ComponentStatus(TypedDict):
status: InstallStatus
repo: Optional[str]
local: Optional[str]
remote: Optional[str]
instances: Optional[int]