diff --git a/tests/diffusion/attention/test_attention_config.py b/tests/diffusion/attention/test_attention_config.py
index 4a053b1bf..0b975f27c 100644
--- a/tests/diffusion/attention/test_attention_config.py
+++ b/tests/diffusion/attention/test_attention_config.py
@@ -42,6 +42,14 @@ from vllm_omni.diffusion.data import (
pytestmark = [pytest.mark.core_model, pytest.mark.diffusion, pytest.mark.cpu]
+@pytest.fixture(autouse=True)
+def _clear_inherited_attention_backend(monkeypatch):
+ # Weekly CPU exports DIFFUSION_ATTENTION_BACKEND; OmniDiffusionConfig
+ # treats that as an explicit default so auto-backend cases break.
+ # Tests that setenv the same variable still work: this fixture runs first.
+ monkeypatch.delenv("DIFFUSION_ATTENTION_BACKEND", raising=False)
+
+
class TestAttentionSpec:
def test_construct_no_skip_softmax(self):
spec = AttentionSpec(backend="FLASH_ATTN")
@@ -416,13 +424,6 @@ class TestBuildAttentionConfig:
class TestOmniDiffusionConfigAttentionParsing:
"""Test OmniDiffusionConfig attention shorthand and structured config."""
- @pytest.fixture(autouse=True)
- def _clear_diffusion_attention_backend_env(self, monkeypatch):
- # OmniDiffusionConfig.__post_init__ applies DIFFUSION_ATTENTION_BACKEND via
- # build_attention_config(); clear it so these tests assert config defaults,
- # not whatever the process inherited from CI / sibling tests.
- monkeypatch.delenv("DIFFUSION_ATTENTION_BACKEND", raising=False)
-
def test_diffusion_attention_backend_sets_default(self):
config = OmniDiffusionConfig.from_kwargs(diffusion_attention_backend="SAGE_ATTN")
assert isinstance(config.diffusion_attention_config, AttentionConfig)
diff --git a/tests/diffusion/model_loader/test_hub_prefetch.py b/tests/diffusion/model_loader/test_hub_prefetch.py
index 94170edcc..b17189539 100644
--- a/tests/diffusion/model_loader/test_hub_prefetch.py
+++ b/tests/diffusion/model_loader/test_hub_prefetch.py
@@ -3,21 +3,21 @@
import contextlib
-import huggingface_hub
import pytest
+from tests.helpers.mock import patch_hf_snapshot_download
from vllm_omni.diffusion.model_loader import hub_prefetch
pytestmark = [pytest.mark.core_model, pytest.mark.diffusion, pytest.mark.cpu]
-def test_prefetch_subfolders_propagates_revision(monkeypatch):
+def test_prefetch_subfolders_propagates_revision(monkeypatch, tmp_path):
calls = []
- def fake_snapshot_download(self, **kwargs):
+ def fake_snapshot_download(**kwargs):
calls.append(kwargs)
- monkeypatch.setattr(huggingface_hub.HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
monkeypatch.setattr(hub_prefetch, "_repo_prefetch_lock", lambda _model: contextlib.nullcontext())
hub_prefetch.prefetch_subfolders(
diff --git a/tests/diffusion/models/hunyuan_image3/test_hunyuan_image3_it2i_multi_image.py b/tests/diffusion/models/hunyuan_image3/test_hunyuan_image3_it2i_multi_image.py
index 1e0fd1590..14a854a7a 100644
--- a/tests/diffusion/models/hunyuan_image3/test_hunyuan_image3_it2i_multi_image.py
+++ b/tests/diffusion/models/hunyuan_image3/test_hunyuan_image3_it2i_multi_image.py
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
"""Multi-image input regression for HunyuanImage3 IT2I prompt construction.
The official HunyuanImage-3.0-Instruct supports up to 3 reference images
@@ -41,7 +41,7 @@ pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
class FakeTokenizer:
- """Recording fake tokenizer mirroring the one in test_prompt_utils.
+ """Recording fake tokenizer mirroring the one in test_hunyuan_image3_prompt_utils.
Special token ids: `<|startoftext|>`=1, `
`=2, ``=3,
``=4. encode() returns one id per character starting at
diff --git a/tests/diffusion/models/hunyuan_image3/test_prompt_utils.py b/tests/diffusion/models/hunyuan_image3/test_hunyuan_image3_prompt_utils.py
similarity index 99%
rename from tests/diffusion/models/hunyuan_image3/test_prompt_utils.py
rename to tests/diffusion/models/hunyuan_image3/test_hunyuan_image3_prompt_utils.py
index 7a467e359..a2be63fd2 100644
--- a/tests/diffusion/models/hunyuan_image3/test_prompt_utils.py
+++ b/tests/diffusion/models/hunyuan_image3/test_hunyuan_image3_prompt_utils.py
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
from __future__ import annotations
import ast
diff --git a/tests/diffusion/models/magi2/test_pipeline_magi2.py b/tests/diffusion/models/magi2/test_pipeline_magi2.py
index 2cda7e66e..4e6057457 100644
--- a/tests/diffusion/models/magi2/test_pipeline_magi2.py
+++ b/tests/diffusion/models/magi2/test_pipeline_magi2.py
@@ -171,7 +171,7 @@ def test_huggingface_url_resolves_pinned_snapshot(tmp_path, monkeypatch):
else pytest.fail("unexpected snapshot request")
)
monkeypatch.setattr(
- "vllm.transformers_utils.repo_utils.hf_api",
+ "vllm_omni.transformers_utils.repo_utils.hf_api",
lambda: api,
)
assert _resolve_checkpoint_root(
diff --git a/tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py b/tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py
index 3beda5acc..dd54f00ae 100644
--- a/tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py
+++ b/tests/diffusion/models/minimax_h3/test_minimax_h3_quantization_quality.py
@@ -16,6 +16,7 @@ from tests.diffusion.quantization.test_quantization_quality import (
_maybe_save_output,
)
from tests.helpers.mark import hardware_marks
+from tests.helpers.mock import patch_hf_snapshot_download
_MINIMAX_H3_REPO = "MiniMaxAI/MiniMax-H3"
_MINIMAX_H3_REVISION = "48d93ede732756e404a3b1b2f3b3a9b5a22f6cfc"
@@ -258,13 +259,13 @@ def test_resolve_fl2va_model_ref(tmp_path, monkeypatch):
fl2va_root.mkdir()
(fl2va_root / "model_index.json").write_text("{}", encoding="utf-8")
- def fake_snapshot_download(self, *, repo_id, revision, allow_patterns):
+ def fake_snapshot_download(*, repo_id, revision, allow_patterns):
assert repo_id == _MINIMAX_H3_REPO
assert revision == _MINIMAX_H3_REVISION
assert allow_patterns == ["FL2VA/**"]
return str(tmp_path)
- monkeypatch.setattr("huggingface_hub.HfApi.snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert _resolve_fl2va_model_ref() == str(fl2va_root)
diff --git a/tests/e2e/accuracy/ltx/test_ltx25_official_similarity.py b/tests/e2e/accuracy/ltx/test_ltx25_official_similarity.py
index c8ce29c37..ba39fb204 100644
--- a/tests/e2e/accuracy/ltx/test_ltx25_official_similarity.py
+++ b/tests/e2e/accuracy/ltx/test_ltx25_official_similarity.py
@@ -32,7 +32,6 @@ from huggingface_hub import hf_hub_download, snapshot_download
from torchmetrics.image import PeakSignalNoiseRatio, StructuralSimilarityIndexMeasure
from tests.e2e.accuracy.helpers import reset_artifact_dir
-from tests.helpers import skip_if_gated_repo_inaccessible
from tests.helpers.mark import hardware_test
OFFICIAL_REPOSITORY = "https://github.com/Lightricks/LTX-2.git"
@@ -303,32 +302,6 @@ def _resolve_ltx25_image() -> Path:
)
-def _require_ltx25_model_access() -> None:
- configured_omni_model = os.environ.get("VLLM_TEST_LTX25_MODEL")
- if not (configured_omni_model and Path(configured_omni_model).exists()):
- omni_model = configured_omni_model or LTX25_OMNI_MODEL_ID
- omni_revision = os.environ.get("VLLM_TEST_LTX25_MODEL_REVISION")
- if omni_revision is None and omni_model == LTX25_OMNI_MODEL_ID:
- omni_revision = LTX25_OMNI_MODEL_REVISION
- skip_if_gated_repo_inaccessible(
- omni_model,
- revision=omni_revision,
- filename="model_index.json",
- )
-
- configured_official_model = os.environ.get("VLLM_TEST_LTX25_OFFICIAL_MODEL")
- if not (configured_official_model and Path(configured_official_model).exists()):
- official_model = configured_official_model or LTX25_OFFICIAL_MODEL_ID
- official_revision = os.environ.get("VLLM_TEST_LTX25_OFFICIAL_MODEL_REVISION")
- if official_revision is None and official_model == LTX25_OFFICIAL_MODEL_ID:
- official_revision = LTX25_OFFICIAL_MODEL_REVISION
- skip_if_gated_repo_inaccessible(
- official_model,
- revision=official_revision,
- filename=LTX25_OFFICIAL_COMMON_FILES["text_encoder"],
- )
-
-
def _ltx25_request(image: Path | None = None) -> dict[str, object]:
request: dict[str, object] = {
"prompt": LTX25_PROMPT,
@@ -475,7 +448,6 @@ def _assert_strict_similarity(
@pytest.mark.parametrize("task", ["t2v", "i2v"])
def test_ltx25_distilled_two_stage_matches_official(accuracy_artifact_root: Path, task: str) -> None:
"""Compare Omni with official canonical DiffVAE and matching connector weights."""
- _require_ltx25_model_access()
artifact_parent = accuracy_artifact_root / "ltx_official"
output_root = reset_artifact_dir(artifact_parent / f"ltx2_5_distilled_{task}")
official_root, official_revision = _ltx25_official_source(artifact_parent)
@@ -600,7 +572,6 @@ def test_ltx25_distilled_two_stage_matches_official(accuracy_artifact_root: Path
@pytest.mark.parametrize("pipeline_mode", ["full_one_stage", "full_two_stage"])
def test_ltx25_full_matches_official(accuracy_artifact_root: Path, task: str, pipeline_mode: str) -> None:
"""Compare raw official Full/SFT and DiffVAE weights with Omni."""
- _require_ltx25_model_access()
artifact_parent = accuracy_artifact_root / "ltx_official"
output_root = reset_artifact_dir(artifact_parent / f"ltx2_5_{pipeline_mode}_{task}")
model_class_name = {
diff --git a/tests/e2e/offline_inference/test_hunyuanimage3.py b/tests/e2e/offline_inference/test_hunyuanimage3.py
index 21bfe9b39..ab1bb5701 100644
--- a/tests/e2e/offline_inference/test_hunyuanimage3.py
+++ b/tests/e2e/offline_inference/test_hunyuanimage3.py
@@ -558,7 +558,7 @@ def test_shared_script_ar_path_reaches_generation(
# safe against MODEL_NAME's base checkpoint missing the Instruct-only
# / tokens. Wiring it here exercises the
# real production path (get_ar_tokenizer_validator via the registry),
- # not just the isolated fake-tokenizer coverage in test_prompt_utils.py
+ # not just the isolated fake-tokenizer coverage in test_hunyuan_image3_prompt_utils.py
# / test_shared_script_ar_integration.py.
validate_tokenizer=get_ar_tokenizer_validator(model_class_name),
)
diff --git a/tests/e2e/online_serving/test_ltx25.py b/tests/e2e/online_serving/test_ltx25.py
index 4975abcc0..400210a7d 100644
--- a/tests/e2e/online_serving/test_ltx25.py
+++ b/tests/e2e/online_serving/test_ltx25.py
@@ -7,7 +7,6 @@ import os
import pytest
-from tests.helpers import skip_if_gated_repo_inaccessible
from tests.helpers.mark import hardware_marks
from tests.helpers.media import generate_synthetic_image
from tests.helpers.runtime import OmniServer, OmniServerParams, OpenAIClientHandler
@@ -24,16 +23,6 @@ pytestmark = [pytest.mark.diffusion, pytest.mark.slow]
SINGLE_CARD_MARKS = hardware_marks(res={"cuda": "H100"})
-@pytest.fixture(scope="module", autouse=True)
-def require_ltx25_model_access() -> None:
- if not os.path.isdir(MODEL):
- skip_if_gated_repo_inaccessible(
- MODEL,
- revision=MODEL_REVISION or None,
- filename="model_index.json",
- )
-
-
def _server(model_class_name: str) -> OmniServerParams:
return OmniServerParams(
model=MODEL,
diff --git a/tests/e2e/online_serving/test_stable_audio_online_expansion.py b/tests/e2e/online_serving/test_stable_audio_online_expansion.py
index fbd6bdbfd..beb51f7c9 100644
--- a/tests/e2e/online_serving/test_stable_audio_online_expansion.py
+++ b/tests/e2e/online_serving/test_stable_audio_online_expansion.py
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
"""
E2E online serving test for Stable Audio Open text-to-audio diffusion.
@@ -11,7 +11,6 @@ import os
import pytest
-from tests.helpers import skip_if_gated_repo_inaccessible
from tests.helpers.mark import hardware_marks
from tests.helpers.runtime import OmniServer, OmniServerParams, OpenAIClientHandler
@@ -32,17 +31,10 @@ def _stable_audio_server_cases(model: str):
]
-@pytest.fixture
-def _require_stable_audio_access() -> None:
- """Skip cleanly (before the server boots) if the gated checkpoint is inaccessible."""
- skip_if_gated_repo_inaccessible(STABLE_AUDIO_TEST_MODEL)
-
-
@pytest.mark.slow
@pytest.mark.diffusion
@pytest.mark.parametrize("omni_server", _stable_audio_server_cases(STABLE_AUDIO_TEST_MODEL), indirect=True)
def test_stable_audio_t2a_online(
- _require_stable_audio_access: None,
omni_server: OmniServer,
openai_client: OpenAIClientHandler,
) -> None:
diff --git a/tests/engine/test_arg_utils.py b/tests/engine/test_arg_utils.py
index 3b0192a79..142affab7 100644
--- a/tests/engine/test_arg_utils.py
+++ b/tests/engine/test_arg_utils.py
@@ -22,6 +22,7 @@ from pydantic import ValidationError
from transformers import PretrainedConfig, Qwen3OmniMoeConfig
from vllm.engine.arg_utils import EngineArgs
+from tests.helpers.mock import patch_hf_snapshot_download
from vllm_omni.config.model import OmniModelConfig
from vllm_omni.engine.arg_utils import OmniEngineArgs
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
@@ -296,7 +297,7 @@ def test_remote_tokenizer_subfolder_download_does_not_report_failure(tmp_path, m
baseline_config = Mock()
warning = mocker.patch("vllm_omni.engine.arg_utils.logger.warning")
- monkeypatch.setattr("huggingface_hub.HfApi.snapshot_download", lambda *args, **kwargs: str(tmp_path))
+ patch_hf_snapshot_download(monkeypatch, lambda *args, **kwargs: str(tmp_path), hf_home=tmp_path)
monkeypatch.setattr(OmniEngineArgs, "_patch_empty_hf_config", lambda *args, **kwargs: None)
monkeypatch.setattr(EngineArgs, "create_model_config", lambda _self: baseline_config)
monkeypatch.setattr(
diff --git a/tests/engine/test_async_omni_engine_stage_init.py b/tests/engine/test_async_omni_engine_stage_init.py
index ec897bd7d..a8255f81a 100644
--- a/tests/engine/test_async_omni_engine_stage_init.py
+++ b/tests/engine/test_async_omni_engine_stage_init.py
@@ -14,6 +14,7 @@ import pytest
from omegaconf import OmegaConf
from vllm.v1.engine.utils import EngineZmqAddresses
+from tests.helpers.mock import patch_hf_snapshot_download
from vllm_omni.config.omni_config import OmniStageRuntimeConfig
from vllm_omni.diffusion.data import AttentionConfig
from vllm_omni.engine import omni_engine_base as async_omni_engine_module
@@ -1566,22 +1567,20 @@ def test_build_engine_args_pulls_stage_subdirs_missing_from_cached_snapshot(monk
never materialized. Stage init must fetch exactly those subfolders instead
of joining onto a path that exists nowhere.
"""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
snapshot = tmp_path / "snapshots" / "deadbeef"
_make_snapshot(snapshot, ["tokenizer"])
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
if kwargs.get("local_files_only"):
return str(snapshot)
_make_snapshot(snapshot, ["language_model"])
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1601,18 +1600,16 @@ def test_build_engine_args_pulls_stage_subdirs_missing_from_cached_snapshot(monk
def test_build_engine_args_skips_hub_call_when_cached_snapshot_is_complete(monkeypatch, tmp_path):
"""A warm cache stays offline-friendly: no outgoing Hub request."""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
snapshot = tmp_path / "snapshots" / "deadbeef"
_make_snapshot(snapshot, ["language_model", "tokenizer"])
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
assert kwargs.get("local_files_only"), "warm cache must not reach the Hub"
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1633,8 +1630,6 @@ def test_build_engine_args_redownloads_a_partial_subdir(monkeypatch, tmp_path):
that local path leaves vLLM's loader without any fallback for the missing
weights.
"""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
snapshot = tmp_path / "snapshots" / "deadbeef"
@@ -1644,14 +1639,14 @@ def test_build_engine_args_redownloads_a_partial_subdir(monkeypatch, tmp_path):
_make_snapshot(snapshot, ["tokenizer"])
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
if kwargs.get("local_files_only"):
return str(snapshot)
_make_snapshot(snapshot, ["language_model"])
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1672,8 +1667,6 @@ def test_build_engine_args_redownloads_when_index_lists_missing_shards(monkeypat
The index downloads early; accepting it as proof of weights converts the
Hub ID into a local path vLLM cannot fetch the remaining shards for.
"""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
snapshot = tmp_path / "snapshots" / "deadbeef"
@@ -1693,13 +1686,13 @@ def test_build_engine_args_redownloads_when_index_lists_missing_shards(monkeypat
_make_snapshot(snapshot, ["tokenizer"])
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
if not kwargs.get("local_files_only"):
(partial / "model-00002-of-00002.safetensors").write_text("x")
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1716,8 +1709,6 @@ def test_build_engine_args_redownloads_when_index_lists_missing_shards(monkeypat
def test_build_engine_args_redownloads_shards_without_their_index(monkeypatch, tmp_path):
"""Shard-named weights always ship an index; one without it is partial."""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
snapshot = tmp_path / "snapshots" / "deadbeef"
@@ -1727,7 +1718,7 @@ def test_build_engine_args_redownloads_shards_without_their_index(monkeypatch, t
_make_snapshot(snapshot, ["tokenizer"])
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
if not kwargs.get("local_files_only"):
shards = {f"w{i}.weight": f"model-0000{i}-of-00004.safetensors" for i in range(1, 5)}
@@ -1736,7 +1727,7 @@ def test_build_engine_args_redownloads_shards_without_their_index(monkeypatch, t
(partial / shard).write_text("x")
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1752,8 +1743,6 @@ def test_build_engine_args_redownloads_shards_without_their_index(monkeypatch, t
def test_build_engine_args_redownloads_a_tokenizer_folder_without_vocabulary(monkeypatch, tmp_path):
"""Templates and configs download first; alone they are not a tokenizer."""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
snapshot = tmp_path / "snapshots" / "deadbeef"
@@ -1763,13 +1752,13 @@ def test_build_engine_args_redownloads_a_tokenizer_folder_without_vocabulary(mon
(partial / "chat_template.jinja").write_text("{{ messages }}")
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
if not kwargs.get("local_files_only"):
_make_snapshot(snapshot, ["tokenizer"])
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1787,19 +1776,17 @@ def test_build_engine_args_redownloads_a_tokenizer_folder_without_vocabulary(mon
def test_build_engine_args_forwards_revision_and_download_dir(monkeypatch, tmp_path):
"""revision/download_dir must shape snapshot selection (they cannot be
corrected downstream once the repo ID is a local path)."""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
snapshot = tmp_path / "snapshots" / "pinned"
_make_snapshot(snapshot, ["language_model", "tokenizer"])
seen = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
seen.append(kwargs)
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1824,8 +1811,6 @@ def test_build_engine_args_forwards_revision_and_download_dir(monkeypatch, tmp_p
def test_build_engine_args_resolves_tokenizer_revision_separately(monkeypatch, tmp_path):
"""A tokenizer pinned to a different revision resolves against its own snapshot."""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
model_snapshot = tmp_path / "snapshots" / "model-rev"
@@ -1833,12 +1818,12 @@ def test_build_engine_args_resolves_tokenizer_revision_separately(monkeypatch, t
tokenizer_snapshot = tmp_path / "snapshots" / "tok-rev"
_make_snapshot(tokenizer_snapshot, ["tokenizer"])
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
if kwargs.get("revision") == "tok-rev":
return str(tokenizer_snapshot)
return str(model_snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1861,8 +1846,6 @@ def test_build_engine_args_resolves_tokenizer_revision_separately(monkeypatch, t
def test_build_engine_args_resolves_root_tokenizer_revision_separately(monkeypatch, tmp_path):
"""An empty tokenizer_subdir targets the snapshot root and still honors
its own revision."""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
model_snapshot = tmp_path / "snapshots" / "model-rev"
@@ -1875,12 +1858,12 @@ def test_build_engine_args_resolves_root_tokenizer_revision_separately(monkeypat
tokenizer_snapshot.mkdir(parents=True, exist_ok=True)
(tokenizer_snapshot / _SUBDIR_ARTIFACT["tokenizer"]).write_text("x")
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
if kwargs.get("revision") == "tok-rev":
return str(tokenizer_snapshot)
return str(model_snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1902,19 +1885,17 @@ def test_build_engine_args_resolves_root_tokenizer_revision_separately(monkeypat
def test_build_engine_args_fails_closed_when_subdir_cannot_be_downloaded(monkeypatch, tmp_path):
"""An undownloadable subfolder raises here instead of reaching HuggingFace."""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
snapshot = tmp_path / "snapshots" / "deadbeef"
_make_snapshot(snapshot, ["tokenizer"])
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
if kwargs.get("local_files_only"):
return str(snapshot)
raise OSError("offline")
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
@@ -1927,16 +1908,14 @@ def test_build_engine_args_fails_closed_when_subdir_cannot_be_downloaded(monkeyp
build_engine_args_dict(stage_cfg, "MiniMaxAI/MiniMax-Music3")
-def test_build_engine_args_fails_closed_on_cold_cache_instead_of_joining_repo_id(monkeypatch):
+def test_build_engine_args_fails_closed_on_cold_cache_instead_of_joining_repo_id(monkeypatch, tmp_path):
"""With nothing cached, the stage must not join a subdir onto the repo id."""
- from huggingface_hub import HfApi
-
from vllm_omni.engine.stage_init_utils import build_engine_args_dict
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
raise OSError("offline")
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
stage_cfg = types.SimpleNamespace(
stage_id=0,
diff --git a/tests/helpers/__init__.py b/tests/helpers/__init__.py
index 9120e183f..af7977906 100644
--- a/tests/helpers/__init__.py
+++ b/tests/helpers/__init__.py
@@ -3,49 +3,10 @@
"""Shared, importable test helper utilities.
-Submodules (``assertions``, ``clean``, ``client``, ``media``, ``runtime``, …) are imported
+Submodules (``assertions``, ``clean``, ``client``, ``media``, ``mock``, ``runtime``, …) are imported
explicitly by callers. Unit tests for these helpers live under ``tests/``.
Avoid star-importing everything here: that ran before refactor only inside the
old monolithic ``conftest``; a greedy ``__init__`` changes import order and can
affect in-process Omni (``OmniRunner`` / offline e2e) vs subprocess-based
``OmniServer`` tests.
"""
-
-from __future__ import annotations
-
-
-def skip_if_gated_repo_inaccessible(
- repo_id: str,
- *,
- revision: str | None = None,
- filename: str = "config.json",
-) -> None:
- """Skip the test if a gated HuggingFace repo is not accessible.
-
- Tries to download ``filename`` via ``hf_hub_download``, which performs an
- actual file-access check (unlike ``HfApi().model_info()``
- that only checks metadata). If the token has metadata access but not
- file-download access, ``hf_hub_download`` will raise ``GatedRepoError``
- and we skip cleanly.
- """
- try:
- from huggingface_hub.errors import GatedRepoError, RepositoryNotFoundError
-
- from vllm_omni.transformers_utils.repo_utils import hf_api
- except Exception:
- return
- try:
- hf_api().hf_hub_download(repo_id=repo_id, filename=filename, revision=revision)
- except GatedRepoError as exc:
- import pytest
-
- pytest.skip(
- f"Skipping: gated HF repo {repo_id!r} inaccessible to the current "
- f"HF_TOKEN ({exc}). See docs/contributing/ci/hf_credentials.md."
- )
- except RepositoryNotFoundError as exc:
- import pytest
-
- pytest.skip(f"Skipping: HF repo {repo_id!r} not found ({exc}).")
- except Exception:
- return
diff --git a/tests/helpers/mock.py b/tests/helpers/mock.py
new file mode 100644
index 000000000..47ce8f79d
--- /dev/null
+++ b/tests/helpers/mock.py
@@ -0,0 +1,51 @@
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
+"""Shared pytest mocks for unit tests.
+
+Add reusable ``monkeypatch`` helpers here instead of a new module per target.
+Callers import explicitly: ``from tests.helpers.mock import ...``.
+"""
+
+from __future__ import annotations
+
+from collections.abc import Callable
+from os import PathLike
+from pathlib import Path
+from typing import Any
+
+
+def patch_hf_snapshot_download(
+ monkeypatch: Any,
+ fake: Callable[..., Any],
+ *,
+ hf_home: str | PathLike[str] | None = None,
+) -> None:
+ """Replace ``snapshot_download`` on the cached ``hf_api()`` singleton.
+
+ Production code calls ``hf_api().snapshot_download``. Patching
+ ``huggingface_hub.HfApi.snapshot_download`` misses that instance, so
+ weekly CPU jobs talk to the real Hub / ``HF_HOME`` cache.
+
+ ``fake`` is installed on the instance, so it is called without ``self``.
+
+ Pass ``hf_home`` (typically pytest ``tmp_path``) to isolate the Hub cache.
+ ``repo_utils`` imports ``huggingface_hub`` before tests can ``setenv``, so
+ ``constants.HF_HUB_CACHE`` is already frozen from the process environment
+ (weekly: ``/fsx/hf_cache``). Downloads without ``cache_dir`` use that
+ constant, not ``HF_HOME``. Patch both the env and the imported constants
+ so a missed instance mock cannot read the builder cache.
+ """
+ from huggingface_hub import constants as hub_constants
+
+ from vllm_omni.transformers_utils import repo_utils
+
+ monkeypatch.setattr(repo_utils.hf_api(), "snapshot_download", fake)
+ if hf_home is not None:
+ hf_home_str = str(hf_home)
+ hub_cache = str(Path(hf_home_str) / "hub")
+ monkeypatch.setenv("HF_HOME", hf_home_str)
+ monkeypatch.setenv("HF_HUB_CACHE", hub_cache)
+ monkeypatch.setattr(hub_constants, "HF_HOME", hf_home_str)
+ monkeypatch.setattr(hub_constants, "default_cache_path", hub_cache)
+ monkeypatch.setattr(hub_constants, "HF_HUB_CACHE", hub_cache)
+ monkeypatch.setattr(hub_constants, "HUGGINGFACE_HUB_CACHE", hub_cache)
diff --git a/tests/helpers/tests/test_mock.py b/tests/helpers/tests/test_mock.py
new file mode 100644
index 000000000..f30187395
--- /dev/null
+++ b/tests/helpers/tests/test_mock.py
@@ -0,0 +1,93 @@
+# SPDX-License-Identifier: Apache-2.0
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
+
+import os
+from pathlib import Path
+
+import pytest
+
+from tests.helpers.mock import patch_hf_snapshot_download
+
+pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
+
+
+def test_patch_hf_snapshot_download_binds_instance_without_self(monkeypatch):
+ from vllm_omni.transformers_utils.repo_utils import hf_api
+
+ calls: list[tuple[tuple[object, ...], dict[str, object]]] = []
+
+ def fake(*args, **kwargs):
+ calls.append((args, kwargs))
+ return "ok"
+
+ patch_hf_snapshot_download(monkeypatch, fake)
+ assert hf_api().snapshot_download("org/model", revision="abc") == "ok"
+ assert calls == [(("org/model",), {"revision": "abc"})]
+
+
+def test_patch_hf_snapshot_download_sets_hf_home(monkeypatch, tmp_path):
+ hf_home = tmp_path / "hf-home"
+ patch_hf_snapshot_download(monkeypatch, lambda *args, **kwargs: "ok", hf_home=hf_home)
+ assert os.environ["HF_HOME"] == str(hf_home)
+ from huggingface_hub import constants
+
+ assert constants.HF_HOME == str(hf_home)
+ assert constants.HF_HUB_CACHE == str(hf_home / "hub")
+ assert constants.HUGGINGFACE_HUB_CACHE == str(hf_home / "hub")
+ assert constants.default_cache_path == str(hf_home / "hub")
+
+
+def test_patch_hf_snapshot_download_leaves_hf_home_when_omitted(monkeypatch):
+ from huggingface_hub import constants
+
+ monkeypatch.setenv("HF_HOME", "/original-hf-home")
+ original_cache = constants.HF_HUB_CACHE
+ original_default = constants.default_cache_path
+ patch_hf_snapshot_download(monkeypatch, lambda *args, **kwargs: "ok")
+ assert os.environ["HF_HOME"] == "/original-hf-home"
+ assert constants.HF_HUB_CACHE == original_cache
+ assert constants.default_cache_path == original_default
+
+
+def test_patch_hf_snapshot_download_overrides_preimported_hub_cache(monkeypatch, tmp_path):
+ """Hub is imported before the helper; ``HF_HOME`` env alone does not move the cache.
+
+ ``repo_utils`` / ``huggingface_hub`` compute ``constants.HF_HUB_CACHE`` at
+ import time. Weekly CPU already imported them with ``HF_HOME=/fsx/hf_cache``.
+ A download that bypasses the instance mock uses that constant, not the env.
+ """
+ from huggingface_hub import constants, snapshot_download
+ from huggingface_hub.errors import LocalEntryNotFoundError
+
+ from vllm_omni.transformers_utils.repo_utils import hf_api
+
+ hf_api()
+
+ poisoned_home = tmp_path / "fsx-hf-cache"
+ poisoned_cache = poisoned_home / "hub"
+ repo_dir = poisoned_cache / "models--org--model"
+ (repo_dir / "refs").mkdir(parents=True)
+ (repo_dir / "refs" / "main").write_text("deadbeef", encoding="utf-8")
+ snapshot = repo_dir / "snapshots" / "deadbeef"
+ snapshot.mkdir(parents=True)
+ (snapshot / "config.json").write_text("{}", encoding="utf-8")
+
+ monkeypatch.setenv("HF_HOME", str(poisoned_home))
+ monkeypatch.setattr(constants, "HF_HOME", str(poisoned_home))
+ monkeypatch.setattr(constants, "HF_HUB_CACHE", str(poisoned_cache))
+ monkeypatch.setattr(constants, "HUGGINGFACE_HUB_CACHE", str(poisoned_cache))
+
+ found = snapshot_download("org/model", local_files_only=True)
+ assert Path(found).resolve() == snapshot.resolve()
+
+ isolated = tmp_path / "isolated-hf-home"
+ patch_hf_snapshot_download(monkeypatch, lambda *args, **kwargs: "mocked", hf_home=isolated)
+
+ assert os.environ["HF_HOME"] == str(isolated)
+ assert os.environ["HF_HUB_CACHE"] == str(isolated / "hub")
+ assert constants.HF_HOME == str(isolated)
+ assert constants.HF_HUB_CACHE == str(isolated / "hub")
+ assert constants.HUGGINGFACE_HUB_CACHE == str(isolated / "hub")
+ assert constants.default_cache_path == str(isolated / "hub")
+ with pytest.raises(LocalEntryNotFoundError):
+ snapshot_download("org/model", local_files_only=True)
diff --git a/tests/model_executor/models/fish_speech/test_prompt_utils.py b/tests/model_executor/models/fish_speech/test_fish_speech_prompt_utils.py
similarity index 100%
rename from tests/model_executor/models/fish_speech/test_prompt_utils.py
rename to tests/model_executor/models/fish_speech/test_fish_speech_prompt_utils.py
diff --git a/tests/model_executor/models/indextts2/test_prompt_utils.py b/tests/model_executor/models/indextts2/test_indextts2_prompt_utils.py
similarity index 98%
rename from tests/model_executor/models/indextts2/test_prompt_utils.py
rename to tests/model_executor/models/indextts2/test_indextts2_prompt_utils.py
index fe73e69a5..29c86567f 100644
--- a/tests/model_executor/models/indextts2/test_prompt_utils.py
+++ b/tests/model_executor/models/indextts2/test_indextts2_prompt_utils.py
@@ -1,5 +1,5 @@
# SPDX-License-Identifier: Apache-2.0
-# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
+# SPDX-FileCopyrightText: Copyright contributors to the vLLM-Omni project
import importlib.util
from pathlib import Path
diff --git a/tests/model_executor/models/minicpmo_4_5/test_code2wav_model_dir.py b/tests/model_executor/models/minicpmo_4_5/test_code2wav_model_dir.py
index 8d5aeade6..fced5ae46 100644
--- a/tests/model_executor/models/minicpmo_4_5/test_code2wav_model_dir.py
+++ b/tests/model_executor/models/minicpmo_4_5/test_code2wav_model_dir.py
@@ -12,9 +12,9 @@ from __future__ import annotations
from types import SimpleNamespace
-import huggingface_hub
import pytest
+from tests.helpers.mock import patch_hf_snapshot_download
from vllm_omni.model_executor.models.minicpmo_4_5.minicpmo_4_5_code2wav import (
MiniCPMO45Code2Wav,
_resolve_model_dir,
@@ -23,28 +23,28 @@ from vllm_omni.model_executor.models.minicpmo_4_5.minicpmo_4_5_code2wav import (
pytestmark = [pytest.mark.core_model, pytest.mark.cpu]
-def _no_hub(monkeypatch):
+def _no_hub(monkeypatch, tmp_path):
def _fail(*args, **kwargs): # pragma: no cover - must not be reached
raise AssertionError("snapshot_download must not be called here")
- monkeypatch.setattr(huggingface_hub.HfApi, "snapshot_download", _fail)
+ patch_hf_snapshot_download(monkeypatch, _fail, hf_home=tmp_path)
def test_local_directory_is_returned_unchanged(tmp_path, monkeypatch):
- _no_hub(monkeypatch)
+ _no_hub(monkeypatch, tmp_path)
assert _resolve_model_dir(str(tmp_path)) == str(tmp_path)
def test_repo_id_resolves_via_snapshot_download(tmp_path, monkeypatch):
calls = {}
- def _fake_snapshot_download(self, model_ref, revision=None, allow_patterns=None):
+ def _fake_snapshot_download(model_ref, revision=None, allow_patterns=None):
calls["model_ref"] = model_ref
calls["revision"] = revision
calls["allow_patterns"] = allow_patterns
return str(tmp_path / "snapshot")
- monkeypatch.setattr(huggingface_hub.HfApi, "snapshot_download", _fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, _fake_snapshot_download, hf_home=tmp_path)
resolved = _resolve_model_dir("openbmb/MiniCPM-o-4_5", revision="abc123")
assert resolved == str(tmp_path / "snapshot")
assert calls["model_ref"] == "openbmb/MiniCPM-o-4_5"
@@ -52,18 +52,18 @@ def test_repo_id_resolves_via_snapshot_download(tmp_path, monkeypatch):
assert calls["allow_patterns"] == ["assets/*"]
-def test_snapshot_download_failure_propagates(monkeypatch):
+def test_snapshot_download_failure_propagates(monkeypatch, tmp_path):
def _raise(*args, **kwargs):
raise FileNotFoundError("offline and not cached")
- monkeypatch.setattr(huggingface_hub.HfApi, "snapshot_download", _raise)
+ patch_hf_snapshot_download(monkeypatch, _raise, hf_home=tmp_path)
with pytest.raises(FileNotFoundError):
_resolve_model_dir("openbmb/MiniCPM-o-4_5")
-def test_init_with_fake_path_does_not_resolve(monkeypatch):
+def test_init_with_fake_path_does_not_resolve(monkeypatch, tmp_path):
"""Mirrors the CPU-test construction: fake model path, no ``revision``."""
- _no_hub(monkeypatch)
+ _no_hub(monkeypatch, tmp_path)
config = SimpleNamespace(
model_config=SimpleNamespace(
model="/fake/model",
@@ -75,8 +75,8 @@ def test_init_with_fake_path_does_not_resolve(monkeypatch):
assert model._default_prompt_wav == "/fake/model/assets/HT_ref_audio.wav"
-def test_default_prompt_wav_follows_resolved_model_path(monkeypatch):
- _no_hub(monkeypatch)
+def test_default_prompt_wav_follows_resolved_model_path(monkeypatch, tmp_path):
+ _no_hub(monkeypatch, tmp_path)
config = SimpleNamespace(
model_config=SimpleNamespace(
model="openbmb/MiniCPM-o-4_5",
diff --git a/tests/model_executor/models/test_minimax_music3_repo_root.py b/tests/model_executor/models/test_minimax_music3_repo_root.py
index 182635ab7..6cac9d559 100644
--- a/tests/model_executor/models/test_minimax_music3_repo_root.py
+++ b/tests/model_executor/models/test_minimax_music3_repo_root.py
@@ -12,6 +12,7 @@ from __future__ import annotations
import pytest
+from tests.helpers.mock import patch_hf_snapshot_download
from vllm_omni.model_executor.models.minimax_music3.weights import (
_COMPONENT_WEIGHT_NAME,
_REQUIRED_COMPONENTS,
@@ -47,16 +48,14 @@ def test_resolve_repo_root_walks_up_from_a_model_subdir(tmp_path):
def test_resolve_repo_root_resolves_a_hub_id_to_a_local_snapshot(monkeypatch, tmp_path):
"""A hub id must resolve through the cache, not against the working directory."""
- from huggingface_hub import HfApi
-
root = _make_root(tmp_path / "snapshots" / "deadbeef")
seen = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
seen.append(kwargs)
return str(root)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root("MiniMaxAI/MiniMax-Music3") == root
# Cache-first, and only the component folders.
@@ -66,18 +65,16 @@ def test_resolve_repo_root_resolves_a_hub_id_to_a_local_snapshot(monkeypatch, tm
def test_resolve_repo_root_falls_back_to_the_hub_when_the_cache_is_incomplete(monkeypatch, tmp_path):
- from huggingface_hub import HfApi
-
root = _make_root(tmp_path / "snapshots" / "deadbeef")
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
if kwargs.get("local_files_only"):
raise OSError("incomplete snapshot")
return str(root)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root("MiniMaxAI/MiniMax-Music3") == root
assert len(calls) == 2
@@ -89,19 +86,17 @@ def test_resolve_repo_root_retries_online_when_the_local_lookup_returns_a_partia
A returned partial root must fall through to the online call all the same,
or startup fails without ever consulting the Hub.
"""
- from huggingface_hub import HfApi
-
snapshot = tmp_path / "models--MiniMaxAI--MiniMax-Music3" / "snapshots" / "deadbeef"
(snapshot / "language_model").mkdir(parents=True)
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
if not kwargs.get("local_files_only"):
_make_root(snapshot)
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root("MiniMaxAI/MiniMax-Music3") == snapshot
assert [bool(call.get("local_files_only")) for call in calls] == [True, False]
@@ -109,32 +104,28 @@ def test_resolve_repo_root_retries_online_when_the_local_lookup_returns_a_partia
def test_resolve_repo_root_redownloads_weightless_marker_dirs(monkeypatch, tmp_path):
"""Marker folders without their component weights are an interrupted download."""
- from huggingface_hub import HfApi
-
snapshot = tmp_path / "models--MiniMaxAI--MiniMax-Music3" / "snapshots" / "deadbeef"
for marker in _ROOT_MARKERS:
(snapshot / marker).mkdir(parents=True)
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
if not kwargs.get("local_files_only"):
_make_root(snapshot)
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root("MiniMaxAI/MiniMax-Music3") == snapshot
assert any(not call.get("local_files_only") for call in calls)
-def test_resolve_repo_root_reports_the_original_reference_when_unresolvable(monkeypatch):
- from huggingface_hub import HfApi
-
- def fake_snapshot_download(self, repo_id, **kwargs):
+def test_resolve_repo_root_reports_the_original_reference_when_unresolvable(monkeypatch, tmp_path):
+ def fake_snapshot_download(repo_id, **kwargs):
raise OSError("offline")
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
with pytest.raises(FileNotFoundError, match="MiniMaxAI/MiniMax-Music3"):
resolve_repo_root("MiniMaxAI/MiniMax-Music3")
@@ -147,19 +138,17 @@ def test_resolve_repo_root_downloads_components_for_a_cold_cache_model_subdir(mo
the marker walk fails although the repo id is recoverable from the cache
layout and one snapshot_download away from working.
"""
- from huggingface_hub import HfApi
-
snapshot = tmp_path / "models--MiniMaxAI--MiniMax-Music3" / "snapshots" / "deadbeef"
(snapshot / "language_model").mkdir(parents=True)
(snapshot / "tokenizer").mkdir()
seen = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
seen.append(repo_id)
_make_root(snapshot)
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root(str(snapshot / "language_model")) == snapshot
assert seen == ["MiniMaxAI/MiniMax-Music3"]
@@ -167,12 +156,11 @@ def test_resolve_repo_root_downloads_components_for_a_cold_cache_model_subdir(mo
def test_resolve_repo_root_does_not_guess_a_repo_id_for_plain_directories(monkeypatch, tmp_path):
"""A directory outside the HF cache has no recoverable repo id."""
- from huggingface_hub import HfApi
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
raise AssertionError("must not reach the Hub for a plain directory")
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
plain = tmp_path / "language_model"
plain.mkdir()
@@ -187,8 +175,6 @@ def test_resolve_repo_root_rejects_a_snapshot_missing_condition_encoder(monkeypa
acoustic stage would still fail, so completeness must cover every required
component rather than the identification markers alone.
"""
- from huggingface_hub import HfApi
-
snapshot = tmp_path / "models--MiniMaxAI--MiniMax-Music3" / "snapshots" / "deadbeef"
for marker in _ROOT_MARKERS:
folder = snapshot / marker
@@ -196,13 +182,13 @@ def test_resolve_repo_root_rejects_a_snapshot_missing_condition_encoder(monkeypa
(folder / _COMPONENT_WEIGHT_NAME).write_bytes(b"x")
repaired = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
if not kwargs.get("local_files_only"):
repaired.append(repo_id)
_make_root(snapshot)
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root(str(snapshot)) == snapshot
assert repaired == ["MiniMaxAI/MiniMax-Music3"]
@@ -210,8 +196,6 @@ def test_resolve_repo_root_rejects_a_snapshot_missing_condition_encoder(monkeypa
def test_resolve_repo_root_rejects_a_partial_shard_run(monkeypatch, tmp_path):
"""One shard of a multi-shard component satisfies a bare glob but cannot load."""
- from huggingface_hub import HfApi
-
stem = _COMPONENT_WEIGHT_NAME.removesuffix(".safetensors")
snapshot = tmp_path / "models--MiniMaxAI--MiniMax-Music3" / "snapshots" / "deadbeef"
for component in _REQUIRED_COMPONENTS:
@@ -223,14 +207,14 @@ def test_resolve_repo_root_rejects_a_partial_shard_run(monkeypatch, tmp_path):
(partial / f"{stem}-00001-of-00003.safetensors").write_bytes(b"x")
repaired = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
if not kwargs.get("local_files_only"):
repaired.append(repo_id)
for index in (2, 3):
(partial / f"{stem}-0000{index}-of-00003.safetensors").write_bytes(b"x")
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root(str(snapshot)) == snapshot
assert repaired == ["MiniMaxAI/MiniMax-Music3"]
@@ -242,17 +226,15 @@ def test_resolve_repo_root_threads_revision_and_download_dir(monkeypatch, tmp_pa
Resolving components against the default branch while the AR backbone is
pinned elsewhere would combine weights from two different commits.
"""
- from huggingface_hub import HfApi
-
snapshot = tmp_path / "snapshot"
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
_make_root(snapshot)
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root("MiniMaxAI/MiniMax-Music3", revision="abc123", download_dir="/tmp/hub-cache") == snapshot
assert calls
@@ -266,18 +248,16 @@ def test_resolve_repo_root_reuses_the_snapshot_revision_from_the_cache_path(monk
Re-resolving the repo id alone would fetch the default branch rather than
the snapshot the caller is already sitting in.
"""
- from huggingface_hub import HfApi
-
snapshot = tmp_path / "models--MiniMaxAI--MiniMax-Music3" / "snapshots" / "cafebabe"
(snapshot / "language_model").mkdir(parents=True)
calls = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
calls.append(kwargs)
_make_root(snapshot)
return str(snapshot)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root(str(snapshot / "language_model")) == snapshot
assert calls
@@ -292,8 +272,6 @@ def test_resolve_repo_root_accepts_shard_names_the_loader_can_read(monkeypatch,
loadable. Judging it incomplete would force a needless re-download and, with
no network, fail on weights that are present and readable.
"""
- from huggingface_hub import HfApi
-
stem = _COMPONENT_WEIGHT_NAME.removesuffix(".safetensors")
root = tmp_path / "snapshot"
for component in _REQUIRED_COMPONENTS:
@@ -303,18 +281,16 @@ def test_resolve_repo_root_accepts_shard_names_the_loader_can_read(monkeypatch,
(unsharded / _COMPONENT_WEIGHT_NAME).unlink()
(unsharded / f"{stem}-fp16.safetensors").write_bytes(b"x")
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
raise AssertionError("must not reach the Hub for readable weights")
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
assert resolve_repo_root(str(root)) == root
def test_resolve_repo_root_still_rejects_a_partial_run_beside_an_extra_file(monkeypatch, tmp_path):
"""An unparsable extra must not mask a genuinely short ``-of-`` run."""
- from huggingface_hub import HfApi
-
stem = _COMPONENT_WEIGHT_NAME.removesuffix(".safetensors")
root = tmp_path / "snapshot"
for component in _REQUIRED_COMPONENTS:
@@ -326,13 +302,13 @@ def test_resolve_repo_root_still_rejects_a_partial_run_beside_an_extra_file(monk
(partial / f"{stem}-extra.safetensors").write_bytes(b"x")
repaired = []
- def fake_snapshot_download(self, repo_id, **kwargs):
+ def fake_snapshot_download(repo_id, **kwargs):
repaired.append(repo_id)
for index in (2, 3):
(partial / f"{stem}-0000{index}-of-00003.safetensors").write_bytes(b"x")
return str(root)
- monkeypatch.setattr(HfApi, "snapshot_download", fake_snapshot_download)
+ patch_hf_snapshot_download(monkeypatch, fake_snapshot_download, hf_home=tmp_path)
with pytest.raises(FileNotFoundError, match="components are incomplete"):
resolve_repo_root(str(root))
diff --git a/vllm_omni/diffusion/model_loader/diffusers_loader.py b/vllm_omni/diffusion/model_loader/diffusers_loader.py
index c47eab7f7..7cbff273c 100644
--- a/vllm_omni/diffusion/model_loader/diffusers_loader.py
+++ b/vllm_omni/diffusion/model_loader/diffusers_loader.py
@@ -25,7 +25,6 @@ from vllm.model_executor.model_loader.weight_utils import (
pt_weights_iterator,
safetensors_weights_iterator,
)
-from vllm.transformers_utils.repo_utils import hf_api
from vllm.utils.import_utils import resolve_obj_by_qualname
from vllm.utils.torch_utils import set_default_torch_dtype
@@ -54,6 +53,7 @@ from vllm_omni.diffusion.offloader.module_collector import ModuleDiscovery
from vllm_omni.diffusion.offloader.offload_plan import get_offload_plan
from vllm_omni.diffusion.registry import initialize_model
from vllm_omni.model_executor.model_loader.weight_utils import download_weights_from_hf_specific
+from vllm_omni.transformers_utils.repo_utils import hf_api
# download_gguf was removed from upstream vLLM (commit 6635279d8).
diff --git a/vllm_omni/diffusion/models/magi2/pipeline_magi2.py b/vllm_omni/diffusion/models/magi2/pipeline_magi2.py
index 910e0d074..52b95fa4c 100644
--- a/vllm_omni/diffusion/models/magi2/pipeline_magi2.py
+++ b/vllm_omni/diffusion/models/magi2/pipeline_magi2.py
@@ -225,7 +225,7 @@ def _resolve_checkpoint_root(model: str, revision: str | None) -> str:
"MAGI-2 expects a local checkpoint directory or the official "
f"model ID {MAGI2_MODEL_ID!r}; got {model!r}."
)
- from vllm.transformers_utils.repo_utils import hf_api
+ from vllm_omni.transformers_utils.repo_utils import hf_api
pinned_revision = revision or MAGI2_MODEL_REVISION
logger.warning(
diff --git a/vllm_omni/model_executor/models/minimax_music3/weights.py b/vllm_omni/model_executor/models/minimax_music3/weights.py
index b019ff461..912395a81 100644
--- a/vllm_omni/model_executor/models/minimax_music3/weights.py
+++ b/vllm_omni/model_executor/models/minimax_music3/weights.py
@@ -119,7 +119,7 @@ def _download_component_snapshot(
components against the default branch and the default cache while the AR
backbone was pinned elsewhere would silently mix weights from two commits.
"""
- from vllm.transformers_utils.repo_utils import hf_api
+ from vllm_omni.transformers_utils.repo_utils import hf_api
kwargs: dict[str, object] = {"allow_patterns": list(_COMPONENT_PATTERNS)}
if revision is not None: