Pyinstaller support (#93)

* Add main.spec

* Fix issue where fetching supported extensions would crash with no default installation
This commit is contained in:
2024-08-10 14:58:41 -05:00
committed by GitHub
parent 51a5a63944
commit 3b33649f2d
10 changed files with 89 additions and 41 deletions

64
main.spec Normal file
View File

@@ -0,0 +1,64 @@
# -*- mode: python ; coding: utf-8 -*-
from PyInstaller.utils.hooks import collect_all
# - get version from version file
import os
import sys
sys.path.insert(0, os.path.abspath('.'))
from version import APP_NAME, APP_VERSION
datas = [('resources', 'resources'), ('src/engines/blender/scripts/', 'src/engines/blender/scripts')]
binaries = []
hiddenimports = ['zeroconf']
tmp_ret = collect_all('zeroconf')
datas += tmp_ret[0]; binaries += tmp_ret[1]; hiddenimports += tmp_ret[2]
a = Analysis(
['main.py'],
pathex=[],
binaries=binaries,
datas=datas,
hiddenimports=hiddenimports,
hookspath=[],
hooksconfig={},
runtime_hooks=[],
excludes=[],
noarchive=False,
optimize=0,
)
pyz = PYZ(a.pure)
exe = EXE(
pyz,
a.scripts,
[],
exclude_binaries=True,
name='main',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=False,
disable_windowed_traceback=False,
argv_emulation=False,
target_arch=None,
codesign_identity=None,
entitlements_file=None,
)
coll = COLLECT(
exe,
a.binaries,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='main',
)
app = BUNDLE(
coll,
name=f'{APP_NAME}.app',
icon=None,
bundle_identifier=None,
version=APP_VERSION
)

View File

@@ -1,22 +0,0 @@
"""
This is a setup.py script generated by py2applet
Usage:
python setup.py py2app
"""
import glob
from setuptools import setup
APP = ['main.py']
DATA_FILES = [('config', glob.glob('config/*.*')),
('resources', glob.glob('resources/*.*'))]
OPTIONS = {}
setup(
app=APP,
data_files=DATA_FILES,
options={'py2app': OPTIONS},
setup_requires=['py2app'],
name='Zordon'
)

View File

@@ -22,12 +22,12 @@ class Blender(BaseRenderEngine):
from src.engines.blender.blender_worker import BlenderRenderWorker from src.engines.blender.blender_worker import BlenderRenderWorker
return BlenderRenderWorker return BlenderRenderWorker
def ui_options(self):
from src.engines.blender.blender_ui import BlenderUI
return BlenderUI.get_options(self)
@staticmethod @staticmethod
def supported_extensions(): def ui_options(system_info):
from src.engines.blender.blender_ui import BlenderUI
return BlenderUI.get_options(system_info)
def supported_extensions(self):
return ['blend'] return ['blend']
def version(self): def version(self):

View File

@@ -1,9 +1,9 @@
class BlenderUI: class BlenderUI:
@staticmethod @staticmethod
def get_options(instance): def get_options(system_info):
options = [ options = [
{'name': 'engine', 'options': instance.supported_render_engines()}, {'name': 'engine', 'options': system_info.get('engines', [])},
{'name': 'render_device', 'options': ['Any', 'GPU', 'CPU']}, {'name': 'render_device', 'options': ['Any', 'GPU', 'CPU']},
] ]
return options return options

View File

@@ -9,12 +9,11 @@ SUBPROCESS_TIMEOUT = 5
class BaseRenderEngine(object): class BaseRenderEngine(object):
install_paths = [] install_paths = []
supported_extensions = []
def __init__(self, custom_path=None): def __init__(self, custom_path=None):
self.custom_renderer_path = custom_path self.custom_renderer_path = custom_path
if not self.renderer_path() or not os.path.exists(self.renderer_path()): if not self.renderer_path() or not os.path.exists(self.renderer_path()):
raise FileNotFoundError(f"Cannot find path to renderer for {self.name()} instance") raise FileNotFoundError(f"Cannot find path to renderer for {self.name()} instance: {self.renderer_path()}")
if not os.access(self.renderer_path(), os.X_OK): if not os.access(self.renderer_path(), os.X_OK):
logger.warning(f"Path is not executable. Setting permissions to 755 for {self.renderer_path()}") logger.warning(f"Path is not executable. Setting permissions to 755 for {self.renderer_path()}")
@@ -43,6 +42,9 @@ class BaseRenderEngine(object):
def version(self): def version(self):
raise NotImplementedError("version not implemented") raise NotImplementedError("version not implemented")
def supported_extensions(self):
return []
@staticmethod @staticmethod
def downloader(): # override when subclassing if using a downloader class def downloader(): # override when subclassing if using a downloader class
return None return None
@@ -51,7 +53,8 @@ class BaseRenderEngine(object):
def worker_class(): # override when subclassing to link worker class def worker_class(): # override when subclassing to link worker class
raise NotImplementedError("Worker class not implemented") raise NotImplementedError("Worker class not implemented")
def ui_options(self): # override to return options for ui @staticmethod
def ui_options(system_info): # override to return options for ui
return {} return {}
def get_help(self): # override if renderer uses different help flag def get_help(self): # override if renderer uses different help flag

View File

@@ -266,9 +266,9 @@ class EngineManager:
_, extension = os.path.splitext(path) _, extension = os.path.splitext(path)
extension = extension.lower().strip('.') extension = extension.lower().strip('.')
for engine in cls.supported_engines(): for engine in cls.supported_engines():
if extension in engine.supported_extensions(): if extension in engine().supported_extensions():
return engine return engine
undefined_renderer_support = [x for x in cls.supported_engines() if not x.supported_extensions()] undefined_renderer_support = [x for x in cls.supported_engines() if not x().supported_extensions()]
return undefined_renderer_support[0] return undefined_renderer_support[0]

View File

@@ -21,9 +21,8 @@ class FFMPEG(BaseRenderEngine):
from src.engines.ffmpeg.ffmpeg_ui import FFMPEGUI from src.engines.ffmpeg.ffmpeg_ui import FFMPEGUI
return FFMPEGUI.get_options(self) return FFMPEGUI.get_options(self)
@classmethod def supported_extensions(self):
def supported_extensions(cls): help_text = (subprocess.check_output([self.renderer_path(), '-h', 'full'], stderr=subprocess.STDOUT)
help_text = (subprocess.check_output([cls().renderer_path(), '-h', 'full'], stderr=subprocess.STDOUT)
.decode('utf-8')) .decode('utf-8'))
found = re.findall(r'extensions that .* is allowed to access \(default "(.*)"', help_text) found = re.findall(r'extensions that .* is allowed to access \(default "(.*)"', help_text)
found_extensions = set() found_extensions = set()

View File

@@ -1,5 +1,5 @@
class FFMPEGUI: class FFMPEGUI:
@staticmethod @staticmethod
def get_options(instance): def get_options(system_info):
options = [] options = []
return options return options

View File

@@ -68,11 +68,12 @@ class NewRenderJobForm(QWidget):
# Setup # Setup
self.setWindowTitle("New Job") self.setWindowTitle("New Job")
self.setup_ui() self.setup_ui()
self.update_renderer_info()
self.setup_project() self.setup_project()
# get renderer info in bg thread # get renderer info in bg thread
t = threading.Thread(target=self.update_renderer_info) # t = threading.Thread(target=self.update_renderer_info)
t.start() # t.start()
self.show() self.show()
@@ -348,7 +349,8 @@ class NewRenderJobForm(QWidget):
# Dynamic Engine Options # Dynamic Engine Options
clear_layout(self.renderer_options_layout) # clear old options clear_layout(self.renderer_options_layout) # clear old options
# dynamically populate option list # dynamically populate option list
self.current_engine_options = engine().ui_options() system_info = self.renderer_info.get(engine.name(), {}).get('system_info', {})
self.current_engine_options = engine.ui_options(system_info=system_info)
for option in self.current_engine_options: for option in self.current_engine_options:
h_layout = QHBoxLayout() h_layout = QHBoxLayout()
label = QLabel(option['name'].replace('_', ' ').capitalize() + ':') label = QLabel(option['name'].replace('_', ' ').capitalize() + ':')

2
version.py Normal file
View File

@@ -0,0 +1,2 @@
APP_NAME = "Zordon"
APP_VERSION = "0.0.1"