feat: Introduce initial application structure, SQL database tools, and license management.
This commit is contained in:
108
ProBackup.spec
Normal file
108
ProBackup.spec
Normal file
@@ -0,0 +1,108 @@
|
||||
# -*- mode: python ; coding: utf-8 -*-
|
||||
import os
|
||||
import sys
|
||||
import PyQt5
|
||||
|
||||
# --- MONKEYPATCH PyInstaller QT Detection (Force correct path) ---
|
||||
try:
|
||||
from PyInstaller.utils.hooks import qt
|
||||
|
||||
# 1. Find the real plugin path
|
||||
qt5_dir = os.path.dirname(PyQt5.__file__)
|
||||
possible_plugin_paths = [
|
||||
os.path.join(qt5_dir, 'Qt', 'plugins'),
|
||||
os.path.join(qt5_dir, 'plugins'),
|
||||
]
|
||||
real_plugin_path = None
|
||||
for p in possible_plugin_paths:
|
||||
if os.path.exists(p):
|
||||
real_plugin_path = p
|
||||
break
|
||||
|
||||
# 2. Override the failing function
|
||||
if real_plugin_path:
|
||||
print(">>> FORCING QT PLUGINS PATH: {}".format(real_plugin_path))
|
||||
|
||||
# Save original just in case, though we ignore it
|
||||
original_qt_plugins_dir = qt.qt_plugins_dir
|
||||
|
||||
def new_qt_plugins_dir(namespace=None):
|
||||
return real_plugin_path
|
||||
|
||||
qt.qt_plugins_dir = new_qt_plugins_dir
|
||||
|
||||
# Also set env var as backup
|
||||
os.environ['QT_PLUGIN_PATH'] = real_plugin_path
|
||||
else:
|
||||
print(">>> ERROR: Could not find PyQt5 plugins to monkeypatch!")
|
||||
|
||||
except ImportError:
|
||||
print(">>> WARNING: Could not import PyInstaller.utils.hooks.qt for patching")
|
||||
except Exception as e:
|
||||
print(">>> WARNING: Monkeypatch failed: {}".format(e))
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
block_cipher = None
|
||||
|
||||
a = Analysis(
|
||||
['main.py'],
|
||||
pathex=[],
|
||||
binaries=[],
|
||||
# Bundle tools to sql_tools subfolder
|
||||
datas=[
|
||||
('icon.png', '.'),
|
||||
('sql_tools/pg_dump.exe', 'sql_tools'),
|
||||
('sql_tools/mysqldump.exe', 'sql_tools')
|
||||
],
|
||||
hiddenimports=['PyQt5', 'pymysql', 'psycopg2', 'apscheduler'],
|
||||
hookspath=[],
|
||||
runtime_hooks=['rthook_qt_fix.py'],
|
||||
# Context7 Optimization: Exclude unused modules to reduce size
|
||||
excludes=['FixTk', 'tcl', 'tk', '_tkinter', 'tkinter', 'Tkinter', 'matplotlib', 'numpy', 'scipy', 'pandas', 'PIL.ImageTk'],
|
||||
win_no_prefer_redirects=False,
|
||||
cipher=block_cipher,
|
||||
)
|
||||
|
||||
# --- MANUAL BUNDLING OF PLATFORMS (Fix "platform plugin windows not found") ---
|
||||
# Re-locate the plugins directory (redundant but safe)
|
||||
qt5_dir = os.path.dirname(PyQt5.__file__)
|
||||
plugin_sources = [
|
||||
os.path.join(qt5_dir, 'Qt', 'plugins', 'platforms'),
|
||||
os.path.join(qt5_dir, 'plugins', 'platforms'),
|
||||
]
|
||||
found_plugin = None
|
||||
for p in plugin_sources:
|
||||
if os.path.exists(p):
|
||||
found_plugin = p
|
||||
break
|
||||
|
||||
if found_plugin:
|
||||
print(">>> MANUALLY BUNDLING PLATFORMS FROM: {}".format(found_plugin))
|
||||
a.datas += Tree(found_plugin, prefix='platforms') # Bundle as root/platforms/
|
||||
|
||||
# Also bundle as root/qt/plugins/platforms just to match common fallback paths
|
||||
# a.datas += Tree(found_plugin, prefix='qt/plugins/platforms')
|
||||
else:
|
||||
print(">>> ERROR: Could not find 'platforms' folder for bundling!")
|
||||
# -----------------------------------------------------------------------------
|
||||
|
||||
pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher)
|
||||
|
||||
# ONEFILE Mode: Everything bundled into single EXE
|
||||
exe = EXE(
|
||||
pyz,
|
||||
a.scripts,
|
||||
a.binaries,
|
||||
a.zipfiles,
|
||||
a.datas,
|
||||
[],
|
||||
name='ProBackup',
|
||||
debug=False,
|
||||
bootloader_ignore_signals=False,
|
||||
strip=False,
|
||||
upx=False,
|
||||
upx_exclude=[],
|
||||
runtime_tmpdir=None,
|
||||
console=False,
|
||||
icon='icon.ico',
|
||||
)
|
||||
Reference in New Issue
Block a user