feat: Add simplified build script for creating executables
Added build.py to simplify the process of building standalone executables with PyInstaller. Also added .gitignore to exclude build artifacts. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
37
.gitignore
vendored
Normal file
37
.gitignore
vendored
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
# Python
|
||||||
|
__pycache__/
|
||||||
|
*.py[cod]
|
||||||
|
*$py.class
|
||||||
|
*.so
|
||||||
|
.Python
|
||||||
|
*.egg-info/
|
||||||
|
dist/
|
||||||
|
build/
|
||||||
|
*.egg
|
||||||
|
.pytest_cache/
|
||||||
|
|
||||||
|
# PyInstaller
|
||||||
|
*.spec
|
||||||
|
|
||||||
|
# Virtual Environment
|
||||||
|
venv/
|
||||||
|
env/
|
||||||
|
ENV/
|
||||||
|
|
||||||
|
# IDE
|
||||||
|
.vscode/
|
||||||
|
.idea/
|
||||||
|
*.swp
|
||||||
|
*.swo
|
||||||
|
*~
|
||||||
|
|
||||||
|
# OS
|
||||||
|
.DS_Store
|
||||||
|
Thumbs.db
|
||||||
|
|
||||||
|
# Credentials
|
||||||
|
credentials.json
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Claude
|
||||||
|
.claude/settings.local.json
|
||||||
129
build.py
Normal file
129
build.py
Normal file
@@ -0,0 +1,129 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
Simple build wrapper for EBoek.info Scraper
|
||||||
|
Creates a standalone executable using PyInstaller
|
||||||
|
"""
|
||||||
|
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import subprocess
|
||||||
|
import shutil
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main build process."""
|
||||||
|
print("=" * 50)
|
||||||
|
print("EBoek.info Scraper - Executable Builder")
|
||||||
|
print("=" * 50)
|
||||||
|
print()
|
||||||
|
|
||||||
|
project_root = Path(__file__).parent
|
||||||
|
os.chdir(project_root)
|
||||||
|
print(f"Working from: {project_root}")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Check if PyInstaller is installed
|
||||||
|
try:
|
||||||
|
import PyInstaller
|
||||||
|
print(f"PyInstaller {PyInstaller.__version__} found")
|
||||||
|
except ImportError:
|
||||||
|
print("Installing PyInstaller...")
|
||||||
|
subprocess.run([sys.executable, "-m", "pip", "install", "pyinstaller"], check=True)
|
||||||
|
|
||||||
|
# Clean previous builds
|
||||||
|
print()
|
||||||
|
for directory in ["dist", "build"]:
|
||||||
|
if Path(directory).exists():
|
||||||
|
shutil.rmtree(directory)
|
||||||
|
print(f"Cleaned {directory}/")
|
||||||
|
|
||||||
|
# Determine platform-specific settings
|
||||||
|
is_windows = sys.platform.startswith('win')
|
||||||
|
app_name = "EBoek_Scraper"
|
||||||
|
|
||||||
|
# Build command
|
||||||
|
build_cmd = [
|
||||||
|
sys.executable, "-m", "PyInstaller",
|
||||||
|
"--onefile",
|
||||||
|
"--windowed",
|
||||||
|
"--name", app_name,
|
||||||
|
# Hidden imports for PyQt5
|
||||||
|
"--hidden-import", "PyQt5.QtCore",
|
||||||
|
"--hidden-import", "PyQt5.QtGui",
|
||||||
|
"--hidden-import", "PyQt5.QtWidgets",
|
||||||
|
# Hidden imports for Selenium
|
||||||
|
"--hidden-import", "selenium",
|
||||||
|
"--hidden-import", "selenium.webdriver",
|
||||||
|
"--hidden-import", "selenium.webdriver.chrome",
|
||||||
|
"--hidden-import", "selenium.webdriver.chrome.options",
|
||||||
|
"--hidden-import", "selenium.webdriver.common.by",
|
||||||
|
# Hidden imports for our modules
|
||||||
|
"--hidden-import", "core.scraper",
|
||||||
|
"--hidden-import", "core.scraper_thread",
|
||||||
|
"--hidden-import", "core.credentials",
|
||||||
|
"--hidden-import", "gui.main_window",
|
||||||
|
"--hidden-import", "gui.login_dialog",
|
||||||
|
"--hidden-import", "gui.progress_dialog",
|
||||||
|
"--hidden-import", "utils.validators",
|
||||||
|
# Bookys scraper modules
|
||||||
|
"--hidden-import", "core.bookys_scraper",
|
||||||
|
"--hidden-import", "core.bookys_thread",
|
||||||
|
"--hidden-import", "gui.bookys_window",
|
||||||
|
"--hidden-import", "gui.startup_dialog",
|
||||||
|
# Exclude unnecessary modules
|
||||||
|
"--exclude-module", "tkinter",
|
||||||
|
"--exclude-module", "matplotlib",
|
||||||
|
"--exclude-module", "numpy",
|
||||||
|
"--exclude-module", "pandas",
|
||||||
|
# Main script
|
||||||
|
"gui_main.py"
|
||||||
|
]
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("Building executable...")
|
||||||
|
print("This may take a few minutes...")
|
||||||
|
print()
|
||||||
|
|
||||||
|
# Run PyInstaller
|
||||||
|
result = subprocess.run(build_cmd)
|
||||||
|
|
||||||
|
if result.returncode != 0:
|
||||||
|
print("Build failed!")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
print("Build completed successfully!")
|
||||||
|
|
||||||
|
# Check if executable was created
|
||||||
|
exe_name = "EBoek_Scraper.exe" if is_windows else "EBoek_Scraper"
|
||||||
|
exe_path = Path("dist") / exe_name
|
||||||
|
|
||||||
|
if not exe_path.exists():
|
||||||
|
print(f"Error: Executable not found at {exe_path}")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
# Display results
|
||||||
|
file_size = exe_path.stat().st_size / (1024 * 1024) # MB
|
||||||
|
print()
|
||||||
|
print("=" * 50)
|
||||||
|
print("BUILD SUCCESSFUL!")
|
||||||
|
print("=" * 50)
|
||||||
|
print(f"Executable location: {exe_path}")
|
||||||
|
print(f"File size: {file_size:.1f} MB")
|
||||||
|
print()
|
||||||
|
|
||||||
|
if is_windows:
|
||||||
|
print("Windows Instructions:")
|
||||||
|
print(f" Run: {exe_path}")
|
||||||
|
print(" Windows may show security warning on first run")
|
||||||
|
print(" Click 'More Info' -> 'Run Anyway' if prompted")
|
||||||
|
else:
|
||||||
|
print("macOS/Linux Instructions:")
|
||||||
|
print(f" Run: ./{exe_path}")
|
||||||
|
|
||||||
|
print()
|
||||||
|
print("Ready for distribution!")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
Reference in New Issue
Block a user