install: make torch 2.11 the default supported line on wheel-backed platforms
Fresh installs now resolve the torch 2.11 trio (torch 2.11.0, torchvision 0.26.0, torchaudio 2.11.0) everywhere the wheels exist, verified by live index resolution for py3.11-3.13: Linux x86_64 (cpu, cu126, cu128, cu130, rocm7.1, rocm7.2), Linux aarch64 (cpu, cu130), Windows x86_64 (cpu, cu126, cu128, cu130; triton-windows<3.7 resolves 3.6.0.post26, the 2.11 pairing) and macOS arm64. Existing installs are unaffected: the release preservation on both installers keeps the installed torch on re-runs (verified end to end against the live cpu index: a seeded 2.10.0 venv stays 2.10.0 with paired 0.25/2.10 companions while a fresh venv resolves the 2.11 trio). - install.sh: the supported range is centralized in _TORCH_CEILING / _TORCHVISION_CEILING / _TORCHAUDIO_CEILING and composed into the default constraints, so the next bump (torch 2.12) is a three-line change. The now-redundant cu* widen arm and custom-pin companion block collapse into the default; the curated ROCm >=2.11 floors stay literal. - install.ps1: the hoisted default trio, the CUDA flavor repair and the ROCm CPU fallback all use the <2.12 trio (the leaf gate collapsed since cu and non-cu now share the range). - setup.ps1: the unknown-leaf pinned CUDA trio widens to <2.12, matching the pinned cpu path. Deliberately NOT widened: rocm6.4 (tops at torch 2.9.1) and rocm7.0 (2.10.0) by index content; macOS x86_64 (no >=2.4 wheels, stays no-torch); the AMD per-arch repo.amd.com curated bounds for arches outside the 2.11 allowlist. Constraint suites updated to the ceiling scheme; parity suites updated to the widened trio. All sh, ps1 and pytest installer suites pass (the host-defaults suite and the tokenizers negative-control are known pre-existing failures).
This commit is contained in:
parent
e49a89f4f6
commit
3f79b5e53d
6 changed files with 100 additions and 132 deletions
39
install.ps1
39
install.ps1
|
|
@ -2156,29 +2156,21 @@ exit 0
|
|||
}
|
||||
}
|
||||
} elseif ($TorchIndexUrl -or $ROCmIndexUrl) {
|
||||
# Leaf-gated bounded trio, HOISTED so the release-preservation decision below can use it as the
|
||||
# default route window: torchaudio 2.11 dropped its torch pin, so a bare companion can drift from
|
||||
# a capped torch. cu<digits> families ship torch 2.11.x (paired triton-windows 3.6) so the ceiling
|
||||
# widens to <2.12; other leaves keep the 2.10 line. Mirrors install.sh and _CUDA_TORCH_PKG_SPEC.
|
||||
$_idxLeaf = (($TorchIndexUrl -split '[?#]', 2)[0].TrimEnd('/') -split '/')[-1].ToLowerInvariant()
|
||||
if ($_idxLeaf -match '^cu[0-9]+$') {
|
||||
$_pinTorchSpec = "torch>=2.4,<2.12.0"
|
||||
$_pinVisionSpec = "torchvision>=0.19,<0.27.0"
|
||||
$_pinAudioSpec = "torchaudio>=2.4,<2.12.0"
|
||||
} else {
|
||||
$_pinTorchSpec = "torch>=2.4,<2.11.0"
|
||||
$_pinVisionSpec = "torchvision>=0.19,<0.26.0"
|
||||
$_pinAudioSpec = "torchaudio>=2.4,<2.11.0"
|
||||
}
|
||||
# Bounded default trio (torch 2.11 line; wheels verified on cpu + cu126/cu128/cu130 for
|
||||
# win_amd64 with paired triton-windows 3.6), HOISTED so the release-preservation decision
|
||||
# below can use it as the default route window. torchaudio 2.11 dropped its torch pin, so a
|
||||
# bare companion can drift from a capped torch. Bump the three ceilings together with
|
||||
# install.sh's _TORCH_CEILING trio and the repair/fallback sites below (2 more literals).
|
||||
$_pinTorchSpec = "torch>=2.4,<2.12.0"
|
||||
$_pinVisionSpec = "torchvision>=0.19,<0.27.0"
|
||||
$_pinAudioSpec = "torchaudio>=2.4,<2.12.0"
|
||||
# Release preservation (twin of install.sh's _PREV_TORCH_PIN decision): evaluated after every
|
||||
# index/floor choice, incl. the ROCm reroute, so a raised floor rejects an older release. The
|
||||
# route window is the leaf-gated CUDA trio by default; the ROCm path uses its floor (or the
|
||||
# torch>=2.4,<2.11.0 range the ROCm->CPU fallback installs). The kept release is exported for
|
||||
# setup.ps1 (UNSLOTH_KEPT_TORCH) and cleared after setup runs.
|
||||
# kept release is exported for setup.ps1 (UNSLOTH_KEPT_TORCH) and cleared after setup runs.
|
||||
$script:PrevTorchPin = $null
|
||||
if (-not $SkipTorch -and $script:PrevTorchVer) {
|
||||
$_routeWindow = $_pinTorchSpec
|
||||
if ($ROCmIndexUrl) { if ($ROCmTorchFloor) { $_routeWindow = $ROCmTorchFloor } else { $_routeWindow = "torch>=2.4,<2.11.0" } }
|
||||
if ($ROCmIndexUrl -and $ROCmTorchFloor) { $_routeWindow = $ROCmTorchFloor }
|
||||
$script:PrevTorchPin = Get-PreviousTorchPin -TorchVersion $script:PrevTorchVer -Constraint $_routeWindow
|
||||
if ($script:PrevTorchPin) {
|
||||
$env:UNSLOTH_KEPT_TORCH = $script:PrevTorchPin.Release.PublicBase
|
||||
|
|
@ -2212,7 +2204,7 @@ exit 0
|
|||
$CpuFallbackIndexUrl = if ($env:UNSLOTH_PYTORCH_MIRROR) { "$($env:UNSLOTH_PYTORCH_MIRROR.TrimEnd('/'))/cpu" } else { "https://download.pytorch.org/whl/cpu" }
|
||||
substep "ROCm PyTorch install failed (exit $torchInstallExit); using a CPU base, Unsloth setup retries ROCm." "Yellow"
|
||||
# --force-reinstall: a failed ROCm install can leave an unpinned ROCm torch that still satisfies the CPU torch>= range, so without it uv would keep the ROCm build and only swap companions -- a mismatched venv the flavor-repair block won't fix. (No kept-release attempt: the ROCm attempts above always resolve or clear $script:PrevTorchPin first, so a pin never reaches this CPU base.)
|
||||
$torchInstallExit = Invoke-InstallCommandRetry -Label "install PyTorch (CPU fallback)" { uv pip install --python $VenvPython --force-reinstall "torch>=2.4,<2.11.0" "torchvision>=0.19,<0.26.0" "torchaudio>=2.4,<2.11.0" --default-index $CpuFallbackIndexUrl }
|
||||
$torchInstallExit = Invoke-InstallCommandRetry -Label "install PyTorch (CPU fallback)" { uv pip install --python $VenvPython --force-reinstall "torch>=2.4,<2.12.0" "torchvision>=0.19,<0.27.0" "torchaudio>=2.4,<2.12.0" --default-index $CpuFallbackIndexUrl }
|
||||
if ($torchInstallExit -ne 0) {
|
||||
Write-Host "[ERROR] Failed to install PyTorch (ROCm and CPU base both failed, exit code $torchInstallExit)" -ForegroundColor Red
|
||||
return (Exit-InstallFailure "Failed to install PyTorch (exit code $torchInstallExit)" $torchInstallExit)
|
||||
|
|
@ -2363,13 +2355,8 @@ exit 0
|
|||
}
|
||||
$installedTorchTag = Get-InstalledTorchTag -PythonExe $VenvPython
|
||||
} elseif ($expectedTorchTag -ne 'rocm') {
|
||||
# CUDA: stale +cpu (or wrong cuXXX) against a CUDA index -> reinstall triplet. Same leaf-gated ceiling as the install above: cu* serves 2.11.
|
||||
$_fixLeaf = (($TorchIndexUrl -split '[?#]', 2)[0].TrimEnd('/') -split '/')[-1].ToLowerInvariant()
|
||||
if ($_fixLeaf -match '^cu[0-9]+$') {
|
||||
$_fixTorchSpec = "torch>=2.4,<2.12.0"; $_fixVisionSpec = "torchvision>=0.19,<0.27.0"; $_fixAudioSpec = "torchaudio>=2.4,<2.12.0"
|
||||
} else {
|
||||
$_fixTorchSpec = "torch>=2.4,<2.11.0"; $_fixVisionSpec = "torchvision>=0.19,<0.26.0"; $_fixAudioSpec = "torchaudio>=2.4,<2.11.0"
|
||||
}
|
||||
# CUDA: stale +cpu (or wrong cuXXX) against a CUDA index -> reinstall triplet with the default 2.11-line trio (ceiling bump site, see the hoisted trio above).
|
||||
$_fixTorchSpec = "torch>=2.4,<2.12.0"; $_fixVisionSpec = "torchvision>=0.19,<0.27.0"; $_fixAudioSpec = "torchaudio>=2.4,<2.12.0"
|
||||
# Kept-release substitution (twin of install.sh's _install_torch_default_index honoring _PREV_TORCH_PIN): honor the preserved torch when the pin survived the E-decision; restore the range specs and retry if it isn't installable here. The --reinstall-package triplet stays on both attempts.
|
||||
$_cudaKept = $false
|
||||
if ($script:PrevTorchPin) {
|
||||
|
|
|
|||
30
install.sh
30
install.sh
|
|
@ -1888,18 +1888,24 @@ if [ -x "$VENV_DIR/bin/python" ]; then
|
|||
substep "${VENV_DIR}"
|
||||
fi
|
||||
|
||||
# Supported torch line: the default range admits torch 2.11 (wheels verified on
|
||||
# cpu/cu126/cu128/cu130/rocm7.1+/mac arm64). Bump the three ceilings together
|
||||
# when the next torch minor is validated; curated ROCm floors below stay literal.
|
||||
_TORCH_CEILING="2.12.0"
|
||||
_TORCHVISION_CEILING="0.27.0"
|
||||
_TORCHAUDIO_CEILING="2.12.0"
|
||||
# Default torch constraint; tightened for Python 3.13+ on arm64 macOS (torch <2.6 has no cp313 macOS arm64 wheels).
|
||||
TORCH_CONSTRAINT="torch>=2.4,<2.11.0"
|
||||
TORCH_CONSTRAINT="torch>=2.4,<${_TORCH_CEILING}"
|
||||
if [ "$SKIP_TORCH" = false ] && [ "$OS" = "macos" ] && [ "$_ARCH" = "arm64" ]; then
|
||||
_PY_MINOR=$("$VENV_DIR/bin/python" -c \
|
||||
"import sys; print(sys.version_info.minor)" 2>/dev/null || echo "0")
|
||||
if [ "$_PY_MINOR" -ge 13 ] 2>/dev/null; then
|
||||
TORCH_CONSTRAINT="torch>=2.6,<2.11.0"
|
||||
TORCH_CONSTRAINT="torch>=2.6,<${_TORCH_CEILING}"
|
||||
fi
|
||||
fi
|
||||
# Companion constraints bounded to torch's window: torchaudio 2.11 dropped its torch pin, so a bare companion beside a <2.11 torch resolves 2.11.
|
||||
TORCHVISION_CONSTRAINT="torchvision>=0.19,<0.26.0"
|
||||
TORCHAUDIO_CONSTRAINT="torchaudio>=2.4,<2.11.0"
|
||||
# Companion constraints bounded to torch's window: torchaudio 2.11 dropped its torch pin, so a bare companion can drift from a capped torch.
|
||||
TORCHVISION_CONSTRAINT="torchvision>=0.19,<${_TORCHVISION_CEILING}"
|
||||
TORCHAUDIO_CONSTRAINT="torchaudio>=2.4,<${_TORCHAUDIO_CEILING}"
|
||||
|
||||
# ── Resolve repo root (for --local installs) ──
|
||||
_REPO_ROOT="$(cd "$(dirname "$0" 2>/dev/null || echo ".")" && pwd)"
|
||||
|
|
@ -2480,27 +2486,15 @@ else
|
|||
fi
|
||||
|
||||
# rocm7.2 and the per-gfx indexes (Strix _grouped_mm fix) ship torch 2.11.0: raise the floor and pin companions; match the FINAL leaf only.
|
||||
# (cu*/cpu/custom leaves all use the default <2.12 trio above.)
|
||||
case "$_torch_index_leaf" in
|
||||
rocm7.2|gfx120x-all|gfx1151|gfx1150)
|
||||
TORCH_CONSTRAINT="torch>=2.11.0,<2.12.0"
|
||||
TORCHVISION_CONSTRAINT="torchvision>=0.26.0,<0.27.0"
|
||||
TORCHAUDIO_CONSTRAINT="torchaudio>=2.11.0,<2.12.0"
|
||||
;;
|
||||
# CUDA cu12x/cu13x indexes ship torch 2.11.x: widen the trio ceiling to <2.12.0.
|
||||
cu[0-9]*)
|
||||
TORCH_CONSTRAINT="torch>=2.4,<2.12.0"
|
||||
TORCHVISION_CONSTRAINT="torchvision>=0.19,<0.27.0"
|
||||
TORCHAUDIO_CONSTRAINT="torchaudio>=2.4,<2.12.0"
|
||||
;;
|
||||
esac
|
||||
|
||||
# A pinned custom/unknown-leaf index has no curated companion set: bound the companions to the same <2.11 range the Python path pins.
|
||||
if [ "$_torch_index_pinned" = true ] && \
|
||||
[ -z "$(_expected_torch_flavor_tag "$TORCH_INDEX_URL")" ]; then
|
||||
TORCHVISION_CONSTRAINT="torchvision>=0.19,<0.26.0"
|
||||
TORCHAUDIO_CONSTRAINT="torchaudio>=2.4,<2.11.0"
|
||||
fi
|
||||
|
||||
# Detect a Radeon card (*/rocm* index + rocminfo "Marketing Name:.*Radeon"); skipped when the index is pinned.
|
||||
_amd_gpu_radeon=false
|
||||
if [ "$_torch_index_pinned" = false ]; then
|
||||
|
|
|
|||
|
|
@ -2999,9 +2999,9 @@ if (-not $ROCmIndexUrl -and ($CuTag -eq "cpu" -or $ROCmCpuFallback)) {
|
|||
$cudaVisionSpec = "torchvision"
|
||||
$cudaAudioSpec = "torchaudio"
|
||||
if ($TorchIndexPinned -and -not (Test-CudaFamilyLeaf $CuTag)) {
|
||||
$cudaTorchSpec = "torch>=2.4,<2.11.0"
|
||||
$cudaVisionSpec = "torchvision>=0.19,<0.26.0"
|
||||
$cudaAudioSpec = "torchaudio>=2.4,<2.11.0"
|
||||
$cudaTorchSpec = "torch>=2.4,<2.12.0"
|
||||
$cudaVisionSpec = "torchvision>=0.19,<0.27.0"
|
||||
$cudaAudioSpec = "torchaudio>=2.4,<2.12.0"
|
||||
}
|
||||
# Release preservation: keep install.ps1's exported torch RELEASE (UNSLOTH_KEPT_TORCH) so a re-run
|
||||
# reinstalls the same CUDA build (+cuXXX follows this index). On a failed install, restore the computed
|
||||
|
|
|
|||
|
|
@ -405,30 +405,25 @@ class TestKnown211SetParity:
|
|||
), f"{label} floor gate must not use the unanchored ^rocm(\\d+)\\.(\\d+) prefix"
|
||||
|
||||
def test_install_ps1_bounds_unknown_leaf_pinned_torch(self):
|
||||
"""install.ps1's pinned-torch install must bound BOTH companions on EVERY
|
||||
index, cu<digits> families included: torchaudio 2.11 dropped its exact torch
|
||||
pin from the wheel metadata, so a bare companion beside torch<2.11 can
|
||||
resolve a mismatched 2.11.0 build (Codex P2, then unconditional per the
|
||||
torchaudio 2.11 unpinning)."""
|
||||
"""install.ps1's pinned-torch install must bound the whole trio on EVERY
|
||||
index with the default torch 2.11 line (<2.12 trio, matching install.sh's
|
||||
ceiling-composed default and _CUDA_TORCH_PKG_SPEC): torchaudio 2.11
|
||||
dropped its exact torch pin from the wheel metadata, so a bare companion
|
||||
beside a capped torch can resolve a mismatched build."""
|
||||
text = INSTALL_PS1.read_text(encoding = "utf-8")
|
||||
assert (
|
||||
'$_pinVisionSpec = "torchvision>=0.19,<0.26.0"' in text
|
||||
), "install.ps1 custom-pin install must bound torchvision (>=0.19,<0.26.0)"
|
||||
assert (
|
||||
'$_pinAudioSpec = "torchaudio>=2.4,<2.11.0"' in text
|
||||
), "install.ps1 custom-pin install must bound torchaudio (>=2.4,<2.11.0)"
|
||||
# cu<digits> leaves widen the whole trio to the torch 2.11 line (<2.12),
|
||||
# matching install.sh's cu[0-9]* widen and _CUDA_TORCH_PKG_SPEC; other
|
||||
# leaves keep the 2.10 line. The trio stays bounded on every index.
|
||||
assert '$_pinTorchSpec = "torch>=2.4,<2.12.0"' in text, (
|
||||
"install.ps1 must widen torch to <2.12.0 on cu<digits> index leaves"
|
||||
"install.ps1 default install must use the torch 2.11 line (<2.12.0)"
|
||||
)
|
||||
assert (
|
||||
'$_pinVisionSpec = "torchvision>=0.19,<0.27.0"' in text
|
||||
), "install.ps1 cu-leaf install must pair torchvision <0.27.0 with torch <2.12"
|
||||
), "install.ps1 must pair torchvision <0.27.0 with torch <2.12"
|
||||
assert (
|
||||
'$_pinAudioSpec = "torchaudio>=2.4,<2.12.0"' in text
|
||||
), "install.ps1 cu-leaf install must pair torchaudio <2.12.0 with torch <2.12"
|
||||
), "install.ps1 must pair torchaudio <2.12.0 with torch <2.12"
|
||||
# No stale 2.10-line default remains anywhere in the Windows installer.
|
||||
assert '"torch>=2.4,<2.11.0"' not in text, (
|
||||
"install.ps1 must not retain a <2.11.0 default torch range"
|
||||
)
|
||||
# The bounded trio must actually be passed to the install command.
|
||||
assert re.search(
|
||||
r'\$_pinTorchSpec \$_pinVisionSpec \$_pinAudioSpec --default-index \$TorchIndexUrl',
|
||||
|
|
@ -672,9 +667,9 @@ class TestPinnedIndexClearsUvEnvParity:
|
|||
# The custom-leaf branch bounds torch AND both companions (parity with the
|
||||
# other installers' custom-pin trio bounds), gated on a non-cu-family leaf.
|
||||
for spec in (
|
||||
'$cudaTorchSpec = "torch>=2.4,<2.11.0"',
|
||||
'$cudaVisionSpec = "torchvision>=0.19,<0.26.0"',
|
||||
'$cudaAudioSpec = "torchaudio>=2.4,<2.11.0"',
|
||||
'$cudaTorchSpec = "torch>=2.4,<2.12.0"',
|
||||
'$cudaVisionSpec = "torchvision>=0.19,<0.27.0"',
|
||||
'$cudaAudioSpec = "torchaudio>=2.4,<2.12.0"',
|
||||
):
|
||||
assert spec in text, f"setup.ps1 must bound the custom-leaf trio: {spec}"
|
||||
assert (
|
||||
|
|
|
|||
|
|
@ -64,35 +64,30 @@ class TestStructuralTorchConstraint:
|
|||
_sh = _read(_INSTALL_SH)
|
||||
|
||||
def test_default_assignment_exists(self):
|
||||
assert 'TORCH_CONSTRAINT="torch>=2.4,<2.11.0"' in self._sh
|
||||
"""The default range composes the per-file ceiling variable, so the
|
||||
supported line (torch 2.11 today) is bumped in one place."""
|
||||
assert '_TORCH_CEILING="2.12.0"' in self._sh
|
||||
assert 'TORCH_CONSTRAINT="torch>=2.4,<${_TORCH_CEILING}"' in self._sh
|
||||
|
||||
def test_tightened_assignment_exists(self):
|
||||
assert 'TORCH_CONSTRAINT="torch>=2.6,<2.11.0"' in self._sh
|
||||
assert 'TORCH_CONSTRAINT="torch>=2.6,<${_TORCH_CEILING}"' in self._sh
|
||||
|
||||
def test_cuda_constraint_widened_to_2_12(self):
|
||||
"""A fresh CUDA install widens the ceiling to <2.12.0 so cu12x/cu13x
|
||||
land torch 2.11.x (matches the base image and _CUDA_TORCH_PKG_SPEC);
|
||||
without it cu128/cu130 resolves torch 2.10.x."""
|
||||
assert 'TORCH_CONSTRAINT="torch>=2.4,<2.12.0"' in self._sh
|
||||
|
||||
def test_cuda_case_widens_via_index_leaf(self):
|
||||
"""The cu* branch of the _torch_index_leaf case sets the widened
|
||||
constraint (parallel to rocm7.2), anchored on the leaf."""
|
||||
m = re.search(
|
||||
r'cu\[0-9\]\*\)\s*TORCH_CONSTRAINT="torch>=2\.4,<2\.12\.0"',
|
||||
self._sh,
|
||||
)
|
||||
assert m is not None, "CUDA (cu*) TORCH_CONSTRAINT widening case not found"
|
||||
def test_companion_ceilings_composed(self):
|
||||
"""Companions bound to the same window via their own ceiling vars."""
|
||||
assert '_TORCHVISION_CEILING="0.27.0"' in self._sh
|
||||
assert '_TORCHAUDIO_CEILING="2.12.0"' in self._sh
|
||||
assert 'TORCHVISION_CONSTRAINT="torchvision>=0.19,<${_TORCHVISION_CEILING}"' in self._sh
|
||||
assert 'TORCHAUDIO_CONSTRAINT="torchaudio>=2.4,<${_TORCHAUDIO_CEILING}"' in self._sh
|
||||
|
||||
def test_variable_used_in_pip_install(self):
|
||||
"""$TORCH_CONSTRAINT must appear in a uv pip install line."""
|
||||
assert '"$TORCH_CONSTRAINT"' in self._sh
|
||||
|
||||
def test_hardcoded_torch_constraint_only_once(self):
|
||||
"""The hard-coded torch>=2.4,<2.11.0 string should appear exactly once
|
||||
in install.sh (the default assignment), not in pip install lines."""
|
||||
count = self._sh.count('"torch>=2.4,<2.11.0"')
|
||||
assert count == 1, f"Expected 1, found {count}"
|
||||
def test_hardcoded_torch_constraint_gone(self):
|
||||
"""No hard-coded default ranges remain outside the ceiling-composed
|
||||
assignments (curated ROCm >=2.11 floors stay literal)."""
|
||||
assert self._sh.count('"torch>=2.4,<2.11.0"') == 0
|
||||
assert self._sh.count('"torch>=2.4,<2.12.0"') == 0
|
||||
|
||||
def test_tightening_guarded_by_skip_torch(self):
|
||||
"""The block must check SKIP_TORCH=false."""
|
||||
|
|
@ -122,7 +117,7 @@ class TestStructuralInstallPs1Unchanged:
|
|||
assert "$TorchConstraint" not in self._ps1
|
||||
|
||||
def test_hardcoded_torch_constraint_present(self):
|
||||
assert '"torch>=2.4,<2.11.0"' in self._ps1
|
||||
assert '"torch>=2.4,<2.12.0"' in self._ps1
|
||||
|
||||
|
||||
class TestInstallPs1UvDefaultIndex:
|
||||
|
|
|
|||
|
|
@ -76,11 +76,12 @@ run_constraint_snippet() {
|
|||
OS=\"$_os\"
|
||||
_ARCH=\"$_arch\"
|
||||
VENV_DIR=\"$_venv_dir\"
|
||||
TORCH_CONSTRAINT=\"torch>=2.4,<2.11.0\"
|
||||
_TORCH_CEILING=\"2.12.0\"
|
||||
TORCH_CONSTRAINT=\"torch>=2.4,<\${_TORCH_CEILING}\"
|
||||
if [ \"\$SKIP_TORCH\" = false ] && [ \"\$OS\" = \"macos\" ] && [ \"\$_ARCH\" = \"arm64\" ]; then
|
||||
_PY_MINOR=\$(\"\$VENV_DIR/bin/python\" -c \"import sys; print(sys.version_info.minor)\" 2>/dev/null || echo \"0\")
|
||||
if [ \"\$_PY_MINOR\" -ge 13 ] 2>/dev/null; then
|
||||
TORCH_CONSTRAINT=\"torch>=2.6,<2.11.0\"
|
||||
TORCH_CONSTRAINT=\"torch>=2.6,<\${_TORCH_CEILING}\"
|
||||
fi
|
||||
fi
|
||||
echo \"\$TORCH_CONSTRAINT\"
|
||||
|
|
@ -94,43 +95,39 @@ echo "=== Structural: TORCH_CONSTRAINT in install.sh ==="
|
|||
|
||||
_SH_CONTENT=$(cat "$INSTALL_SH")
|
||||
|
||||
_count=$(grep -c 'TORCH_CONSTRAINT="torch>=2.4,<2.11.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "default TORCH_CONSTRAINT assignment exists" "1" "$_count"
|
||||
# The supported line is centralized in per-file ceiling variables so a future
|
||||
# torch 2.12 bump is a three-line change; the default range admits torch 2.11.
|
||||
_count=$(grep -c '_TORCH_CEILING="2.12.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "torch ceiling variable defined once" "1" "$_count"
|
||||
_count=$(grep -c '_TORCHVISION_CEILING="0.27.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "torchvision ceiling variable defined once" "1" "$_count"
|
||||
_count=$(grep -c '_TORCHAUDIO_CEILING="2.12.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "torchaudio ceiling variable defined once" "1" "$_count"
|
||||
|
||||
_count=$(grep -c 'TORCH_CONSTRAINT="torch>=2.6,<2.11.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "tightened TORCH_CONSTRAINT assignment exists" "1" "$_count"
|
||||
_count=$(grep -c 'TORCH_CONSTRAINT="torch>=2.4,<${_TORCH_CEILING}"' "$INSTALL_SH" || true)
|
||||
assert_eq "default TORCH_CONSTRAINT composes the ceiling" "1" "$_count"
|
||||
_count=$(grep -c 'TORCH_CONSTRAINT="torch>=2.6,<${_TORCH_CEILING}"' "$INSTALL_SH" || true)
|
||||
assert_eq "tightened TORCH_CONSTRAINT composes the ceiling" "1" "$_count"
|
||||
|
||||
_count=$(grep -c '"\$TORCH_CONSTRAINT"' "$INSTALL_SH" || true)
|
||||
_has_var=$([ "$_count" -ge 1 ] && echo "yes" || echo "no")
|
||||
assert_eq "\$TORCH_CONSTRAINT used in pip install" "yes" "$_has_var"
|
||||
|
||||
# Hardcoded torch>=2.4,<2.11.0 should only appear once (the default assignment)
|
||||
_hardcoded=$(grep -c '"torch>=2.4,<2.11.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "hardcoded torch>=2.4 appears exactly once" "1" "$_hardcoded"
|
||||
# No stray hardcoded default ranges outside the ceiling-composed assignments
|
||||
# (the curated ROCm >=2.11 floors are deliberately literal).
|
||||
_hardcoded=$(grep -c '"torch>=2.4,<2.11.0"\|"torch>=2.4,<2.12.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "no hardcoded default torch range remains" "0" "$_hardcoded"
|
||||
|
||||
# Companions must be bounded to torch's window everywhere: the <2.11 bound appears
|
||||
# twice (default assignments + the pinned custom-leaf block), never bare. torchaudio
|
||||
# 2.11 dropped its exact torch pin, so a bare companion next to a <2.11-capped torch
|
||||
# resolves a mismatched 2.11 build.
|
||||
_count=$(grep -c 'TORCHVISION_CONSTRAINT="torchvision>=0.19,<0.26.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "torchvision bounded (<0.26) at default + custom-leaf" "2" "$_count"
|
||||
_count=$(grep -c 'TORCHAUDIO_CONSTRAINT="torchaudio>=2.4,<2.11.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "torchaudio bounded (<2.11) at default + custom-leaf" "2" "$_count"
|
||||
# Companions must be bounded to torch's window everywhere, never bare: torchaudio
|
||||
# 2.11 dropped its exact torch pin, so a bare companion can drift from a capped torch.
|
||||
_count=$(grep -c 'TORCHVISION_CONSTRAINT="torchvision>=0.19,<${_TORCHVISION_CEILING}"' "$INSTALL_SH" || true)
|
||||
assert_eq "torchvision default composes the ceiling" "1" "$_count"
|
||||
_count=$(grep -c 'TORCHAUDIO_CONSTRAINT="torchaudio>=2.4,<${_TORCHAUDIO_CEILING}"' "$INSTALL_SH" || true)
|
||||
assert_eq "torchaudio default composes the ceiling" "1" "$_count"
|
||||
_count=$(grep -c 'TORCHVISION_CONSTRAINT="torchvision"$' "$INSTALL_SH" || true)
|
||||
assert_eq "no bare torchvision companion remains" "0" "$_count"
|
||||
_count=$(grep -c 'TORCHAUDIO_CONSTRAINT="torchaudio"$' "$INSTALL_SH" || true)
|
||||
assert_eq "no bare torchaudio companion remains" "0" "$_count"
|
||||
# The cu* widen must carry the companions with it (torch <2.12 with torchaudio <2.11
|
||||
# would cap a mismatched pair the other way).
|
||||
assert_eq "cu widen pairs torchaudio (<2.12)" "1" "$(grep -c 'TORCHAUDIO_CONSTRAINT="torchaudio>=2.4,<2.12.0"' "$INSTALL_SH" || true)"
|
||||
_gated=$(grep -c '_expected_torch_flavor_tag "$TORCH_INDEX_URL"' "$INSTALL_SH" || true)
|
||||
_has_gate=$([ "$_gated" -ge 1 ] && echo "yes" || echo "no")
|
||||
assert_eq "custom-companion bound gated on empty flavor tag" "yes" "$_has_gate"
|
||||
|
||||
# A fresh CUDA install widens the ceiling to <2.12.0 so cu12x/cu13x land torch
|
||||
# 2.11.x (matches the base image and _CUDA_TORCH_PKG_SPEC).
|
||||
_cuda_widen=$(grep -c 'TORCH_CONSTRAINT="torch>=2.4,<2.12.0"' "$INSTALL_SH" || true)
|
||||
assert_eq "CUDA TORCH_CONSTRAINT widened to <2.12.0" "1" "$_cuda_widen"
|
||||
|
||||
# Widening keys off the final leaf (_torch_index_leaf), not the full URL, so a
|
||||
# mirror base path with cu*/rocm7.2 but a cpu/older-rocm leaf is not mis-widened.
|
||||
|
|
@ -181,7 +178,7 @@ _PS1_CONTENT=$(cat "$INSTALL_PS1")
|
|||
_ps1_has_var=$(echo "$_PS1_CONTENT" | grep -c 'TORCH_CONSTRAINT\|TorchConstraint' || true)
|
||||
assert_eq "install.ps1 has no TORCH_CONSTRAINT variable" "0" "$_ps1_has_var"
|
||||
|
||||
_ps1_hardcoded=$(echo "$_PS1_CONTENT" | grep -c '"torch>=2.4,<2.11.0"' || true)
|
||||
_ps1_hardcoded=$(echo "$_PS1_CONTENT" | grep -c '"torch>=2.4,<2.12.0"' || true)
|
||||
_ps1_has_hc=$([ "$_ps1_hardcoded" -ge 1 ] && echo "yes" || echo "no")
|
||||
assert_eq "install.ps1 has hardcoded torch constraint" "yes" "$_ps1_has_hc"
|
||||
|
||||
|
|
@ -196,55 +193,55 @@ trap 'rm -rf "$TMPDIR_BASE"' EXIT
|
|||
|
||||
# 1. arm64 macOS py3.13 -> tightened
|
||||
_result=$(run_constraint_snippet false macos arm64 13 "$TMPDIR_BASE/v1")
|
||||
assert_eq "arm64+macos+py313 -> tightened" "torch>=2.6,<2.11.0" "$_result"
|
||||
assert_eq "arm64+macos+py313 -> tightened" "torch>=2.6,<2.12.0" "$_result"
|
||||
|
||||
# 2. arm64 macOS py3.14 -> tightened (future-proofed)
|
||||
_result=$(run_constraint_snippet false macos arm64 14 "$TMPDIR_BASE/v2")
|
||||
assert_eq "arm64+macos+py314 -> tightened" "torch>=2.6,<2.11.0" "$_result"
|
||||
assert_eq "arm64+macos+py314 -> tightened" "torch>=2.6,<2.12.0" "$_result"
|
||||
|
||||
# 3. arm64 macOS py3.12 -> default
|
||||
_result=$(run_constraint_snippet false macos arm64 12 "$TMPDIR_BASE/v3")
|
||||
assert_eq "arm64+macos+py312 -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "arm64+macos+py312 -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 4. arm64 macOS py3.11 -> default
|
||||
_result=$(run_constraint_snippet false macos arm64 11 "$TMPDIR_BASE/v4")
|
||||
assert_eq "arm64+macos+py311 -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "arm64+macos+py311 -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 5. Linux x86_64 py3.13 -> default (Linux unaffected)
|
||||
_result=$(run_constraint_snippet false linux x86_64 13 "$TMPDIR_BASE/v5")
|
||||
assert_eq "linux+x86_64+py313 -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "linux+x86_64+py313 -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 6. Linux aarch64 py3.13 -> default (guard checks OS=macos)
|
||||
_result=$(run_constraint_snippet false linux aarch64 13 "$TMPDIR_BASE/v6")
|
||||
assert_eq "linux+aarch64+py313 -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "linux+aarch64+py313 -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 7. Intel Mac x86_64 py3.12 -> default (arch mismatch)
|
||||
_result=$(run_constraint_snippet false macos x86_64 12 "$TMPDIR_BASE/v7")
|
||||
assert_eq "macos+x86_64+py312 -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "macos+x86_64+py312 -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 8. SKIP_TORCH=true arm64 macOS py3.13 -> block skipped, default
|
||||
_result=$(run_constraint_snippet true macos arm64 13 "$TMPDIR_BASE/v8")
|
||||
assert_eq "SKIP_TORCH=true -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "SKIP_TORCH=true -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 9. WSL py3.13 -> default
|
||||
_result=$(run_constraint_snippet false wsl x86_64 13 "$TMPDIR_BASE/v9")
|
||||
assert_eq "wsl+py313 -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "wsl+py313 -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 10. py_minor=0 (failed query fallback) -> default
|
||||
_result=$(run_constraint_snippet false macos arm64 0 "$TMPDIR_BASE/v10")
|
||||
assert_eq "py_minor=0 fallback -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "py_minor=0 fallback -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 11. Boundary: py_minor=12 -> NOT tightened
|
||||
_result=$(run_constraint_snippet false macos arm64 12 "$TMPDIR_BASE/v11")
|
||||
assert_eq "boundary py_minor=12 -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "boundary py_minor=12 -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# 12. Boundary: py_minor=13 -> tightened
|
||||
_result=$(run_constraint_snippet false macos arm64 13 "$TMPDIR_BASE/v12")
|
||||
assert_eq "boundary py_minor=13 -> tightened" "torch>=2.6,<2.11.0" "$_result"
|
||||
assert_eq "boundary py_minor=13 -> tightened" "torch>=2.6,<2.12.0" "$_result"
|
||||
|
||||
# 13. Intel Mac py3.13 -> default (arch=x86_64, not arm64)
|
||||
_result=$(run_constraint_snippet false macos x86_64 13 "$TMPDIR_BASE/v13")
|
||||
assert_eq "macos+x86_64+py313 -> default" "torch>=2.4,<2.11.0" "$_result"
|
||||
assert_eq "macos+x86_64+py313 -> default" "torch>=2.4,<2.12.0" "$_result"
|
||||
|
||||
# ======================================================================
|
||||
# Mock uv integration
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue