Release ZipBundler 1.0.0 with guided recompression and complete Windows build
This commit is contained in:
86
verify_exe.py
Normal file
86
verify_exe.py
Normal file
@@ -0,0 +1,86 @@
|
||||
"""Smoke-test the complete frozen package without external Python/Ghostscript on PATH."""
|
||||
|
||||
import io
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
import tempfile
|
||||
import zipfile
|
||||
|
||||
import fitz
|
||||
from PIL import Image
|
||||
from PyInstaller.archive.readers import CArchiveReader
|
||||
|
||||
|
||||
def main():
|
||||
executable = Path(__file__).parent / "dist" / "ZipBundler.exe"
|
||||
archive = CArchiveReader(str(executable))
|
||||
names = [name.replace("\\", "/").lower() for name in archive.toc]
|
||||
for fragment in ("ghostscript/bin/gswin64c.exe", "ghostscript/bin/gsdll64.dll",
|
||||
"python314.dll", "pythoncom314.dll", "pywintypes314.dll",
|
||||
"customtkinter/assets/themes/blue.json", "assets/splash.png"):
|
||||
if not any(fragment in name for name in names):
|
||||
raise AssertionError(f"Missing bundled component: {fragment}")
|
||||
print("Embedded components: OK")
|
||||
|
||||
with tempfile.TemporaryDirectory(prefix="zipbundler-exe-test-") as directory:
|
||||
root = Path(directory)
|
||||
source = root / "source"
|
||||
source.mkdir()
|
||||
output = root / "output"
|
||||
noise = Image.effect_noise((1800, 2400), 80)
|
||||
image_bytes = io.BytesIO()
|
||||
noise.save(image_bytes, format="PNG")
|
||||
pdf = source / "native-scan.pdf"
|
||||
with fitz.open() as document:
|
||||
page = document.new_page(width=600, height=800)
|
||||
page.insert_image(page.rect, stream=image_bytes.getvalue())
|
||||
page.insert_text((20, 30), ("Searchable native text for bundled engine verification.\n" * 20), fontsize=8)
|
||||
document.save(pdf)
|
||||
noise.save(source / "photo.jpg", quality=98)
|
||||
|
||||
environment = os.environ.copy()
|
||||
windows = Path(environment.get("SystemRoot", r"C:\Windows"))
|
||||
environment["PATH"] = os.pathsep.join((str(windows / "System32"), str(windows)))
|
||||
for key in ("PYTHONPATH", "PYTHONHOME", "GS_LIB", "GS_FONTPATH"):
|
||||
environment.pop(key, None)
|
||||
startup = subprocess.STARTUPINFO()
|
||||
startup.dwFlags |= subprocess.STARTF_USESHOWWINDOW
|
||||
startup.wShowWindow = 0
|
||||
completed = subprocess.run(
|
||||
[str(executable), str(source), "--output", str(output), "--size-mb", "0.6"],
|
||||
cwd=root, env=environment, startupinfo=startup, timeout=60,
|
||||
)
|
||||
if completed.returncode:
|
||||
raise AssertionError(f"EXE exited with {completed.returncode}")
|
||||
archives = sorted(output.glob("pacchetto_*.zip"))
|
||||
if not archives:
|
||||
raise AssertionError("No ZIP packages were produced")
|
||||
found_pdf = found_image = False
|
||||
for path in archives:
|
||||
if path.stat().st_size > int(0.6 * 1024 * 1024):
|
||||
raise AssertionError(f"Oversized archive: {path}")
|
||||
with zipfile.ZipFile(path) as zipped:
|
||||
if zipped.testzip() is not None:
|
||||
raise AssertionError("Corrupt ZIP member")
|
||||
for name in zipped.namelist():
|
||||
data = zipped.read(name)
|
||||
if name.endswith(".pdf"):
|
||||
with fitz.open(stream=data, filetype="pdf") as document:
|
||||
if "Searchable native text" not in document[0].get_text():
|
||||
raise AssertionError("Native PDF text was lost")
|
||||
found_pdf = True
|
||||
elif name.endswith(".jpg"):
|
||||
with Image.open(io.BytesIO(data)) as image:
|
||||
image.load()
|
||||
if image.format != "JPEG":
|
||||
raise AssertionError("Image format changed")
|
||||
found_image = True
|
||||
print(f"{path.name}: {path.stat().st_size} bytes, OK")
|
||||
if not (found_pdf and found_image):
|
||||
raise AssertionError("Missing optimized PDF or JPEG")
|
||||
print("Frozen EXE: PDF with searchable text and JPEG compression OK; external tools absent from PATH")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user