Files
uploader/build.py
T

118 lines
4.8 KiB
Python

import shutil
import importlib.util
from pathlib import Path
import PyInstaller.__main__
import typer
from rich import print
app = typer.Typer()
@app.command()
def build(build: bool = True, copy: bool = True, test: bool = False, dest: str | None = None):
"""Windows-focused build script.
- `--test` creates a one-file test binary in `dist\test`.
- `--copy` (default) copies the artifact to the shared network path used previously.
"""
project_root = Path(__file__).resolve().parent
if build:
if test:
print("Building Windows test one-file bundle with PyInstaller")
# On Windows use ';' as add-data separator (src;dest)
# Use absolute path for the icon folder so PyInstaller can find it
icon_src = str(project_root / "icon")
add_data_args = ["--add-data", f"{icon_src};icon"]
# Try to include dicognito package data (release_notes.md) which
# PyInstaller may miss. This prevents runtime FileNotFoundError for
# dicognito/release_notes.md when the package expects the file at runtime.
try:
spec = importlib.util.find_spec("dicognito")
if spec and spec.submodule_search_locations:
dicognito_path = Path(spec.submodule_search_locations[0])
release_notes = dicognito_path / "release_notes.md"
if release_notes.exists():
# PyInstaller on Windows expects 'src;dest'
add_data_args += ["--add-data", f"{str(release_notes)};dicognito"]
else:
# include whole package folder if the single file wasn't found
add_data_args += ["--add-data", f"{str(dicognito_path)};dicognito"]
except Exception as e:
print(f"Warning: couldn't locate dicognito package: {e}")
# Try to include pythonnet runtime DLLs to avoid missing
# Python.Runtime.dll at runtime (used by pythonnet / webview).
add_binary_args = []
try:
spec_py = importlib.util.find_spec("pythonnet")
if spec_py and spec_py.submodule_search_locations:
pn_path = Path(spec_py.submodule_search_locations[0])
runtime_dir = pn_path / "runtime"
if runtime_dir.exists():
for f in runtime_dir.rglob("*.dll"):
# PyInstaller on Windows expects 'src;dest'
add_binary_args += ["--add-binary", f"{str(f)};pythonnet\\runtime"]
except Exception as e:
print(f"Warning: couldn't locate pythonnet runtime: {e}")
PyInstaller.__main__.run([
str(project_root / "nice.py"),
"--onefile",
"--name",
"Uploader_test",
"--distpath",
str(project_root / "dist" / "test"),
"--workpath",
str(project_root / "build" / "test"),
"--specpath",
str(project_root / "build" / "specs"),
] + add_data_args + add_binary_args + [
# add some common hidden imports that PyInstaller sometimes misses
"--hidden-import",
"bs4",
"--hidden-import",
"requests",
"--hidden-import",
"nicegui",
])
else:
print("Building using spec: nice_uploader.spec")
PyInstaller.__main__.run([str(project_root / "nice_uploader.spec")])
if copy:
# Windows-only default destination used previously in the repo
default_dest = Path(r"\\ict\Go\RCH\Shared\Dragon-Xray\rad-tools\uploader\Uploader")
artifact_dir = project_root / "dist" / ("test" if test else "")
if not artifact_dir.exists():
artifact_dir = project_root / "dist"
# Look for a matching artifact
candidates = list(artifact_dir.glob("Uploader*")) + list(artifact_dir.glob("*.exe"))
if not candidates:
print(f"No build artifact found in {artifact_dir}, skipping copy")
return
artifact = candidates[0]
dest_path = Path(dest) if dest else default_dest
dest_path.mkdir(parents=True, exist_ok=True)
if artifact.is_file():
target = dest_path / artifact.name
print(f"Copying {artifact} -> {target}")
shutil.copy2(artifact, target)
else:
target = dest_path / artifact.name
print(f"Copying directory {artifact} -> {target}")
if target.exists():
shutil.rmtree(target)
shutil.copytree(artifact, target)
if __name__ == "__main__":
app()