"""Create a portable source ZIP, excluding all user data and credentials.""" import stat import zipfile from pathlib import Path ROOT = Path(__file__).resolve().parent.parent FILES = ['run.py', 'README.md', '.gitignore', '.gitattributes', 'start-mac.command', 'start-windows.cmd'] DIRS = ['wechat_tool', 'scripts', 'examples', 'tests', 'docs'] def main(): out = ROOT / 'dist' / 'zhiwei-wechat-analysis-v0.4.zip' out.parent.mkdir(exist_ok=True) paths = [ROOT / p for p in FILES] for directory in DIRS: paths.extend(p for p in (ROOT / directory).rglob('*') if p.is_file() and '__pycache__' not in p.parts and p.suffix != '.pyc') with zipfile.ZipFile(out, 'w', compression=zipfile.ZIP_DEFLATED) as archive: for path in sorted(paths): name = 'zhiwei-wechat-analysis/' + path.relative_to(ROOT).as_posix() info = zipfile.ZipInfo(name) info.create_system = 3 mode = 0o755 if path.name == 'start-mac.command' else 0o644 info.external_attr = (stat.S_IFREG | mode) << 16 info.compress_type = zipfile.ZIP_DEFLATED # Match .gitattributes even when packaging without a Git checkout. # All files selected above are text; binary artifacts are excluded. data = path.read_bytes().replace(b'\r\n', b'\n').replace(b'\r', b'\n') if path.suffix in ('.cmd', '.bat'): data = data.replace(b'\n', b'\r\n') archive.writestr(info, data) print(out) if __name__ == '__main__': main()