"""把 export_runtime.py 产物打包成带版本号的 zip 分发包。 产物:dist/--.zip zip 内部扁平结构:解压到 plugins// 即得完整目录。 用法: python build_pyd.py --clean python tools/export_runtime.py python tools/pack_zip.py """ from __future__ import annotations import json import platform import re import sys import zipfile from pathlib import Path ROOT = Path(__file__).resolve().parent.parent PLUGINS_DIR = ROOT / "plugins" DIST_DIR = ROOT / "dist" def _read_plugin_meta() -> tuple[str, str]: """从 mil/__init__.py 源码提取插件名与版本号(绕过 PySide6 import)。""" src = (ROOT / "mil" / "__init__.py").read_text(encoding="utf-8") name = re.search(r'NMAE\s*=\s*"([^"]+)"', src).group(1) major = re.search(r"__MAJOR_VER:\s*int\s*=\s*(\d+)", src).group(1) minor = re.search(r"__MINOR_VER:\s*int\s*=\s*(\d+)", src).group(1) micro = re.search(r"__MICRO_VER:\s*int\s*=\s*(\d+)", src).group(1) return name, f"{major}.{minor}.{micro}" def _python_tag() -> str: impl = "cp" + str(sys.version_info.major) + str(sys.version_info.minor) plat = "win_amd64" if platform.system() == "Windows" else platform.machine() return f"{impl}-{plat}" def main() -> None: if not PLUGINS_DIR.exists() or not any(PLUGINS_DIR.iterdir()): print("[pack] ERROR: plugins/ 不存在或为空,请先运行 export_runtime.py", file=sys.stderr) sys.exit(1) name, version = _read_plugin_meta() manifest = json.loads((PLUGINS_DIR / "manifest.json").read_text(encoding="utf-8")) # 主业务包名由 export_runtime 写入 manifest,固定为 mil tool_name = manifest["tool_name"] zip_name = f"{tool_name}-{version}-{_python_tag()}.zip" DIST_DIR.mkdir(parents=True, exist_ok=True) zip_path = DIST_DIR / zip_name with zipfile.ZipFile(zip_path, "w", compression=zipfile.ZIP_DEFLATED) as zf: for f in PLUGINS_DIR.rglob("*"): if f.is_file(): # 扁平结构:arcname 相对 plugins/,解压到子目录即得完整布局 arcname = f.relative_to(PLUGINS_DIR).as_posix() zf.write(f, arcname) file_count = len(zipfile.ZipFile(zip_path).namelist()) print(f"[pack] 打包完成: {zip_path}") print(f"[pack] 插件: {name} v{version}") print(f"[pack] 文件数: {file_count}") print(f"[pack] 下一步: 把 zip 复制到远程 Y:/SE/xufeifei/plugins/") if __name__ == "__main__": main()