-
-
Notifications
You must be signed in to change notification settings - Fork 7
Expand file tree
/
Copy pathcreate_release_zip.py
More file actions
143 lines (126 loc) · 4.57 KB
/
create_release_zip.py
File metadata and controls
143 lines (126 loc) · 4.57 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
"""Create ZIP file(s) for GitHub releases.
This script zips a PyInstaller *dist* folder (NOT the intermediate build output).
Supports multiple build flavors (e.g. core/full) by allowing callers to specify
the dist folder and output zip path.
"""
import zipfile
import os
import re
from pathlib import Path
import argparse
def _ensure_readme_first(dist_dir: Path, version: str, flavor: str | None = None) -> None:
"""Write a small readme into the dist folder to prevent common launch mistakes."""
readme_path = dist_dir / "README_FIRST.txt"
flavor_label = f" ({flavor})" if flavor else ""
text = (
f"Supervertaler v{version} (Windows){flavor_label}\n"
"\n"
"How to run\n"
"----------\n"
"1) Extract the ZIP to a folder (e.g. Desktop\\Supervertaler).\n"
"2) Run: Supervertaler\\Supervertaler.exe\n"
"\n"
"Optional: Add to Start Menu\n"
"---------------------------\n"
"Right-click create_start_menu_shortcut.ps1 and select 'Run with PowerShell'.\n"
"This creates a Start Menu shortcut so you can launch Supervertaler easily.\n"
"\n"
"Important\n"
"---------\n"
"- Do NOT run the EXE from inside the ZIP file.\n"
"- Do NOT move Supervertaler.exe away from the _internal folder.\n"
" The _internal folder contains python312.dll and other runtime files.\n"
)
# Only overwrite if missing or content changed.
if readme_path.exists():
try:
existing = readme_path.read_text(encoding="utf-8")
except OSError:
existing = None
if existing == text:
return
readme_path.write_text(text, encoding="utf-8")
def get_version():
"""Extract version from pyproject.toml (single source of truth)."""
try:
try:
import tomllib
except ImportError:
import tomli as tomllib
with open("pyproject.toml", "rb") as f:
data = tomllib.load(f)
return data["project"]["version"]
except Exception:
return "unknown"
def create_release_zip(
dist_dir: Path,
output_zip: Path,
*,
flavor: str | None = None,
version: str | None = None,
verbose: bool = False,
) -> None:
if version is None:
version = get_version()
if not dist_dir.exists():
raise FileNotFoundError(
f"Expected PyInstaller output folder not found: {dist_dir}. "
"Run PyInstaller first."
)
_ensure_readme_first(dist_dir, version, flavor=flavor)
print(f"Creating release ZIP: {output_zip}")
print(f"Version: {version}")
print(f"From directory: {dist_dir}")
# Remove existing ZIP if it exists
if output_zip.exists():
output_zip.unlink()
print(f"Removed existing ZIP")
with zipfile.ZipFile(output_zip, 'w', zipfile.ZIP_DEFLATED) as zipf:
added_files = 0
for root, dirs, files in os.walk(dist_dir):
for file in files:
file_path = Path(root) / file
arcname = file_path.relative_to(dist_dir.parent)
if verbose:
print(f"Adding: {arcname}")
zipf.write(file_path, arcname)
added_files += 1
size_mb = output_zip.stat().st_size / (1024 * 1024)
print(f"\nZIP created successfully!")
if not verbose:
print(f"Files added: {added_files}")
print(f"Size: {size_mb:.1f} MB")
print(f"Location: {output_zip.absolute()}")
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Create a versioned ZIP from a PyInstaller dist folder")
parser.add_argument(
"--dist-dir",
default="dist/Supervertaler",
help="PyInstaller output folder to zip (default: dist/Supervertaler)",
)
parser.add_argument(
"--output-zip",
default=None,
help="Output ZIP path (default: dist/Supervertaler-v<version>-Windows.zip)",
)
parser.add_argument(
"--flavor",
default=None,
help="Optional label written into README_FIRST.txt (e.g. core/full)",
)
parser.add_argument(
"--verbose",
action="store_true",
help="Print every file added to the ZIP (very noisy).",
)
args = parser.parse_args()
version = get_version()
dist_dir = Path(args.dist_dir)
output_zip = Path(args.output_zip) if args.output_zip else Path(f"dist/Supervertaler-v{version}-Windows.zip")
create_release_zip(
dist_dir=dist_dir,
output_zip=output_zip,
flavor=args.flavor,
version=version,
verbose=args.verbose,
)