install: harden the preservation probe and the Windows override handoff

Three review follow-ups:

- install.sh's existing-venv torch probe now reads the version from dist
  metadata via the bounded runner instead of importing torch: a wedged
  CUDA/ROCm driver can hang the import indefinitely, while the metadata
  read never touches the driver. A failed or timed-out probe simply
  yields no preservable version.

- install.ps1's New-UnslothTorchOverridesFile folds caller-supplied
  UV_OVERRIDE files into the temporary overrides file (minus their
  torch-trio lines), matching install.sh: --overrides replaces the env
  file wholesale, so without the merge a caller's own dependency
  overrides were silently dropped during the unsloth resolution.

- install.ps1 clears an inherited UNSLOTH_KEPT_TORCH before the pin
  decision and sets it only on a fresh Get-PreviousTorchPin result: an
  interrupted earlier run could leak a stale exact pin into setup.ps1
  even when the current run found nothing to preserve or the upgrade
  opt-in was set.

Verified: the metadata probe returns the installed release through the
bounded runner; the override filter keeps unrelated pins (numpy,
torchao) while dropping torch/torchvision/torchaudio lines in all spec
forms. Full sh, ps1 and pytest installer batteries pass (host-defaults
and the tokenizers negative-control are the known pre-existing
failures).
This commit is contained in:
Daniel Han 2026-07-20 12:07:08 +00:00
commit d90fd8b563
2 changed files with 19 additions and 3 deletions

View file

@ -2112,6 +2112,17 @@ exit 0
$pins = & $PythonExe -c "from importlib.metadata import version, PackageNotFoundError`nfor _p in ('torch', 'torchvision', 'torchaudio'):`n try:`n print(_p + '==' + version(_p))`n except PackageNotFoundError:`n pass" 2>$null
$lines = @($pins | Where-Object { $_ -match '^torch' })
if ($lines.Count -eq 0 -or $lines[0] -notmatch '^torch==') { return $null }
# --overrides replaces any UV_OVERRIDE env file, so fold caller-supplied
# override files in (minus their torch-trio lines) like install.sh does.
if ($env:UV_OVERRIDE) {
foreach ($ovFile in ($env:UV_OVERRIDE -split '\s+' | Where-Object { $_ })) {
if (Test-Path -LiteralPath $ovFile -PathType Leaf) {
$lines += @(Get-Content -LiteralPath $ovFile | Where-Object {
$_ -notmatch '^\s*torch(vision|audio)?([\s<>=!~;@[]|$)'
})
}
}
}
$f = [System.IO.Path]::GetTempFileName()
Set-Content -LiteralPath $f -Value ($lines -join "`n") -Encoding ascii
return $f
@ -2168,6 +2179,9 @@ exit 0
# index/floor choice, incl. the ROCm reroute, so a raised floor rejects an older release. The
# kept release is exported for setup.ps1 (UNSLOTH_KEPT_TORCH) and cleared after setup runs.
$script:PrevTorchPin = $null
# Internal handoff variable: always clear an inherited value first (an interrupted
# earlier run can leak a stale pin into setup.ps1) and set it only on a fresh decision.
Remove-Item Env:UNSLOTH_KEPT_TORCH -ErrorAction SilentlyContinue
if (-not $SkipTorch -and $script:PrevTorchVer) {
$_routeWindow = $_pinTorchSpec
if ($ROCmIndexUrl -and $ROCmTorchFloor) { $_routeWindow = $ROCmTorchFloor }

View file

@ -1770,9 +1770,11 @@ if [ -x "$VENV_DIR/bin/python" ]; then
echo " Move it aside or choose an empty UNSLOTH_STUDIO_HOME." >&2
exit 1
fi
# Record the existing venv's torch BEFORE replacement (see _previous_torch_pin); last line only so stdout noise can't corrupt it.
_PREV_TORCH_VER=$("$VENV_DIR/bin/python" -c \
"import torch; print(torch.__version__)" 2>/dev/null | tail -n 1 || true)
# Record the existing venv's torch BEFORE replacement (see _previous_torch_pin); last line
# only so stdout noise can't corrupt it. Reads dist metadata instead of importing torch (a
# wedged CUDA/ROCm driver can hang the import indefinitely) and bounds the interpreter run.
_PREV_TORCH_VER=$(_run_bounded "$VENV_DIR/bin/python" -c \
"import importlib.metadata as m; print(m.version('torch'))" 2>/dev/null | tail -n 1 || true)
substep "preserving existing environment for rollback..."
_start_studio_venv_replacement "$VENV_DIR"
elif [ "$_STUDIO_HOME_REDIRECT" != "env" ] && [ -x "$STUDIO_HOME/.venv/bin/python" ]; then