mirror of
https://github.com/blw1138/Zordon.git
synced 2025-12-17 08:48:13 +00:00
Add ability to ignore system builds
This commit is contained in:
@@ -34,7 +34,7 @@ class EngineManager:
|
|||||||
return obj
|
return obj
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def get_engines(cls, filter_name=None, include_corrupt=False):
|
def get_engines(cls, filter_name=None, include_corrupt=False, ignore_system=False):
|
||||||
|
|
||||||
if not cls.engines_path:
|
if not cls.engines_path:
|
||||||
raise FileNotFoundError("Engine path is not set")
|
raise FileNotFoundError("Engine path is not set")
|
||||||
@@ -96,46 +96,47 @@ class EngineManager:
|
|||||||
'type': 'system'
|
'type': 'system'
|
||||||
}
|
}
|
||||||
|
|
||||||
with concurrent.futures.ThreadPoolExecutor() as executor:
|
if not ignore_system:
|
||||||
futures = {
|
with concurrent.futures.ThreadPoolExecutor() as executor:
|
||||||
executor.submit(fetch_engine_details, eng, include_corrupt): eng.name()
|
futures = {
|
||||||
for eng in cls.supported_engines()
|
executor.submit(fetch_engine_details, eng, include_corrupt): eng.name()
|
||||||
if eng.default_renderer_path() and (not filter_name or filter_name == eng.name())
|
for eng in cls.supported_engines()
|
||||||
}
|
if eng.default_renderer_path() and (not filter_name or filter_name == eng.name())
|
||||||
|
}
|
||||||
|
|
||||||
for future in concurrent.futures.as_completed(futures):
|
for future in concurrent.futures.as_completed(futures):
|
||||||
result = future.result()
|
result = future.result()
|
||||||
if result:
|
if result:
|
||||||
results.append(result)
|
results.append(result)
|
||||||
|
|
||||||
return results
|
return results
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def all_versions_for_engine(cls, engine_name, include_corrupt=False):
|
def all_versions_for_engine(cls, engine_name, include_corrupt=False, ignore_system=False):
|
||||||
versions = cls.get_engines(filter_name=engine_name, include_corrupt=include_corrupt)
|
versions = cls.get_engines(filter_name=engine_name, include_corrupt=include_corrupt, ignore_system=ignore_system)
|
||||||
sorted_versions = sorted(versions, key=lambda x: x['version'], reverse=True)
|
sorted_versions = sorted(versions, key=lambda x: x['version'], reverse=True)
|
||||||
return sorted_versions
|
return sorted_versions
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def newest_engine_version(cls, engine, system_os=None, cpu=None):
|
def newest_engine_version(cls, engine, system_os=None, cpu=None, ignore_system=None):
|
||||||
system_os = system_os or current_system_os()
|
system_os = system_os or current_system_os()
|
||||||
cpu = cpu or current_system_cpu()
|
cpu = cpu or current_system_cpu()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
filtered = [x for x in cls.all_versions_for_engine(engine) if x['system_os'] == system_os and
|
filtered = [x for x in cls.all_versions_for_engine(engine, ignore_system=ignore_system)
|
||||||
x['cpu'] == cpu]
|
if x['system_os'] == system_os and x['cpu'] == cpu]
|
||||||
return filtered[0]
|
return filtered[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
logger.error(f"Cannot find newest engine version for {engine}-{system_os}-{cpu}")
|
logger.error(f"Cannot find newest engine version for {engine}-{system_os}-{cpu}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def is_version_downloaded(cls, engine, version, system_os=None, cpu=None):
|
def is_version_downloaded(cls, engine, version, system_os=None, cpu=None, ignore_system=False):
|
||||||
system_os = system_os or current_system_os()
|
system_os = system_os or current_system_os()
|
||||||
cpu = cpu or current_system_cpu()
|
cpu = cpu or current_system_cpu()
|
||||||
|
|
||||||
filtered = [x for x in cls.get_engines(filter_name=engine) if x['system_os'] == system_os and
|
filtered = [x for x in cls.get_engines(filter_name=engine, ignore_system=ignore_system) if
|
||||||
x['cpu'] == cpu and x['version'] == version]
|
x['system_os'] == system_os and x['cpu'] == cpu and x['version'] == version]
|
||||||
return filtered[0] if filtered else False
|
return filtered[0] if filtered else False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -168,7 +169,7 @@ class EngineManager:
|
|||||||
return None
|
return None
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def download_engine(cls, engine, version, system_os=None, cpu=None, background=False):
|
def download_engine(cls, engine, version, system_os=None, cpu=None, background=False, ignore_system=False):
|
||||||
|
|
||||||
engine_to_download = cls.engine_with_name(engine)
|
engine_to_download = cls.engine_with_name(engine)
|
||||||
existing_task = cls.get_existing_download_task(engine, version, system_os, cpu)
|
existing_task = cls.get_existing_download_task(engine, version, system_os, cpu)
|
||||||
@@ -191,7 +192,7 @@ class EngineManager:
|
|||||||
return thread
|
return thread
|
||||||
|
|
||||||
thread.join()
|
thread.join()
|
||||||
found_engine = cls.is_version_downloaded(engine, version, system_os, cpu) # Check that engine downloaded
|
found_engine = cls.is_version_downloaded(engine, version, system_os, cpu, ignore_system) # Check that engine downloaded
|
||||||
if not found_engine:
|
if not found_engine:
|
||||||
logger.error(f"Error downloading {engine}")
|
logger.error(f"Error downloading {engine}")
|
||||||
return found_engine
|
return found_engine
|
||||||
@@ -217,34 +218,7 @@ class EngineManager:
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def update_all_engines(cls):
|
def is_engine_update_available(cls, engine_class, ignore_system_installs=False):
|
||||||
def engine_update_task(engine_class):
|
|
||||||
logger.debug(f"Checking for updates to {engine_class.name()}")
|
|
||||||
latest_version = engine_class.downloader().find_most_recent_version()
|
|
||||||
|
|
||||||
if not latest_version:
|
|
||||||
logger.warning(f"Could not find most recent version of {engine.name()} to download")
|
|
||||||
return
|
|
||||||
|
|
||||||
version_num = latest_version.get('version')
|
|
||||||
if cls.is_version_downloaded(engine_class.name(), version_num):
|
|
||||||
logger.debug(f"Latest version of {engine_class.name()} ({version_num}) already downloaded")
|
|
||||||
return
|
|
||||||
|
|
||||||
# download the engine
|
|
||||||
logger.info(f"Downloading latest version of {engine_class.name()} ({version_num})...")
|
|
||||||
cls.download_engine(engine=engine_class.name(), version=version_num, background=True)
|
|
||||||
|
|
||||||
logger.info(f"Checking for updates for render engines...")
|
|
||||||
threads = []
|
|
||||||
for engine in cls.supported_engines():
|
|
||||||
if engine.downloader():
|
|
||||||
thread = threading.Thread(target=engine_update_task, args=(engine,))
|
|
||||||
threads.append(thread)
|
|
||||||
thread.start()
|
|
||||||
|
|
||||||
@classmethod
|
|
||||||
def update_engine(cls, engine_class):
|
|
||||||
logger.debug(f"Checking for updates to {engine_class.name()}")
|
logger.debug(f"Checking for updates to {engine_class.name()}")
|
||||||
latest_version = engine_class.downloader().find_most_recent_version()
|
latest_version = engine_class.downloader().find_most_recent_version()
|
||||||
|
|
||||||
@@ -253,15 +227,11 @@ class EngineManager:
|
|||||||
return
|
return
|
||||||
|
|
||||||
version_num = latest_version.get('version')
|
version_num = latest_version.get('version')
|
||||||
if cls.is_version_downloaded(engine_class.name(), version_num):
|
if cls.is_version_downloaded(engine_class.name(), version_num, ignore_system=ignore_system_installs):
|
||||||
logger.debug(f"Latest version of {engine_class.name()} ({version_num}) already downloaded")
|
logger.debug(f"Latest version of {engine_class.name()} ({version_num}) already downloaded")
|
||||||
return
|
return
|
||||||
|
|
||||||
# download the engine
|
return latest_version
|
||||||
logger.info(f"Downloading latest version of {engine_class.name()} ({version_num})...")
|
|
||||||
download_job = cls.download_engine(engine=engine_class.name(), version=version_num, background=True)
|
|
||||||
|
|
||||||
return {"latest": latest_version, "thread": download_job, "name": engine_class.name()}
|
|
||||||
|
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
@@ -330,7 +300,8 @@ class EngineDownloadWorker(threading.Thread):
|
|||||||
self.cpu = cpu
|
self.cpu = cpu
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
existing_download = EngineManager.is_version_downloaded(self.engine, self.version, self.system_os, self.cpu)
|
existing_download = EngineManager.is_version_downloaded(self.engine, self.version, self.system_os, self.cpu,
|
||||||
|
ignore_system=True)
|
||||||
if existing_download:
|
if existing_download:
|
||||||
logger.info(f"Requested download of {self.engine} {self.version}, but local copy already exists")
|
logger.info(f"Requested download of {self.engine} {self.version}, but local copy already exists")
|
||||||
return existing_download
|
return existing_download
|
||||||
|
|||||||
20
src/init.py
20
src/init.py
@@ -5,6 +5,9 @@ import socket
|
|||||||
import sys
|
import sys
|
||||||
import threading
|
import threading
|
||||||
from collections import deque
|
from collections import deque
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from PyQt6.QtCore import QSettings
|
||||||
|
|
||||||
from src.api.api_server import start_server
|
from src.api.api_server import start_server
|
||||||
from src.api.preview_manager import PreviewManager
|
from src.api.preview_manager import PreviewManager
|
||||||
@@ -16,7 +19,7 @@ from src.utilities.config import Config
|
|||||||
from src.utilities.misc_helper import (system_safe_path, current_system_cpu, current_system_os,
|
from src.utilities.misc_helper import (system_safe_path, current_system_cpu, current_system_os,
|
||||||
current_system_os_version, check_for_updates)
|
current_system_os_version, check_for_updates)
|
||||||
from src.utilities.zeroconf_server import ZeroconfServer
|
from src.utilities.zeroconf_server import ZeroconfServer
|
||||||
from version import APP_NAME, APP_VERSION, APP_REPO_NAME, APP_REPO_OWNER
|
from version import APP_NAME, APP_VERSION, APP_REPO_NAME, APP_REPO_OWNER, APP_AUTHOR
|
||||||
|
|
||||||
logger = logging.getLogger()
|
logger = logging.getLogger()
|
||||||
|
|
||||||
@@ -66,6 +69,8 @@ def run(server_only=False) -> int:
|
|||||||
APP_VERSION))
|
APP_VERSION))
|
||||||
update_thread.start()
|
update_thread.start()
|
||||||
|
|
||||||
|
settings = QSettings(APP_AUTHOR, APP_NAME)
|
||||||
|
|
||||||
# main start
|
# main start
|
||||||
logger.info(f"Starting {APP_NAME} Render Server")
|
logger.info(f"Starting {APP_NAME} Render Server")
|
||||||
return_code = 0
|
return_code = 0
|
||||||
@@ -92,9 +97,16 @@ def run(server_only=False) -> int:
|
|||||||
ServerProxyManager.subscribe_to_listener()
|
ServerProxyManager.subscribe_to_listener()
|
||||||
DistributedJobManager.subscribe_to_listener()
|
DistributedJobManager.subscribe_to_listener()
|
||||||
|
|
||||||
# check for updates for render engines if configured or on first launch
|
# check for updates for render engines if configured
|
||||||
if Config.update_engines_on_launch or not EngineManager.get_engines():
|
ignore_system = settings.value("engines_ignore_system_installs", False)
|
||||||
EngineManager.update_all_engines()
|
if settings.value('check_for_engine_updates_on_launch', False):
|
||||||
|
for engine in EngineManager.downloadable_engines():
|
||||||
|
if settings.value(f'engine_download-{engine.name()}', False):
|
||||||
|
update_result = EngineManager.is_engine_update_available(engine, ignore_system_installs=ignore_system)
|
||||||
|
EngineManager.download_engine(engine=engine.name(), version=update_result['version'],
|
||||||
|
background=True,
|
||||||
|
ignore_system=ignore_system)
|
||||||
|
settings.setValue("engines_last_update_time", datetime.now().isoformat())
|
||||||
|
|
||||||
# get hostname
|
# get hostname
|
||||||
local_hostname = socket.gethostname()
|
local_hostname = socket.gethostname()
|
||||||
|
|||||||
@@ -184,6 +184,12 @@ class SettingsWindow(QMainWindow):
|
|||||||
installed_layout = QVBoxLayout()
|
installed_layout = QVBoxLayout()
|
||||||
self.installed_engines_table = EngineTableWidget()
|
self.installed_engines_table = EngineTableWidget()
|
||||||
installed_layout.addWidget(self.installed_engines_table)
|
installed_layout.addWidget(self.installed_engines_table)
|
||||||
|
|
||||||
|
engine_ignore_system_installs_checkbox = QCheckBox("Ignore system installs")
|
||||||
|
engine_ignore_system_installs_checkbox.setChecked(settings.value("engines_ignore_system_installs", False))
|
||||||
|
engine_ignore_system_installs_checkbox.stateChanged.connect(self.change_ignore_system_installs)
|
||||||
|
installed_layout.addWidget(engine_ignore_system_installs_checkbox)
|
||||||
|
|
||||||
installed_buttons_layout = QHBoxLayout()
|
installed_buttons_layout = QHBoxLayout()
|
||||||
launch_engine_button = QPushButton("Launch")
|
launch_engine_button = QPushButton("Launch")
|
||||||
launch_engine_button.clicked.connect(self.launch_selected_engine)
|
launch_engine_button.clicked.connect(self.launch_selected_engine)
|
||||||
@@ -226,7 +232,7 @@ class SettingsWindow(QMainWindow):
|
|||||||
self.update_last_checked_label()
|
self.update_last_checked_label()
|
||||||
self.engines_last_update_label.setEnabled(at_least_one_downloadable)
|
self.engines_last_update_label.setEnabled(at_least_one_downloadable)
|
||||||
engine_updates_layout.addWidget(self.engines_last_update_label)
|
engine_updates_layout.addWidget(self.engines_last_update_label)
|
||||||
self.check_for_new_engines_button = QPushButton("Check for New Versions")
|
self.check_for_new_engines_button = QPushButton("Check for New Versions...")
|
||||||
self.check_for_new_engines_button.setEnabled(at_least_one_downloadable)
|
self.check_for_new_engines_button.setEnabled(at_least_one_downloadable)
|
||||||
self.check_for_new_engines_button.clicked.connect(self.check_for_new_engines)
|
self.check_for_new_engines_button.clicked.connect(self.check_for_new_engines)
|
||||||
engine_updates_layout.addWidget(self.check_for_new_engines_button)
|
engine_updates_layout.addWidget(self.check_for_new_engines_button)
|
||||||
@@ -239,6 +245,11 @@ class SettingsWindow(QMainWindow):
|
|||||||
page.setLayout(layout)
|
page.setLayout(layout)
|
||||||
return page
|
return page
|
||||||
|
|
||||||
|
def change_ignore_system_installs(self, value):
|
||||||
|
settings.setValue("engines_ignore_system_installs", bool(value))
|
||||||
|
self.installed_engines_table.update_table()
|
||||||
|
|
||||||
|
|
||||||
def update_last_checked_label(self):
|
def update_last_checked_label(self):
|
||||||
"""Retrieve the last check timestamp and return a human-friendly string."""
|
"""Retrieve the last check timestamp and return a human-friendly string."""
|
||||||
last_checked_str = settings.value("engines_last_update_time", None)
|
last_checked_str = settings.value("engines_last_update_time", None)
|
||||||
@@ -275,22 +286,27 @@ class SettingsWindow(QMainWindow):
|
|||||||
os.path.join(os.path.join(os.path.expanduser(Config.upload_folder),
|
os.path.join(os.path.join(os.path.expanduser(Config.upload_folder),
|
||||||
'engines')))
|
'engines')))
|
||||||
|
|
||||||
results = []
|
ignore_system = settings.value("engines_ignore_system_installs", False)
|
||||||
|
messagebox_shown = False
|
||||||
for engine in EngineManager.downloadable_engines():
|
for engine in EngineManager.downloadable_engines():
|
||||||
if settings.value(f'engine_download-{engine.name()}', False):
|
if settings.value(f'engine_download-{engine.name()}', False):
|
||||||
update_result = EngineManager.update_engine(engine)
|
result = EngineManager.is_engine_update_available(engine, ignore_system_installs=ignore_system)
|
||||||
if update_result:
|
if result:
|
||||||
results.append(update_result)
|
result['name'] = engine.name()
|
||||||
|
msg_box = QMessageBox()
|
||||||
|
msg_box.setWindowTitle(f"{result['name']} ({result['version']}) Available")
|
||||||
|
msg_box.setText(f"A new version of {result['name']} is available ({result['version']}).\n\n"
|
||||||
|
f"Would you like to download it now?")
|
||||||
|
msg_box.setIcon(QMessageBox.Icon.Information)
|
||||||
|
msg_box.setStandardButtons(QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)
|
||||||
|
msg_result = msg_box.exec()
|
||||||
|
messagebox_shown = True
|
||||||
|
if msg_result == QMessageBox.StandardButton.Yes:
|
||||||
|
EngineManager.download_engine(engine=engine.name(), version=result['version'], background=True,
|
||||||
|
ignore_system=ignore_system)
|
||||||
|
self.update_engine_download_status()
|
||||||
|
|
||||||
if results:
|
if not messagebox_shown:
|
||||||
for result in results:
|
|
||||||
msg_box = QMessageBox()
|
|
||||||
msg_box.setWindowTitle(f"{result['name']} {result['version']} Available")
|
|
||||||
msg_box.setText(f"A new version of {result['name']} is available ({result['version']}). It will begin downloading now.")
|
|
||||||
msg_box.setIcon(QMessageBox.Icon.Information)
|
|
||||||
msg_box.setStandardButtons(QMessageBox.StandardButton.Ok)
|
|
||||||
msg_box.exec()
|
|
||||||
else:
|
|
||||||
msg_box = QMessageBox()
|
msg_box = QMessageBox()
|
||||||
msg_box.setWindowTitle("No Updates Available")
|
msg_box.setWindowTitle("No Updates Available")
|
||||||
msg_box.setText("All your render engines are up-to-date.")
|
msg_box.setText("All your render engines are up-to-date.")
|
||||||
@@ -299,7 +315,16 @@ class SettingsWindow(QMainWindow):
|
|||||||
msg_box.exec()
|
msg_box.exec()
|
||||||
|
|
||||||
settings.setValue("engines_last_update_time", datetime.now().isoformat())
|
settings.setValue("engines_last_update_time", datetime.now().isoformat())
|
||||||
self.update_last_checked_label()
|
self.update_engine_download_status()
|
||||||
|
|
||||||
|
def update_engine_download_status(self):
|
||||||
|
running_tasks = [x for x in EngineManager.download_tasks if x.is_alive()]
|
||||||
|
if not running_tasks:
|
||||||
|
self.update_last_checked_label()
|
||||||
|
return
|
||||||
|
|
||||||
|
self.engines_last_update_label.setText(f"Downloading {running_tasks[0].engine} ({running_tasks[0].version})...")
|
||||||
|
|
||||||
|
|
||||||
class EngineTableWidget(QWidget):
|
class EngineTableWidget(QWidget):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
@@ -315,20 +340,26 @@ class EngineTableWidget(QWidget):
|
|||||||
layout = QVBoxLayout(self)
|
layout = QVBoxLayout(self)
|
||||||
layout.addWidget(self.table)
|
layout.addWidget(self.table)
|
||||||
|
|
||||||
|
self.raw_server_data = None
|
||||||
|
|
||||||
def showEvent(self, event):
|
def showEvent(self, event):
|
||||||
"""Runs when the widget is about to be shown."""
|
"""Runs when the widget is about to be shown."""
|
||||||
self.update_table()
|
self.update_table()
|
||||||
super().showEvent(event) # Ensure normal event processing
|
super().showEvent(event) # Ensure normal event processing
|
||||||
|
|
||||||
def update_table(self):
|
def update_table(self, use_cached=True):
|
||||||
raw_server_data = RenderServerProxy(socket.gethostname()).get_renderer_info()
|
if not self.raw_server_data or not use_cached:
|
||||||
if not raw_server_data:
|
self.raw_server_data = RenderServerProxy(socket.gethostname()).get_renderer_info()
|
||||||
|
if not self.raw_server_data:
|
||||||
return
|
return
|
||||||
|
|
||||||
table_data = [] # convert the data into a flat list
|
table_data = [] # convert the data into a flat list
|
||||||
for _, engine_data in raw_server_data.items():
|
for _, engine_data in self.raw_server_data.items():
|
||||||
table_data.extend(engine_data['versions'])
|
table_data.extend(engine_data['versions'])
|
||||||
|
|
||||||
|
if settings.value("engines_ignore_system_installs", False):
|
||||||
|
table_data = [x for x in table_data if x['type'] != 'system']
|
||||||
|
|
||||||
self.table.clear()
|
self.table.clear()
|
||||||
self.table.setRowCount(len(table_data))
|
self.table.setRowCount(len(table_data))
|
||||||
self.table.setColumnCount(4)
|
self.table.setColumnCount(4)
|
||||||
@@ -364,6 +395,7 @@ class EngineTableWidget(QWidget):
|
|||||||
return data
|
return data
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
app = QApplication([])
|
app = QApplication([])
|
||||||
window = SettingsWindow()
|
window = SettingsWindow()
|
||||||
|
|||||||
Reference in New Issue
Block a user