* Reduce and tighten comments and docstrings in tests Shorten verbose comments and docstrings across the test suite without changing any test logic. Remove narration that restates the next line, collapse long module and test docstrings to a single line, and drop banner separators. Keep regression context (issue and PR references, run ids), skip reasons, mocking and timing rationale, license headers, lint and type directives, and commented-out code. Comments and docstrings only: an AST signature check confirms no code, assertions, or string literals changed, and the suite byte-compiles cleanly. * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
167 lines
5.9 KiB
Python
167 lines
5.9 KiB
Python
# SPDX-License-Identifier: AGPL-3.0-only
|
|
# Copyright 2026-present the Unsloth AI Inc. team.
|
|
"""CPU-only smoke imports for unsloth_zoo modules touching vLLM / GRPO +
|
|
fast_inference, under the tests/_zoo_aggressive_cuda_spoof harness.
|
|
|
|
rl_replacements and empty_model are vllm-free and MUST import on CPU with no
|
|
vllm; the three vllm-hard-import modules are skipped without it (covered
|
|
statically by test_vllm_pinned_symbols.py).
|
|
|
|
Cross-references (unsloth_zoo commits that fixed bugs surfaced here):
|
|
e3072a23 (WorkerLoRAManager.supports_tower_connector_lora missing),
|
|
0c95753a (_call_create_lora_manager TypeError on vLLM 0.9.x),
|
|
2a80d543 (vLLM 0.15 LoRA manager compat),
|
|
ec186187 (vLLM PR #30253 vllm.lora.models split),
|
|
e915bca1 (LoRA embeddings= arg removed; lora_extra_vocab_size optional),
|
|
fa82dcc2 / 664e52ea (UNSLOTH_VLLM_STANDBY hard-error on vLLM 0.10/0.14).
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import importlib
|
|
import importlib.util
|
|
import os
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
|
|
|
|
# Apply the consolidated CPU spoof at import time, before any unsloth import.
|
|
_SPOOF_DIR = Path(__file__).resolve().parents[1]
|
|
sys.path.insert(0, str(_SPOOF_DIR))
|
|
import _zoo_aggressive_cuda_spoof as _spoof # noqa: E402
|
|
|
|
_spoof.apply()
|
|
|
|
|
|
# Some unsloth_zoo modules read pynvml at import; stub it for the runner.
|
|
def _stub_module(name: str, attrs: dict | None = None) -> None:
|
|
if name in sys.modules:
|
|
return
|
|
import types
|
|
|
|
m = types.ModuleType(name)
|
|
for k, v in (attrs or {}).items():
|
|
setattr(m, k, v)
|
|
sys.modules[name] = m
|
|
|
|
|
|
_stub_module(
|
|
"pynvml",
|
|
{
|
|
"nvmlInit": lambda: None,
|
|
"nvmlShutdown": lambda: None,
|
|
"nvmlDeviceGetCount": lambda: 1,
|
|
"nvmlDeviceGetHandleByIndex": lambda i: object(),
|
|
"nvmlDeviceGetMemoryInfo": lambda h: type(
|
|
"_M",
|
|
(),
|
|
{"total": 80 * 1024**3, "free": 70 * 1024**3, "used": 10 * 1024**3},
|
|
)(),
|
|
},
|
|
)
|
|
|
|
|
|
@pytest.fixture(autouse = True)
|
|
def _torch_distributed_safe(monkeypatch):
|
|
"""Give torch.distributed probes safe single-process defaults."""
|
|
try:
|
|
import torch.distributed as dist
|
|
|
|
monkeypatch.setattr(dist, "is_available", lambda: True, raising = False)
|
|
monkeypatch.setattr(dist, "is_initialized", lambda: False, raising = False)
|
|
monkeypatch.setattr(dist, "get_world_size", lambda *a, **k: 1, raising = False)
|
|
monkeypatch.setattr(dist, "get_rank", lambda *a, **k: 0, raising = False)
|
|
except Exception:
|
|
pass
|
|
|
|
|
|
def _has_unsloth_zoo() -> bool:
|
|
return importlib.util.find_spec("unsloth_zoo") is not None
|
|
|
|
|
|
def _has_vllm() -> bool:
|
|
return importlib.util.find_spec("vllm") is not None
|
|
|
|
|
|
# rl_replacements: zero direct vllm imports; the GRPO + fast_inference surface.
|
|
|
|
|
|
@pytest.mark.skipif(not _has_unsloth_zoo(), reason = "unsloth_zoo not installed")
|
|
def test_rl_replacements_imports_without_vllm():
|
|
"""unsloth_zoo.rl_replacements must NOT pull in vllm at import time."""
|
|
sys.modules.pop("unsloth_zoo.rl_replacements", None)
|
|
rl = importlib.import_module("unsloth_zoo.rl_replacements")
|
|
# A transitive vllm import crashes GRPOTrainer construction on Colab.
|
|
assert "vllm" not in sys.modules, (
|
|
"unsloth_zoo.rl_replacements imported vllm transitively; this breaks "
|
|
"GRPO on environments without vllm installed (the use_vllm=False path "
|
|
"is supposed to work without vllm)."
|
|
)
|
|
# Spot-check a known public surface
|
|
assert (
|
|
hasattr(rl, "RL_REPLACEMENTS")
|
|
or hasattr(rl, "RL_FUNCTIONS")
|
|
or any(name.startswith("grpo_") for name in dir(rl))
|
|
), "expected at least one GRPO-related export in rl_replacements"
|
|
|
|
|
|
# empty_model: no vllm import; pure builder for the fast_inference=True path.
|
|
|
|
|
|
@pytest.mark.skipif(not _has_unsloth_zoo(), reason = "unsloth_zoo not installed")
|
|
def test_empty_model_imports_without_vllm():
|
|
sys.modules.pop("unsloth_zoo.empty_model", None)
|
|
em = importlib.import_module("unsloth_zoo.empty_model")
|
|
assert (
|
|
"vllm" not in sys.modules
|
|
), "unsloth_zoo.empty_model imported vllm transitively; expected to be vllm-free"
|
|
assert (
|
|
hasattr(em, "create_empty_causal_lm")
|
|
or hasattr(em, "create_empty_model")
|
|
or any(n.startswith("create_empty") for n in dir(em))
|
|
), "expected a create_empty_* helper in empty_model"
|
|
|
|
|
|
# vllm_lora_request / vllm_lora_worker_manager / vllm_utils: hard-import vllm,
|
|
# so skip without it (pinned-symbols test covers version compat statically).
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not (_has_unsloth_zoo() and _has_vllm()), reason = "vllm not installed on this runner"
|
|
)
|
|
def test_vllm_lora_request_imports():
|
|
sys.modules.pop("unsloth_zoo.vllm_lora_request", None)
|
|
importlib.import_module("unsloth_zoo.vllm_lora_request")
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not (_has_unsloth_zoo() and _has_vllm()), reason = "vllm not installed on this runner"
|
|
)
|
|
def test_vllm_lora_worker_manager_imports():
|
|
sys.modules.pop("unsloth_zoo.vllm_lora_worker_manager", None)
|
|
mod = importlib.import_module("unsloth_zoo.vllm_lora_worker_manager")
|
|
# e3072a23 added supports_tower_connector_lora for vLLM 0.14's
|
|
# gpu_model_runner; assert the patched class exposes it.
|
|
cls = getattr(mod, "WorkerLoRAManager", None)
|
|
if cls is not None:
|
|
assert (
|
|
hasattr(cls, "supports_tower_connector_lora")
|
|
or any("tower_connector" in name for name in dir(cls))
|
|
or True
|
|
), (
|
|
"WorkerLoRAManager should expose supports_tower_connector_lora "
|
|
"for vLLM 0.14+ compatibility"
|
|
)
|
|
|
|
|
|
@pytest.mark.skipif(
|
|
not (_has_unsloth_zoo() and _has_vllm()), reason = "vllm not installed on this runner"
|
|
)
|
|
def test_vllm_utils_imports():
|
|
sys.modules.pop("unsloth_zoo.vllm_utils", None)
|
|
mod = importlib.import_module("unsloth_zoo.vllm_utils")
|
|
assert callable(
|
|
getattr(mod, "patch_vllm", None)
|
|
), "unsloth_zoo.vllm_utils must expose patch_vllm()"
|