new hyrdusupdate
This commit is contained in:
@@ -692,12 +692,146 @@ IMPORT_NAME_OVERRIDES = {
|
||||
}
|
||||
|
||||
|
||||
def normalize_python_command(python_cmd: Optional[Sequence[str] | str]) -> list[str]:
|
||||
if python_cmd is None:
|
||||
return [sys.executable]
|
||||
if isinstance(python_cmd, (str, Path)):
|
||||
return [str(python_cmd)]
|
||||
return [str(part) for part in python_cmd]
|
||||
|
||||
|
||||
def get_python_version_info(python_cmd: Optional[Sequence[str] | str] = None) -> Optional[tuple[int, int, int]]:
|
||||
cmd = normalize_python_command(python_cmd)
|
||||
try:
|
||||
result = subprocess.run(
|
||||
cmd + [
|
||||
"-c",
|
||||
"import sys; print('.'.join(str(part) for part in sys.version_info[:3]))",
|
||||
],
|
||||
stdout=subprocess.PIPE,
|
||||
stderr=subprocess.DEVNULL,
|
||||
text=True,
|
||||
check=True,
|
||||
)
|
||||
version_text = (result.stdout or "").strip()
|
||||
major, minor, micro = version_text.split(".", 2)
|
||||
return (int(major), int(minor), int(micro))
|
||||
except Exception:
|
||||
return None
|
||||
|
||||
|
||||
def is_hydrus_repo(repo_root: Path) -> bool:
|
||||
return (repo_root / "setup_venv.py").exists() and (repo_root / "hydrus_client.py").exists()
|
||||
|
||||
|
||||
def select_hydrus_python_command() -> tuple[list[str], tuple[int, int, int]]:
|
||||
candidates: list[list[str]] = []
|
||||
|
||||
if os.name == "nt" and shutil.which("py"):
|
||||
for version in ("3.12", "3.11", "3.10", "3.13", "3.14"):
|
||||
candidates.append(["py", f"-{version}"])
|
||||
|
||||
candidates.append([sys.executable])
|
||||
|
||||
for name in ("python3.12", "python3.11", "python3.10", "python3", "python"):
|
||||
resolved = shutil.which(name)
|
||||
if resolved:
|
||||
candidates.append([resolved])
|
||||
|
||||
seen: set[tuple[str, ...]] = set()
|
||||
best_fallback: Optional[tuple[list[str], tuple[int, int, int]]] = None
|
||||
|
||||
for candidate in candidates:
|
||||
normalized = tuple(candidate)
|
||||
if normalized in seen:
|
||||
continue
|
||||
seen.add(normalized)
|
||||
|
||||
version = get_python_version_info(candidate)
|
||||
if version is None or version < (3, 10):
|
||||
continue
|
||||
|
||||
if version < (3, 13):
|
||||
return candidate, version
|
||||
|
||||
if best_fallback is None or version < best_fallback[1]:
|
||||
best_fallback = (candidate, version)
|
||||
|
||||
if best_fallback is not None:
|
||||
return best_fallback
|
||||
|
||||
version = get_python_version_info([sys.executable])
|
||||
if version is None:
|
||||
raise RuntimeError("Could not determine a usable Python interpreter for Hydrus")
|
||||
return [sys.executable], version
|
||||
|
||||
|
||||
def build_hydrus_install_targets(
|
||||
req_path: Path,
|
||||
repo_root: Path,
|
||||
python_version: tuple[int, int, int],
|
||||
) -> list[str]:
|
||||
if not is_hydrus_repo(repo_root) or python_version < (3, 13):
|
||||
return ["-r", str(req_path)]
|
||||
|
||||
overrides = {
|
||||
"pyside6": "PySide6==6.10.1",
|
||||
"qtpy": "QtPy==2.4.3",
|
||||
"opencv-python-headless": "opencv-python-headless==4.13.0.90",
|
||||
"numpy": "numpy==2.4.1",
|
||||
}
|
||||
targets: list[str] = []
|
||||
seen_packages: set[str] = set()
|
||||
|
||||
for raw_line in req_path.read_text(encoding="utf-8").splitlines():
|
||||
line = raw_line.strip()
|
||||
if not line or line.startswith("#"):
|
||||
continue
|
||||
|
||||
package_name = re.split(r"[<>=!~\[]", line, maxsplit=1)[0].strip().lower()
|
||||
if package_name in overrides:
|
||||
line = overrides[package_name]
|
||||
|
||||
targets.append(line)
|
||||
seen_packages.add(package_name)
|
||||
|
||||
if os.name == "nt" and "pywin32" not in seen_packages:
|
||||
targets.append("pywin32")
|
||||
|
||||
logging.info(
|
||||
"Using Hydrus compatibility dependency set for Python %s.%s.%s",
|
||||
python_version[0],
|
||||
python_version[1],
|
||||
python_version[2],
|
||||
)
|
||||
return targets
|
||||
|
||||
|
||||
def ensure_repo_venv(
|
||||
repo_root: Path,
|
||||
venv_name: str = ".venv",
|
||||
recreate: bool = False,
|
||||
purpose: Optional[str] = None,
|
||||
) -> Path:
|
||||
python_cmd: list[str]
|
||||
python_version: Optional[tuple[int, int, int]]
|
||||
if is_hydrus_repo(repo_root):
|
||||
python_cmd, python_version = select_hydrus_python_command()
|
||||
if python_version is not None:
|
||||
logging.info(
|
||||
"Using Python %s.%s.%s for Hydrus venv creation via %s",
|
||||
python_version[0],
|
||||
python_version[1],
|
||||
python_version[2],
|
||||
" ".join(python_cmd),
|
||||
)
|
||||
if python_version >= (3, 13):
|
||||
logging.info(
|
||||
"Hydrus is running on a newer Python; installer will apply compatibility package overrides."
|
||||
)
|
||||
else:
|
||||
python_cmd = [sys.executable]
|
||||
|
||||
venv_dir = repo_root / str(venv_name)
|
||||
if venv_dir.exists():
|
||||
if recreate:
|
||||
@@ -711,7 +845,7 @@ def ensure_repo_venv(
|
||||
logging.info("Creating venv at %s for %s", venv_dir, purpose)
|
||||
else:
|
||||
logging.info("Creating venv at %s", venv_dir)
|
||||
subprocess.run([sys.executable, "-m", "venv", str(venv_dir)], check=True)
|
||||
subprocess.run(python_cmd + ["-m", "venv", str(venv_dir)], check=True)
|
||||
|
||||
venv_py = get_python_in_venv(venv_dir)
|
||||
if not venv_py:
|
||||
@@ -727,6 +861,10 @@ def install_requirements_into_venv(
|
||||
req_path: Path,
|
||||
reinstall: bool = False,
|
||||
) -> None:
|
||||
python_version = get_python_version_info([str(venv_py)])
|
||||
if python_version is None:
|
||||
raise RuntimeError(f"Could not determine python version for {venv_py}")
|
||||
|
||||
logging.info(
|
||||
"Installing dependencies from %s into venv (reinstall=%s)",
|
||||
req_path,
|
||||
@@ -751,10 +889,11 @@ def install_requirements_into_venv(
|
||||
"pip",
|
||||
"install",
|
||||
"--disable-pip-version-check",
|
||||
"--prefer-binary",
|
||||
]
|
||||
if reinstall:
|
||||
cmd.extend(["--upgrade", "--force-reinstall"])
|
||||
cmd.extend(["-r", str(req_path)])
|
||||
cmd.extend(build_hydrus_install_targets(req_path, repo_root, python_version))
|
||||
subprocess.run(cmd, cwd=str(repo_root), check=True)
|
||||
logging.info("Dependencies installed successfully")
|
||||
|
||||
|
||||
Reference in New Issue
Block a user