| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115 |
- #!/usr/bin/env python3
- # -*- coding: utf-8 -*-
- """Install project Python deps into embedded python/py (site-packages). No virtual environment."""
- import os
- import subprocess
- import sys
- from pathlib import Path
- PIP_INDEX_URL = os.environ.get("PIP_INDEX_URL", "https://pypi.tuna.tsinghua.edu.cn/simple")
- PIP_TRUSTED_HOST = "pypi.tuna.tsinghua.edu.cn"
- PIP_INDEX_ARGS = f"-i {PIP_INDEX_URL} --trusted-host {PIP_TRUSTED_HOST}"
- SCRIPT_DIR = Path(__file__).parent.absolute()
- PROJECT_ROOT = SCRIPT_DIR.parent.absolute()
- PY_EMBED = SCRIPT_DIR / "py" / "python.exe"
- if not PY_EMBED.exists():
- PY_EMBED = SCRIPT_DIR / "py" / "python"
- ENVIRONMENT_FILE = SCRIPT_DIR / "environment.txt"
- REQUIREMENTS_FILE = PROJECT_ROOT / "requirements.txt"
- def run_pip(args: str) -> subprocess.CompletedProcess:
- cmd = f'"{PY_EMBED}" -m pip {args}'
- return subprocess.run(cmd, shell=True, capture_output=True, text=True, encoding="utf-8")
- def installed_names() -> set:
- out = set()
- sp = SCRIPT_DIR / "py" / "Lib" / "site-packages"
- if not sp.exists():
- return out
- for item in sp.iterdir():
- if not item.is_dir():
- continue
- name = item.name
- if name.endswith(".dist-info"):
- base = name.replace(".dist-info", "").rsplit("-", 1)[0]
- out.add(base.lower().replace("_", "-"))
- elif name.endswith(".egg-info"):
- base = name.replace(".egg-info", "").rsplit("-", 1)[0]
- out.add(base.lower().replace("_", "-"))
- elif (item / "__init__.py").exists() or any(item.glob("*.py")):
- out.add(name.lower())
- out.add(name.lower().replace("_", "-"))
- if "cv2" in out:
- out.add("opencv-python")
- return out
- def pkg_key(line: str) -> str:
- line = line.strip()
- if not line or line.startswith("#"):
- return ""
- for sep in ("==", ">=", "<=", "~=", ">", "<"):
- if sep in line:
- line = line.split(sep)[0]
- break
- return line.strip().lower()
- def main() -> None:
- if not PY_EMBED.exists():
- print(f"[X] Embedded Python not found: {PY_EMBED}")
- sys.exit(1)
- if run_pip("--version").returncode != 0:
- print("[X] pip not usable. Run enviroment-check.ps1 (copies from python/backup/site-packages first, then get-pip.py if needed).")
- sys.exit(1)
- if REQUIREMENTS_FILE.exists():
- source = REQUIREMENTS_FILE
- elif ENVIRONMENT_FILE.exists():
- source = ENVIRONMENT_FILE
- else:
- fr = run_pip("freeze")
- if fr.returncode == 0 and fr.stdout:
- ENVIRONMENT_FILE.write_text(fr.stdout, encoding="utf-8", newline="\n")
- print("[OK] Created environment.txt from pip freeze")
- sys.exit(0)
- lines = [ln.strip() for ln in source.read_text(encoding="utf-8").splitlines() if ln.strip() and not ln.strip().startswith("#")]
- if not lines:
- print("[OK] No packages listed")
- sys.exit(0)
- have = installed_names()
- missing = []
- for ln in lines:
- k = pkg_key(ln)
- if not k:
- continue
- if k in have or k.replace("-", "_") in have:
- continue
- missing.append(ln)
- if missing:
- print(f"Installing {len(missing)} package(s) into python/py...")
- for pkg in missing:
- print(f" pip install {pkg}")
- ins = run_pip(f"install {PIP_INDEX_ARGS} --no-warn-script-location {pkg}")
- if ins.returncode != 0:
- print(ins.stderr or ins.stdout or "")
- sys.exit(1)
- fr = run_pip("freeze")
- if fr.returncode != 0:
- sys.exit(1)
- ENVIRONMENT_FILE.write_text(fr.stdout, encoding="utf-8", newline="\n")
- print(f"[OK] Synced {ENVIRONMENT_FILE}")
- sys.exit(0)
- if __name__ == "__main__":
- main()
|