#!/usr/bin/env python3 """Build the dependency-free ICT login zipapp and its checksum.""" from __future__ import annotations import argparse import hashlib import os import shutil import tempfile from pathlib import Path from zipapp import create_archive ROOT = Path(__file__).resolve().parents[1] DEFAULT_OUTPUT = ROOT / "dist" / "ictlogin.pyz" def _copy_source(source: Path, target: Path) -> None: target.mkdir(parents=True, exist_ok=True) shutil.copytree( source, target / "ictlogin", ignore=shutil.ignore_patterns("__pycache__", "*.pyc", "*.pyo", "*.egg-info"), ) def _sha256(path: Path) -> str: digest = hashlib.sha256() with path.open("rb") as handle: for chunk in iter(lambda: handle.read(1024 * 1024), b""): digest.update(chunk) return digest.hexdigest() def build(output: Path, checksum_path: Path) -> None: output.parent.mkdir(parents=True, exist_ok=True) staging_root = Path(tempfile.mkdtemp(prefix="ictlogin-build-")) temporary_output = output.with_name(output.name + ".tmp") try: _copy_source(ROOT / "src" / "ictlogin", staging_root) create_archive( staging_root, temporary_output, interpreter="/usr/bin/env python3", main="ictlogin.cli:main", compressed=True, ) os.chmod(temporary_output, 0o755) os.replace(temporary_output, output) digest = _sha256(output) checksum_path.parent.mkdir(parents=True, exist_ok=True) checksum_path.write_text(f"{digest} {output.name}\n", encoding="ascii") os.chmod(checksum_path, 0o644) finally: if temporary_output.exists(): temporary_output.unlink() shutil.rmtree(staging_root, ignore_errors=True) def main() -> None: parser = argparse.ArgumentParser(description=__doc__) parser.add_argument( "--output", type=Path, default=DEFAULT_OUTPUT, help="output .pyz path" ) parser.add_argument( "--checksum", type=Path, help="checksum path (defaults to OUTPUT.sha256)" ) args = parser.parse_args() checksum_path = args.checksum or Path(str(args.output) + ".sha256") build(args.output.resolve(), checksum_path.resolve()) print(f"built {args.output}") print(f"sha256 {checksum_path}") if __name__ == "__main__": main()