Files
unslothai--unsloth/tests/python/test_install_python_stack.py
wehub-resource-sync e93507a09c
Lockfile supply-chain audit / lockfile supply-chain audit (push) Has been cancelled
Windows Studio GGUF CI / GPU prebuilt resolves without Visual Studio (push) Has been cancelled
Windows Studio GGUF CI / setup.ps1 unit tests (VS 2026 / CMake guard) (push) Has been cancelled
Windows Studio GGUF CI / real-VS detection (VS 2022) (push) Has been cancelled
Windows Studio GGUF CI / real-VS detection (VS 2026) (push) Has been cancelled
Windows Studio GGUF CI / VC++ runtime detect + install round-trip (windows-2025-vs2026) (push) Has been cancelled
Windows Studio GGUF CI / VC++ runtime detect + install round-trip (windows-latest) (push) Has been cancelled
Windows Studio Update CI / Studio Updating Tests (push) Has been cancelled
Wheel CI / Wheel build + content sanity + import smoke (push) Has been cancelled
Lint CI / Source lint (Python + shell + YAML + JSON + safety nets) (push) Has been cancelled
MLX CI on Mac M1 / dispatch (push) Has been cancelled
Security audit / advisory audit (pip + npm + cargo) (push) Has been cancelled
Security audit / pip scan-packages :: extras (push) Has been cancelled
Security audit / pip scan-packages :: studio (push) Has been cancelled
Security audit / pip scan-packages :: hf-stack (push) Has been cancelled
Security audit / npm scan-packages (Studio frontend tarballs) (push) Has been cancelled
Security audit / workflow-trigger lint (pull_request_target / cache-poisoning) (push) Has been cancelled
Security audit / pytest tests/security (push) Has been cancelled
Security audit / npm provenance + new install-script diff (push) Has been cancelled
Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Backend CI / (Python 3.10) (push) Has been cancelled
Backend CI / (Python 3.11) (push) Has been cancelled
Backend CI / (Python 3.12) (push) Has been cancelled
Backend CI / (Python 3.13) (push) Has been cancelled
Backend CI / Repo tests (CPU) (push) Has been cancelled
Frontend CI / Frontend build + bundle sanity (push) Has been cancelled
Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Studio GGUF CI / JSON, images (push) Has been cancelled
Mac Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Mac Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Mac Studio GGUF CI / JSON, images (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-14) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-15) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-26) (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-15-intel) (push) Has been cancelled
Mac Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Mac Studio Install Matrix CI / Install + load (macos-26-intel) (push) Has been cancelled
Mac Studio UI CI / Chat UI Tests (push) Has been cancelled
Studio Tauri CI / Tauri Linux debug build (no codesign) (push) Has been cancelled
Mac Studio Update CI / Studio Updating Tests (push) Has been cancelled
Studio UI CI / Chat UI Tests (push) Has been cancelled
Windows Studio API CI / Studio API & Auth Tests (push) Has been cancelled
Windows Studio UI CI / Chat UI Tests (push) Has been cancelled
Studio Update CI / Studio Updating Tests (push) Has been cancelled
Core / Core (HF=default + TRL=default) (push) Has been cancelled
Core / Core (HF=4.57.6 + TRL<1) (push) Has been cancelled
Core / Core (HF=latest + TRL=latest) (push) Has been cancelled
Core / llama.cpp build + smoke (push) Has been cancelled
Windows Studio GGUF CI / OpenAI, Anthropic API tests (push) Has been cancelled
Windows Studio GGUF CI / Tool calling Tests (push) Has been cancelled
Windows Studio GGUF CI / JSON, images (push) Has been cancelled
Windows Studio GGUF CI / Studio install + inference without Visual Studio (push) Has been cancelled
Studio export capability / capability (macos-latest) (push) Has been cancelled
Studio export capability / capability (ubuntu-latest) (push) Has been cancelled
Studio export capability / capability (windows-latest) (push) Has been cancelled
Cross-platform parity / parity (macos-latest) (push) Has been cancelled
Cross-platform parity / parity (windows-latest) (push) Has been cancelled
Scorecard supply-chain security / Scorecard analysis (push) Has been cancelled
Studio load-orchestrator CI / test (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:59:56 +08:00

151 lines
5.8 KiB
Python

"""Tests for install_python_stack._build_uv_cmd torch-backend handling."""
from __future__ import annotations
import glob
import importlib
import os
import sys
import tempfile
from pathlib import Path
from unittest import mock
import pytest
STUDIO_DIR = Path(__file__).resolve().parents[2] / "studio"
sys.path.insert(0, str(STUDIO_DIR))
import install_python_stack as ips
class TestBuildUvCmdTorchBackend:
"""Verify _build_uv_cmd only adds --torch-backend when UV_TORCH_BACKEND is set."""
def _call(self, args: tuple[str, ...] = ()) -> list[str]:
return ips._build_uv_cmd(args)
def test_default_no_torch_backend(self):
"""Without UV_TORCH_BACKEND env var, no --torch-backend flag."""
env = os.environ.copy()
env.pop("UV_TORCH_BACKEND", None)
with mock.patch.dict(os.environ, env, clear = True):
cmd = self._call(("somepackage",))
assert not any(
a.startswith("--torch-backend") for a in cmd
), f"--torch-backend should not appear by default, got: {cmd}"
def test_uv_torch_backend_auto(self):
"""UV_TORCH_BACKEND=auto adds --torch-backend=auto."""
with mock.patch.dict(os.environ, {"UV_TORCH_BACKEND": "auto"}):
cmd = self._call(("somepackage",))
assert "--torch-backend=auto" in cmd
def test_uv_torch_backend_cpu(self):
"""UV_TORCH_BACKEND=cpu adds --torch-backend=cpu."""
with mock.patch.dict(os.environ, {"UV_TORCH_BACKEND": "cpu"}):
cmd = self._call(("somepackage",))
assert "--torch-backend=cpu" in cmd
def test_uv_torch_backend_empty(self):
"""UV_TORCH_BACKEND="" (empty string) should NOT add --torch-backend."""
with mock.patch.dict(os.environ, {"UV_TORCH_BACKEND": ""}):
cmd = self._call(("somepackage",))
assert not any(
a.startswith("--torch-backend") for a in cmd
), f"Empty UV_TORCH_BACKEND should not add flag, got: {cmd}"
class TestUvSafePath:
"""_uv_safe_path hands uv a space-free `-c`/`-r` path (issue #6503)."""
def test_passthrough_when_no_space(self):
"""A path without a space is returned unchanged on every platform."""
p = "/tmp/plain/constraints.txt"
assert ips._uv_safe_path(p) == p
@pytest.mark.skipif(ips.IS_WINDOWS, reason = "POSIX temp-copy fallback")
def test_posix_space_path_returns_spacefree_copy(self, tmp_path):
src = tmp_path / "Open Source" / "constraints.txt"
src.parent.mkdir(parents = True)
src.write_text("torch>=2.6\n")
out = ips._uv_safe_path(str(src))
assert " " not in out, f"uv-safe path still has a space: {out!r}"
assert out != str(src)
assert Path(out).read_text() == "torch>=2.6\n"
@pytest.mark.skipif(ips.IS_WINDOWS, reason = "POSIX temp-copy fallback")
def test_posix_missing_file_falls_back_to_original(self):
"""No file to copy -> return the original path rather than raise."""
p = "/nonexistent dir/constraints.txt"
assert ips._uv_safe_path(p) == p
class TestUvSafePathHardening:
"""Edge cases for uv_safe_path + the UV_OVERRIDE channel (issue #6503)."""
@pytest.mark.skipif(ips.IS_WINDOWS, reason = "POSIX temp-copy fallback")
def test_tmpdir_with_space_falls_back(self, tmp_path, monkeypatch):
"""A space in the temp root itself -> fall back to the original path."""
from backend.utils import uv_path_safety as uvps
spaced = tmp_path / "tmp dir with space"
spaced.mkdir()
monkeypatch.setattr(uvps.tempfile, "mkdtemp", lambda *a, **k: str(spaced))
src = tmp_path / "Open Source" / "constraints.txt"
src.parent.mkdir(parents = True)
src.write_text("idna\n")
assert uvps.uv_safe_path(str(src)) == str(src)
@pytest.mark.skipif(ips.IS_WINDOWS, reason = "POSIX temp-copy fallback")
def test_no_temp_dir_leak_on_copy_failure(self, tmp_path, monkeypatch):
"""A copyfile failure after mkdtemp must not orphan the temp dir."""
from backend.utils import uv_path_safety as uvps
src = tmp_path / "Open Source" / "constraints.txt"
src.parent.mkdir(parents = True)
src.write_text("idna\n")
pattern = os.path.join(tempfile.gettempdir(), "unsloth_uv_*")
before = set(glob.glob(pattern))
def boom(*a, **k):
raise OSError("boom")
monkeypatch.setattr(uvps.shutil, "copyfile", boom)
out = uvps.uv_safe_path(str(src))
assert out == str(src)
assert set(glob.glob(pattern)) == before
@pytest.mark.skipif(ips.IS_WINDOWS, reason = "POSIX temp-copy fallback")
def test_cleanup_removes_and_clears_registry(self, tmp_path):
"""The atexit-registered cleanup removes the copies and empties the list."""
from backend.utils import uv_path_safety as uvps
src = tmp_path / "Open Source" / "constraints.txt"
src.parent.mkdir(parents = True)
src.write_text("idna\n")
out = uvps.uv_safe_path(str(src))
tmp_dir = Path(out).parent
assert tmp_dir.is_dir() and str(tmp_dir) in uvps._UV_SAFE_PATH_TMPDIRS
uvps._cleanup_uv_safe_path_tmpdirs()
assert not tmp_dir.exists()
assert uvps._UV_SAFE_PATH_TMPDIRS == []
@pytest.mark.skipif(ips.IS_WINDOWS, reason = "POSIX temp-copy fallback")
def test_uv_override_value_is_space_safe(self, tmp_path):
"""The value stored for UV_OVERRIDE must be space-free."""
from backend.utils import uv_path_safety as uvps
overrides = tmp_path / "Open Source" / "overrides-darwin-arm64.txt"
overrides.parent.mkdir(parents = True)
overrides.write_text("transformers>=4.57.6\n")
value = uvps.uv_safe_path(overrides)
assert " " not in value
assert Path(value).read_text() == "transformers>=4.57.6\n"