"""PyInstaller entry shim with aggressive startup diagnostics. Writes a log entry the moment this module is loaded (before any project imports). Logs to two locations: 1. Next to the exe (sys.executable directory) -- usually the user's Downloads folder; trivially findable. 2. %LOCALAPPDATA%/sephiria_inv/startup.log Either log existing tells us Python started. Neither existing means the PyInstaller bootloader died before Python ran (DLL/runtime issue). """ from __future__ import annotations import os import sys import traceback from datetime import datetime def _candidate_log_paths(): paths = [] # 1. Next to the exe (most discoverable for the user) try: exe_dir = os.path.dirname(os.path.abspath(sys.executable)) if exe_dir: paths.append(os.path.join(exe_dir, "sephiria_inv_startup.log")) except Exception: pass # 2. LOCALAPPDATA / home try: base = os.environ.get("LOCALAPPDATA") or os.path.expanduser("~") folder = os.path.join(base, "sephiria_inv") os.makedirs(folder, exist_ok=True) paths.append(os.path.join(folder, "startup.log")) except Exception: pass return paths def _write_log(msg: str) -> list: written = [] stamp = datetime.now().isoformat() for path in _candidate_log_paths(): try: with open(path, "a", encoding="utf-8") as fh: fh.write(f"\n=== {stamp} ===\n{msg}\n") written.append(path) except Exception: pass return written def _env_dump() -> str: lines = [ f"python: {sys.version}", f"executable: {sys.executable}", f"argv: {sys.argv}", f"frozen: {getattr(sys, 'frozen', False)}", f"_MEIPASS: {getattr(sys, '_MEIPASS', '')}", f"cwd: {os.getcwd()}", f"PATH head: {os.environ.get('PATH', '')[:200]}", f"LOCALAPPDATA: {os.environ.get('LOCALAPPDATA', '')}", ] return "\n".join(lines) # === MODULE-IMPORT BREADCRUMB === # This runs the moment Python loads the entry script. If this never appears # in either log, the PyInstaller bootloader failed before Python started. _BOOT_LOGS = _write_log("BOOT: run.py loaded\n" + _env_dump()) def _show_error(title: str, body: str) -> None: try: import tkinter as tk from tkinter import scrolledtext root = tk.Tk() root.title(title) root.geometry("780x460") txt = scrolledtext.ScrolledText(root, wrap="word") txt.pack(fill="both", expand=True) txt.insert("1.0", body) tk.Button(root, text="Close", command=root.destroy).pack(pady=4) root.mainloop() except Exception: pass def _main() -> int: try: from sephiria_inv.__main__ import main except BaseException: tb = traceback.format_exc() logs = _write_log("IMPORT FAIL\n" + tb + "\n--env--\n" + _env_dump()) _show_error( "sephiria_inv: import failed", f"Failed to import sephiria_inv.__main__\n\nLogs: {logs}\n\n{tb}", ) return 11 try: return int(main() or 0) except SystemExit: raise except BaseException: tb = traceback.format_exc() logs = _write_log("RUNTIME FAIL\n" + tb) _show_error( "sephiria_inv: runtime error", f"Crashed during main()\n\nLogs: {logs}\n\n{tb}", ) return 12 if __name__ == "__main__": raise SystemExit(_main())