86 lines
3.8 KiB
Python
86 lines
3.8 KiB
Python
# File: pyinstallerguiwrapper/helpers/wexpect_console_entry.py
|
|
"""
|
|
Entry point for the standalone wexpect console helper executable.
|
|
This script is compiled by PyInstaller (triggered by the GUI Wrapper)
|
|
to create an executable that wexpect.host.SpawnBase can launch when
|
|
the main application is frozen.
|
|
"""
|
|
import sys
|
|
import os
|
|
import time # For error log timestamp
|
|
import traceback
|
|
|
|
# Attempt to set up basic logging to a file if something goes wrong INSIDE this helper.
|
|
# This is for debugging the helper itself, not the main app or wexpect's own logging.
|
|
HELPER_ERROR_LOG = "wexpect_helper_runtime_error.log"
|
|
|
|
|
|
def log_helper_error(message, ex_info=False):
|
|
try:
|
|
log_path = HELPER_ERROR_LOG
|
|
# Try to place log near the helper executable if frozen
|
|
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
|
|
# When frozen, sys.executable is the original path, not in _MEIPASS
|
|
# So, log relative to the helper's actual location.
|
|
exe_dir = os.path.dirname(
|
|
sys.executable
|
|
) # sys.executable is this helper.exe
|
|
log_path = os.path.join(exe_dir, HELPER_ERROR_LOG)
|
|
|
|
with open(log_path, "a", encoding="utf-8") as f:
|
|
f.write(f"Timestamp: {time.strftime('%Y-%m-%d %H:%M:%S')}\n")
|
|
f.write(f"Helper Entry Args: {sys.argv}\n")
|
|
f.write(f"Error: {message}\n")
|
|
if ex_info:
|
|
f.write(traceback.format_exc())
|
|
f.write("-" * 70 + "\n")
|
|
except Exception as log_e:
|
|
# Fallback print if logging to file fails
|
|
print(
|
|
f"CRITICAL HELPER LOG ERROR: Cannot write to {log_path}: {log_e}",
|
|
file=sys.stderr,
|
|
)
|
|
print(f"Original Helper Error: {message}", file=sys.stderr)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
# When this script is run as the entry point of the compiled helper.exe,
|
|
# sys.argv will contain the arguments passed by wexpect.host.SpawnBase.startChild:
|
|
# e.g., wexpect_helper.exe --console_reader_class=ConsoleReaderPipe --host_pid=... -- "actual_command" "arg1"
|
|
# The wexpect.console_reader_base.main() function is designed to parse these arguments from sys.argv.
|
|
|
|
# For PyInstaller frozen builds, ensure paths are set up correctly for wexpect to find its modules
|
|
# This is usually handled by PyInstaller itself if wexpect is a hidden import.
|
|
if getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS"):
|
|
# Add _MEIPASS to sys.path if not already there, might help some imports.
|
|
# However, PyInstaller usually does this.
|
|
# if sys._MEIPASS not in sys.path:
|
|
# sys.path.insert(0, sys._MEIPASS)
|
|
pass # Usually not needed, PyInstaller sets up paths
|
|
|
|
try:
|
|
# Import the main entry point of wexpect's console reader logic
|
|
from wexpect import console_reader_base
|
|
|
|
# Call the main function, which will parse sys.argv and run the appropriate reader
|
|
# No arguments are passed to main() here, as it's expected to use sys.argv
|
|
console_reader_base.main()
|
|
|
|
sys.exit(0) # Explicitly exit with 0 on successful completion of main()
|
|
|
|
except SystemExit as se:
|
|
# If console_reader_base.main() calls sys.exit() itself (e.g., on argparse error)
|
|
sys.exit(se.code) # Propagate the exit code
|
|
except ImportError as ie:
|
|
err_msg = f"ImportError in wexpect_helper: {ie}. Check PyInstaller packaging for the helper."
|
|
log_helper_error(err_msg, ex_info=True)
|
|
print(
|
|
err_msg, file=sys.stderr
|
|
) # Also print to stderr for console visibility if any
|
|
sys.exit(2)
|
|
except Exception as e:
|
|
err_msg_main = f"Unhandled Exception in wexpect_console_entry.py: {e}"
|
|
log_helper_error(err_msg_main, ex_info=True)
|
|
print(err_msg_main, file=sys.stderr)
|
|
sys.exit(1)
|