SXXXXXXX_PyInstallerGUIWrapper/pyinstallerguiwrapper/builder.py
2025-06-10 09:09:06 +02:00

86 lines
3.8 KiB
Python

# -*- coding: utf-8 -*-
"""builder.py - Handles the execution of the PyInstaller build process in a separate thread."""
import subprocess
import os
import traceback
from typing import Optional, List, Dict, Callable
def run_build_in_thread(
command: List[str],
working_dir: str,
output_queue: 'queue.Queue',
logger_func: Callable[..., None],
output_dir_name: str,
environment: Optional[Dict[str, str]] = None
):
"""
Executes the PyInstaller command using subprocess.Popen in the background.
Streams stdout/stderr to the output_queue for display in the GUI.
Notifies the main thread of success, failure, or completion via the queue.
"""
build_process = None
try:
logger_func("Build thread starting execution...", level="INFO")
command_str_for_log = " ".join([f'"{c}"' if " " in c else c for c in command])
logger_func(f"PyInstaller command to be executed: {command_str_for_log}", level="DEBUG")
logger_func(f"Working directory: {working_dir}", level="DEBUG")
env_log_msg = f"Using {'custom' if environment else 'inherited'} environment."
logger_func(f"PyInstaller process starting. {env_log_msg}", level="INFO")
build_process = subprocess.Popen(
command,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
cwd=working_dir,
text=True,
encoding="utf-8",
errors="replace",
bufsize=1,
env=environment,
)
logger_func(f"PyInstaller process launched (PID: {build_process.pid}).", level="INFO")
# Stream output
while True:
line = build_process.stdout.readline()
if not line:
if build_process.poll() is not None:
logger_func("End of PyInstaller output stream.", level="DEBUG")
break
else:
continue
# Messaggio per il logger della GUI
output_queue.put(("LOG_STREAM", "LOG", line))
return_code = build_process.wait()
logger_func(f"PyInstaller process finished with exit code: {return_code}", level="INFO")
if return_code == 0:
dist_path_abs = os.path.join(working_dir, output_dir_name)
if os.path.exists(dist_path_abs):
success_msg = f"Build completed successfully!\nOutput Directory: {dist_path_abs}"
# Messaggio per la GUI principale
output_queue.put(("MAIN_GUI_ACTION", "BUILD_SUCCESS", success_msg))
else:
warn_msg = f"Build finished with exit code 0, but output directory not found:\n{dist_path_abs}\nCheck the full log for potential issues."
logger_func(warn_msg, level="WARNING")
output_queue.put(("MAIN_GUI_ACTION", "BUILD_ERROR", warn_msg))
else:
error_msg = f"Build failed! (Exit Code: {return_code})\nCheck the log for details."
output_queue.put(("MAIN_GUI_ACTION", "BUILD_ERROR", error_msg))
except FileNotFoundError:
error_msg = "Error: 'pyinstaller' command not found.\nEnsure PyInstaller is installed correctly and in the system PATH."
output_queue.put(("MAIN_GUI_ACTION", "BUILD_ERROR", error_msg))
logger_func(error_msg, level="CRITICAL")
except Exception as e:
error_msg = f"Unexpected error during build process execution: {e}"
output_queue.put(("MAIN_GUI_ACTION", "BUILD_ERROR", error_msg))
logger_func(error_msg, level="CRITICAL")
logger_func(traceback.format_exc(), level="DEBUG")
finally:
# Segnala sempre la fine del tentativo di build
output_queue.put(("MAIN_GUI_ACTION", "BUILD_FINISHED", None))
logger_func("Build thread finished.", level="INFO")