feat: add option to customize python binary for Klipper and Moonraker, add option to not install Moonraker speedups (#671)

Add option to cusomize python binary for klipper and moonraker. Add option to not install moonraker speedups.
This commit is contained in:
Pavel Sorejs
2025-04-06 22:23:39 +02:00
committed by GitHub
parent c91816d13f
commit 95cf809378
5 changed files with 60 additions and 32 deletions

View File

@@ -13,6 +13,10 @@ repositories:
https://github.com/Klipper3d/klipper
[moonraker]
# Moonraker supports two optional Python packages that can be used to reduce its CPU load
# If set to true, those packages will be installed during the Moonraker installation
optional_speedups: True
# add custom repositories here, if at least one is given, the first in the list will be used by default
# otherwise the official repository is used
#

View File

@@ -277,7 +277,7 @@ class KlipperSetupService:
try:
install_klipper_packages()
if create_python_venv(KLIPPER_ENV_DIR):
if create_python_venv(KLIPPER_ENV_DIR, False, False, self.settings.klipper.use_python_binary):
install_python_requirements(KLIPPER_ENV_DIR, KLIPPER_REQ_FILE)
except Exception:
Logger.print_error("Error during installation of Klipper requirements!")

View File

@@ -315,11 +315,12 @@ class MoonrakerSetupService:
try:
install_moonraker_packages()
if create_python_venv(MOONRAKER_ENV_DIR):
if create_python_venv(MOONRAKER_ENV_DIR, False, False, self.settings.moonraker.use_python_binary):
install_python_requirements(MOONRAKER_ENV_DIR, MOONRAKER_REQ_FILE)
install_python_requirements(
MOONRAKER_ENV_DIR, MOONRAKER_SPEEDUPS_REQ_FILE
)
if self.settings.moonraker.optional_speedups:
install_python_requirements(
MOONRAKER_ENV_DIR, MOONRAKER_SPEEDUPS_REQ_FILE
)
self.__install_polkit()
except Exception:
Logger.print_error("Error during installation of Moonraker requirements!")

View File

@@ -53,11 +53,16 @@ class Repository:
url: str
branch: str
@dataclass
class KlipperSettings:
repositories: List[Repository] | None = field(default=None)
use_python_binary: str | None = field(default=None)
@dataclass
class RepoSettings:
class MoonrakerSettings:
optional_speedups: bool | None = field(default=None)
repositories: List[Repository] | None = field(default=None)
use_python_binary: str | None = field(default=None)
@dataclass
class WebUiSettings:
@@ -93,8 +98,8 @@ class KiauhSettings:
self.__initialized = True
self.config = SimpleConfigParser()
self.kiauh = AppSettings()
self.klipper = RepoSettings()
self.moonraker = RepoSettings()
self.klipper = KlipperSettings()
self.moonraker = MoonrakerSettings()
self.mainsail = WebUiSettings()
self.fluidd = WebUiSettings()
@@ -154,6 +159,8 @@ class KiauhSettings:
self._validate_int("fluidd", "port")
self._validate_bool("fluidd", "unstable_releases")
self._validate_bool("moonraker", "optional_speedups")
except ValueError:
err = f"Invalid value for option '{self._v_option}' in section '{self._v_section}'"
__err_and_kill(err)
@@ -208,12 +215,17 @@ class KiauhSettings:
"kiauh", "backup_before_update"
)
self.moonraker.optional_speedups = self.config.getboolean("moonraker", "optional_speedups", True)
kl_repos = self.config.getval("klipper", "repositories")
self.klipper.repositories = self.__set_repo_state(kl_repos)
mr_repos = self.config.getval("moonraker", "repositories")
self.moonraker.repositories = self.__set_repo_state(mr_repos)
self.klipper.use_python_binary = self.config.getval("klipper", "use_python_binary", None)
self.moonraker.use_python_binary = self.config.getval("moonraker", "use_python_binary", None)
self.mainsail.port = self.config.getint("mainsail", "port")
self.mainsail.unstable_releases = self.config.getboolean(
"mainsail", "unstable_releases"

View File

@@ -95,6 +95,7 @@ def create_python_venv(
target: Path,
force: bool = False,
allow_access_to_system_site_packages: bool = False,
use_python_binary: str | None = None
) -> bool:
"""
Create a python 3 virtualenv at the provided target destination.
@@ -103,36 +104,46 @@ def create_python_venv(
:param target: Path where to create the virtualenv at
:param force: Force recreation of the virtualenv
:param allow_access_to_system_site_packages: give the virtual environment access to the system site-packages dir
:param use_python_binary: allows to override default python binary
:return: bool
"""
Logger.print_status("Set up Python virtual environment ...")
cmd = ["virtualenv", "-p", "/usr/bin/python3", target.as_posix()]
# If binarry override is not set, we use default defined here
python_binary = use_python_binary if use_python_binary else "/usr/bin/python3"
cmd = ["virtualenv", "-p", python_binary, target.as_posix()]
cmd.append(
"--system-site-packages"
) if allow_access_to_system_site_packages else None
if not target.exists():
try:
run(cmd, check=True)
Logger.print_ok("Setup of virtualenv successful!")
return True
except CalledProcessError as e:
Logger.print_error(f"Error setting up virtualenv:\n{e}")
return False
else:
if not force and not get_confirm(
"Virtualenv already exists. Re-create?", default_choice=False
):
Logger.print_info("Skipping re-creation of virtualenv ...")
return False
try:
shutil.rmtree(target)
create_python_venv(target)
return True
except OSError as e:
log = f"Error removing existing virtualenv: {e.strerror}"
Logger.print_error(log, False)
return False
n = 2
while(n > 0):
if not target.exists():
try:
run(cmd, check=True)
Logger.print_ok("Setup of virtualenv successful!")
return True
except CalledProcessError as e:
Logger.print_error(f"Error setting up virtualenv:\n{e}")
return False
else:
if n == 1:
# This case should never happen,
# but the function should still behave correctly
Logger.print_error("Virtualenv still exists after deletion.")
return False
if not force and not get_confirm(
"Virtualenv already exists. Re-create?", default_choice=False
):
Logger.print_info("Skipping re-creation of virtualenv ...")
return False
try:
shutil.rmtree(target)
n -= 1
except OSError as e:
log = f"Error removing existing virtualenv: {e.strerror}"
Logger.print_error(log, False)
return False
def update_python_pip(target: Path) -> None: