-
Notifications
You must be signed in to change notification settings - Fork 8
Expand file tree
/
Copy pathinstall.py
More file actions
146 lines (108 loc) · 4.84 KB
/
Copy pathinstall.py
File metadata and controls
146 lines (108 loc) · 4.84 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
#!/usr/bin/env python3
"""memect-ppx installer — works on Windows / macOS / Linux"""
import os
import platform
import subprocess
import sys
from pathlib import Path
MIN_PYTHON = (3, 12)
UV_INSTALL_URL = "https://astral.sh/uv/install.sh"
UV_INSTALL_URL_WIN = "https://astral.sh/uv/install.ps1"
def info(msg: str) -> None:
print(f"[ppx] {msg}")
def error(msg: str) -> None:
print(f"[ppx] ERROR: {msg}", file=sys.stderr)
def run(cmd: list[str], **kwargs) -> subprocess.CompletedProcess:
info(f"$ {' '.join(cmd)}")
return subprocess.run(cmd, check=True, **kwargs)
# ── 1. Python version check ───────────────────────────────────────────────────
def check_python() -> None:
if sys.version_info < MIN_PYTHON:
error(f"Python {MIN_PYTHON[0]}.{MIN_PYTHON[1]}+ required, got {sys.version}")
sys.exit(1)
info(f"Python {sys.version.split()[0]} OK")
# ── 2. uv availability ────────────────────────────────────────────────────────
def ensure_uv() -> str:
"""Return path to uv, installing it if missing."""
from shutil import which
uv = which("uv")
if uv:
info(f"uv found: {uv}")
return uv
info("uv not found — installing...")
system = platform.system()
if system == "Windows":
run([
"powershell", "-ExecutionPolicy", "Bypass",
"-Command",
f"irm {UV_INSTALL_URL_WIN} | iex",
])
# After install, uv lands in %USERPROFILE%\.local\bin
candidate = Path.home() / ".local" / "bin" / "uv.exe"
else:
run(["sh", "-c", f"curl -LsSf {UV_INSTALL_URL} | sh"])
candidate = Path.home() / ".local" / "bin" / "uv"
if candidate.exists():
return str(candidate)
# Fallback: re-check PATH (installer may have modified it)
uv = which("uv")
if uv:
return uv
error("uv installation failed. Install manually: https://docs.astral.sh/uv/")
sys.exit(1)
# ── 3. GPU detection ──────────────────────────────────────────────────────────
def detect_gpu() -> bool:
"""Best-effort NVIDIA GPU detection."""
from shutil import which
if which("nvidia-smi"):
try:
r = subprocess.run(["nvidia-smi"], capture_output=True, timeout=5)
return r.returncode == 0
except Exception:
pass
return False
def ask_gpu(auto: bool) -> bool:
if auto:
has_gpu = detect_gpu()
info(f"GPU detected: {has_gpu}")
return has_gpu
ans = input("[ppx] Install GPU (CUDA) support? [y/N] ").strip().lower()
return ans in ("y", "yes")
# ── 4. Install ────────────────────────────────────────────────────────────────
def install(uv: str, gpu: bool) -> None:
pkg = "memect-ppx[cuda]" if gpu else "memect-ppx"
info(f"Installing {pkg} ...")
run([uv, "pip", "install", pkg])
onnx = "onnxruntime-gpu" if gpu else "onnxruntime"
info(f"Installing {onnx} ...")
run([uv, "pip", "install", onnx, "--no-config"])
info("Installing opencv ...")
run([uv, "pip", "install", "opencv-contrib-python", "--no-config"])
# ── 5. Verify ─────────────────────────────────────────────────────────────────
def verify(uv: str) -> None:
try:
run([uv, "run", "ppx", "--help"], capture_output=True)
info("Installation verified — run `ppx --help` to get started.")
except subprocess.CalledProcessError:
error("Verification failed. Try: ppx --help")
# ── main ──────────────────────────────────────────────────────────────────────
def main() -> None:
import argparse
parser = argparse.ArgumentParser(description="Install memect-ppx")
parser.add_argument("--gpu", action="store_true", help="Force GPU install")
parser.add_argument("--cpu", action="store_true", help="Force CPU install")
parser.add_argument("--auto", action="store_true", default=True,
help="Auto-detect GPU (default)")
args = parser.parse_args()
check_python()
uv = ensure_uv()
if args.gpu:
gpu = True
elif args.cpu:
gpu = False
else:
gpu = ask_gpu(auto=args.auto)
install(uv, gpu)
verify(uv)
if __name__ == "__main__":
main()