diff --git a/tests/compile/correctness_e2e/test_sequence_parallel.py b/tests/compile/correctness_e2e/test_sequence_parallel.py index e320f5a112..9c9c596198 100644 --- a/tests/compile/correctness_e2e/test_sequence_parallel.py +++ b/tests/compile/correctness_e2e/test_sequence_parallel.py @@ -348,10 +348,14 @@ def test_tp_sp_generation( if use_inductor_graph_partition and not is_torch_equal_or_newer("2.9.0.dev"): pytest.skip("inductor graph partition is only available in PyTorch 2.9+") - # Skip FP8 SP-only test on sm89 (compute capability 8.9) + # Skip FP8 SP-only test on sm89 (compute capability 8.9). + # An unknown capability (None) is left to fail in the test body rather than + # being silently skipped here. + capability = current_platform.get_device_capability() if ( "fp8" in model_id.lower() - and current_platform.get_device_capability() < (9, 0) + and capability is not None + and capability < (9, 0) and (not fuse_gemm_comms) ): pytest.skip("FP8 reduction support begins with sm90 capable devices.") diff --git a/tests/compile/fullgraph/test_full_cudagraph.py b/tests/compile/fullgraph/test_full_cudagraph.py index 95306e2062..c2af7be048 100644 --- a/tests/compile/fullgraph/test_full_cudagraph.py +++ b/tests/compile/fullgraph/test_full_cudagraph.py @@ -9,7 +9,7 @@ import pytest from tests.utils import wait_for_gpu_memory_to_clear from tests.v1.attention.utils import full_cg_backend_configs as backend_configs from vllm import LLM, SamplingParams -from vllm.config import CompilationConfig +from vllm.config import CompilationConfig, CUDAGraphMode from vllm.platforms import current_platform from vllm.utils.torch_utils import is_torch_equal_or_newer from vllm.v1.attention.backends.registry import AttentionBackendEnum @@ -97,7 +97,9 @@ def llm_pair(request): trust_remote_code=True, max_model_len=1024, max_num_seqs=128, - compilation_config=CompilationConfig(cudagraph_mode="PIECEWISE"), + compilation_config=CompilationConfig( + cudagraph_mode=CUDAGraphMode.PIECEWISE + ), generation_config="vllm", seed=42, ) diff --git a/tests/compile/fullgraph/test_full_graph.py b/tests/compile/fullgraph/test_full_graph.py index cc13845480..0f3368c0db 100644 --- a/tests/compile/fullgraph/test_full_graph.py +++ b/tests/compile/fullgraph/test_full_graph.py @@ -75,7 +75,7 @@ def test_full_graph( monkeypatch: pytest.MonkeyPatch, model: str, model_kwargs: dict[str, Any], - compilation_mode: int, + compilation_mode: CompilationMode, ): if ( "w8a8" in model @@ -197,7 +197,7 @@ def test_custom_compile_config( ], ) def test_fp8_kv_scale_compile( - compilation_mode: int, + compilation_mode: CompilationMode, model: str, backend: AttentionBackendEnum | None, ): @@ -213,7 +213,9 @@ def test_fp8_kv_scale_compile( run_model(compilation_mode, model, **model_kwargs) -def run_model(compile_config: int | CompilationConfig, model: str, **model_kwargs): +def run_model( + compile_config: CompilationMode | CompilationConfig, model: str, **model_kwargs +): compilation_config = ( compile_config if isinstance(compile_config, CompilationConfig) diff --git a/tests/compile/fusions_e2e/conftest.py b/tests/compile/fusions_e2e/conftest.py index a4ed63ffe7..929b27c11c 100644 --- a/tests/compile/fusions_e2e/conftest.py +++ b/tests/compile/fusions_e2e/conftest.py @@ -12,7 +12,9 @@ from vllm.config import CompilationConfig, CompilationMode, CUDAGraphMode from .common import FUSION_LOG_PATTERNS, AttentionBackendCase, Matches -def run_model(compile_config: int | CompilationConfig, model: str, **model_kwargs): +def run_model( + compile_config: CompilationMode | CompilationConfig, model: str, **model_kwargs +): """Run a model with the given compilation config for E2E fusion tests.""" compilation_config = ( compile_config @@ -54,7 +56,7 @@ def run_model(compile_config: int | CompilationConfig, model: str, **model_kwarg ) # Fetch match table from each worker via RPC and sum across workers. - worker_tables = llm.llm_engine.engine_core.collective_rpc( + worker_tables: list[dict[str, int]] = llm.llm_engine.engine_core.collective_rpc( "get_compilation_match_table" ) combined: defaultdict[str, int] = defaultdict(int) diff --git a/tests/config/test_bailing_mtp_config.py b/tests/config/test_bailing_mtp_config.py index 8fae29959f..bb7cf3ad56 100644 --- a/tests/config/test_bailing_mtp_config.py +++ b/tests/config/test_bailing_mtp_config.py @@ -1,6 +1,8 @@ # SPDX-License-Identifier: Apache-2.0 # SPDX-FileCopyrightText: Copyright contributors to the vLLM project +from typing import get_args + from transformers import PretrainedConfig from vllm.config.speculative import MTPModelTypes, SpeculativeConfig @@ -34,7 +36,7 @@ def test_bailing_hybrid_mtp_hf_config_override(): assert overridden.model_type == "bailing_hybrid_mtp" assert overridden.architectures == ["BailingMoeV25MTPModel"] assert overridden.n_predict == 1 - assert "bailing_hybrid_mtp" in MTPModelTypes.__args__ + assert "bailing_hybrid_mtp" in get_args(MTPModelTypes) def test_bailing_hybrid_mtp_model_arch_config(): diff --git a/tests/config/test_multimodal_config.py b/tests/config/test_multimodal_config.py index befcc73b0b..7786cef857 100644 --- a/tests/config/test_multimodal_config.py +++ b/tests/config/test_multimodal_config.py @@ -15,13 +15,13 @@ from vllm.v1.attention.backends.registry import AttentionBackendEnum def test_mm_encoder_attn_backend_str_conversion(): - config = MultiModalConfig(mm_encoder_attn_backend="FLASH_ATTN") + config = MultiModalConfig(mm_encoder_attn_backend="FLASH_ATTN") # type: ignore[arg-type] assert config.mm_encoder_attn_backend == AttentionBackendEnum.FLASH_ATTN def test_mm_encoder_attn_backend_invalid(): with pytest.raises(ValueError): - MultiModalConfig(mm_encoder_attn_backend="not_a_backend") + MultiModalConfig(mm_encoder_attn_backend="not_a_backend") # type: ignore[arg-type] def test_mm_encoder_attn_backend_hash_updates(): diff --git a/tests/config/test_speculative_draft_max_position_embeddings.py b/tests/config/test_speculative_draft_max_position_embeddings.py index 4338867837..117ae5a66d 100644 --- a/tests/config/test_speculative_draft_max_position_embeddings.py +++ b/tests/config/test_speculative_draft_max_position_embeddings.py @@ -14,6 +14,7 @@ methods only. """ import logging +from typing import Literal import pytest from transformers import PretrainedConfig @@ -77,7 +78,7 @@ def test_override_ignores_missing_attribute(vllm_caplog: pytest.LogCaptureFixtur @pytest.mark.cpu_test @pytest.mark.parametrize("method", ["eagle", "eagle3"]) def test_eagle_draft_inherits_target_max_model_len( - method: str, vllm_caplog: pytest.LogCaptureFixture + method: Literal["eagle", "eagle3"], vllm_caplog: pytest.LogCaptureFixture ): target_model_config = ModelConfig(LLAMA3_TARGET) assert target_model_config.max_model_len > 2048 diff --git a/tests/entrypoints/generate/generative_scoring/test_generative_scoring.py b/tests/entrypoints/generate/generative_scoring/test_generative_scoring.py index 12dae6dfd5..92c6061545 100644 --- a/tests/entrypoints/generate/generative_scoring/test_generative_scoring.py +++ b/tests/entrypoints/generate/generative_scoring/test_generative_scoring.py @@ -285,7 +285,7 @@ class TestPromptBuilding: ) for i, exp in enumerate(expected): - assert engine_inputs[i]["prompt_token_ids"] == exp + assert engine_inputs[i]["prompt_token_ids"] == exp # type: ignore[typeddict-item] class TestGeneration: diff --git a/tests/entrypoints/tool_parsers/test_hermes_tool_parser.py b/tests/entrypoints/tool_parsers/test_hermes_tool_parser.py index f9a7bef253..f03b6e8a38 100644 --- a/tests/entrypoints/tool_parsers/test_hermes_tool_parser.py +++ b/tests/entrypoints/tool_parsers/test_hermes_tool_parser.py @@ -45,7 +45,7 @@ class ServerConfig(TypedDict, total=False): model: str arguments: list[str] model_arg: str - tool_parser: ToolParser + tool_parser: type[ToolParser] CONFIGS: dict[str, ServerConfig] = { diff --git a/tests/entrypoints/weight_transfer/test_weight_transfer_llm.py b/tests/entrypoints/weight_transfer/test_weight_transfer_llm.py index 31d562e5cc..5681c1ffeb 100644 --- a/tests/entrypoints/weight_transfer/test_weight_transfer_llm.py +++ b/tests/entrypoints/weight_transfer/test_weight_transfer_llm.py @@ -329,4 +329,5 @@ def test_weight_transfer_config_backend(): ) config = llm.llm_engine.vllm_config.weight_transfer_config + assert config is not None assert config.backend == "nccl" diff --git a/tests/kernels/core/test_fused_qk_norm_rope.py b/tests/kernels/core/test_fused_qk_norm_rope.py index 43737f4f23..b91db79c6c 100644 --- a/tests/kernels/core/test_fused_qk_norm_rope.py +++ b/tests/kernels/core/test_fused_qk_norm_rope.py @@ -35,10 +35,12 @@ def _apply_qk_norm_rope( q_by_head = q.view(*q.shape[:-1], q.shape[-1] // head_dim, head_dim) q_by_head = q_norm.forward_native(q_by_head) + assert isinstance(q_by_head, torch.Tensor) q = q_by_head.view(q.shape) k_by_head = k.view(*k.shape[:-1], k.shape[-1] // head_dim, head_dim) k_by_head = k_norm.forward_native(k_by_head) + assert isinstance(k_by_head, torch.Tensor) k = k_by_head.view(k.shape) q, k = rope.forward_native(positions, q, k) diff --git a/tests/kernels/core/test_vit_fp8_attn.py b/tests/kernels/core/test_vit_fp8_attn.py index ef1c44cada..a677fc942a 100644 --- a/tests/kernels/core/test_vit_fp8_attn.py +++ b/tests/kernels/core/test_vit_fp8_attn.py @@ -34,10 +34,9 @@ NUM_HEADS = [16] @pytest.fixture def _fp8_attention(): """Create FP8-enabled MMEncoderAttention via config.""" - from types import SimpleNamespace - from unittest.mock import patch + from unittest.mock import MagicMock, patch - from vllm.config import VllmConfig, set_current_vllm_config + from vllm.config import ModelConfig, VllmConfig, set_current_vllm_config from vllm.config.multimodal import MultiModalConfig if not is_flashinfer_cudnn_fp8_prefill_attn_supported(): @@ -45,7 +44,7 @@ def _fp8_attention(): mm_config = MultiModalConfig(mm_encoder_attn_dtype="fp8") vllm_config = VllmConfig() - vllm_config.model_config = SimpleNamespace(multimodal_config=mm_config) + vllm_config.model_config = MagicMock(spec=ModelConfig, multimodal_config=mm_config) # MMEncoderAttention reads torch.get_default_dtype() during init # to determine the output dtype. In real model loading this is bf16. diff --git a/tests/kernels/core/test_vit_fp8_scaling.py b/tests/kernels/core/test_vit_fp8_scaling.py index bd0685af70..d756bfedbb 100644 --- a/tests/kernels/core/test_vit_fp8_scaling.py +++ b/tests/kernels/core/test_vit_fp8_scaling.py @@ -4,8 +4,7 @@ import contextlib import json -from types import SimpleNamespace -from unittest.mock import patch +from unittest.mock import MagicMock, patch import pytest import torch @@ -48,7 +47,7 @@ def _build_attention(mm_config, attn_backend=None): invokes ``process_weights_after_loading`` to simulate the model loader's auto-scan. Yields ``None`` if FlashInfer cuDNN is not available. """ - from vllm.config import VllmConfig, set_current_vllm_config + from vllm.config import ModelConfig, VllmConfig, set_current_vllm_config from vllm.model_executor.layers.attention.mm_encoder_attention import ( MMEncoderAttention, ) @@ -65,7 +64,7 @@ def _build_attention(mm_config, attn_backend=None): return vllm_config = VllmConfig() - vllm_config.model_config = SimpleNamespace(multimodal_config=mm_config) + vllm_config.model_config = MagicMock(spec=ModelConfig, multimodal_config=mm_config) with ( set_current_vllm_config(vllm_config), @@ -212,7 +211,7 @@ def test_aiter_static_scales_loaded(tmp_path) -> None: def test_static_scales_missing_layer(tmp_path) -> None: """Verify error when requested layer is not in the scale file.""" - from vllm.config import VllmConfig, set_current_vllm_config + from vllm.config import ModelConfig, VllmConfig, set_current_vllm_config from vllm.config.multimodal import MultiModalConfig from vllm.v1.attention.backends.registry import AttentionBackendEnum @@ -228,7 +227,7 @@ def test_static_scales_missing_layer(tmp_path) -> None: mm_encoder_fp8_scale_path=str(scale_file), ) vllm_config = VllmConfig() - vllm_config.model_config = SimpleNamespace(multimodal_config=mm_config) + vllm_config.model_config = MagicMock(spec=ModelConfig, multimodal_config=mm_config) from vllm.model_executor.layers.attention.mm_encoder_attention import ( MMEncoderAttention, diff --git a/tests/kernels/mamba/cpu/test_cpu_gdn_ops.py b/tests/kernels/mamba/cpu/test_cpu_gdn_ops.py index 4bfb545564..f43a9b4a58 100644 --- a/tests/kernels/mamba/cpu/test_cpu_gdn_ops.py +++ b/tests/kernels/mamba/cpu/test_cpu_gdn_ops.py @@ -12,6 +12,7 @@ import vllm._custom_ops as ops from vllm.model_executor.layers.mamba.ops.cpu import gdn_attention from vllm.platforms import current_platform from vllm.utils.torch_utils import set_random_seed +from vllm.v1.attention.backends.gdn_attn import GDNAttentionMetadata if not current_platform.is_cpu(): pytest.skip("skipping CPU-only tests", allow_module_level=True) @@ -452,12 +453,17 @@ def test_spec_aware_mixed_routing_preserves_token_order( spec_indices = torch.tensor([0, 2]) nonspec_indices = torch.tensor([1, 3]) - metadata = types.SimpleNamespace( + metadata = GDNAttentionMetadata( + num_prefills=1, + num_prefill_tokens=0, + num_decodes=0, + num_decode_tokens=0, + num_spec_decodes=0, + num_spec_decode_tokens=0, + num_actual_tokens=0, spec_sequence_masks=torch.ones(1, dtype=torch.bool), spec_token_indx=spec_indices, non_spec_token_indx=nonspec_indices, - num_prefills=1, - num_decodes=0, ) routed = [] @@ -501,13 +507,16 @@ def test_spec_aware_nonspec_materializes_state_indices( state_indices = block_table[:, 0] assert not state_indices.is_contiguous() - metadata = types.SimpleNamespace( - non_spec_state_indices_tensor=state_indices, - non_spec_query_start_loc=torch.tensor([0, 2, 4], dtype=torch.int32), - num_decodes=0, - num_decode_tokens=0, + metadata = GDNAttentionMetadata( num_prefills=2, num_prefill_tokens=4, + num_decodes=0, + num_decode_tokens=0, + num_spec_decodes=0, + num_spec_decode_tokens=0, + num_actual_tokens=4, + non_spec_state_indices_tensor=state_indices, + non_spec_query_start_loc=torch.tensor([0, 2, 4], dtype=torch.int32), has_initial_state=torch.tensor([False, False]), ) @@ -575,8 +584,14 @@ def test_spec_forward_prepares_native_conv_metadata( state_indices = block_table[:, 0] accepted_counts = torch.tensor([1, 4], dtype=torch.int32) assert not state_indices.is_contiguous() - metadata = types.SimpleNamespace( + metadata = GDNAttentionMetadata( + num_prefills=0, + num_prefill_tokens=0, + num_decodes=0, + num_decode_tokens=0, num_spec_decodes=2, + num_spec_decode_tokens=8, + num_actual_tokens=8, spec_state_indices_tensor=block_table, spec_query_start_loc=torch.tensor([0, 4, 8], dtype=torch.int32), num_accepted_tokens=accepted_counts, diff --git a/tests/kernels/mamba/test_gdn_forward_core_split.py b/tests/kernels/mamba/test_gdn_forward_core_split.py index fa28f4701c..b1c3030380 100644 --- a/tests/kernels/mamba/test_gdn_forward_core_split.py +++ b/tests/kernels/mamba/test_gdn_forward_core_split.py @@ -174,7 +174,9 @@ def test_forward_core_split_matches_unified( batch = BatchSpec(seq_lens=seq_lens, query_lens=query_lens) builder = GDNAttentionMetadataBuilder( - kv_cache_spec=MambaSpec( + # GDNAttentionMetadataBuilder declares kv_cache_spec as AttentionSpec but + # asserts isinstance(kv_cache_spec, MambaSpec). MambaSpec is correct here. + kv_cache_spec=MambaSpec( # type: ignore[arg-type] block_size=BLOCK_SIZE, shapes=((16, 64),), dtypes=(torch.float16,) ), layer_names=[PREFIX], @@ -198,6 +200,7 @@ def test_forward_core_split_matches_unified( # Full-batch chunk metadata for the unified reference path, built the same # way the builder would for a non-split batch (backend-matched). cu_full = meta_split.non_spec_query_start_loc + assert cu_full is not None if builder.gdn_prefill_backend == "cutedsl": from vllm.model_executor.layers.mamba.ops.gdn_chunk_cutedsl import ( prepare_metadata_cutedsl, @@ -227,6 +230,7 @@ def test_forward_core_split_matches_unified( ) # Size the state pools from the indices the builder actually produced. + assert meta_split.non_spec_state_indices_tensor is not None pool_size = int(meta_split.non_spec_state_indices_tensor.max().item()) + 1 conv_state_shape, temporal_state_shape = ( MambaStateShapeCalculator.gated_delta_net_state_shape( diff --git a/tests/kernels/mamba/test_precopy_mamba_align.py b/tests/kernels/mamba/test_precopy_mamba_align.py index ef855ae099..b7a3da37d5 100644 --- a/tests/kernels/mamba/test_precopy_mamba_align.py +++ b/tests/kernels/mamba/test_precopy_mamba_align.py @@ -21,7 +21,9 @@ The kernel must also no-op when ``src_col < 0`` (fresh request) or from __future__ import annotations +from collections.abc import Callable from types import SimpleNamespace +from typing import Any import numpy as np import torch @@ -31,6 +33,8 @@ from vllm.platforms import current_platform from vllm.v1.worker import mamba_utils as worker_mamba_utils from vllm.v1.worker.mamba_utils import precopy_mamba_align_fused_kernel +_parametrize: Callable[..., Callable[[Any], Any]] + try: import pytest @@ -40,17 +44,18 @@ try: ) _parametrize = pytest.mark.parametrize except ModuleNotFoundError: # allow running directly as ``python `` - pytest = None def _cuda_required(fn): return fn - def _parametrize(_name, _values): + def _no_parametrize(_name, _values): def _deco(fn): return fn return _deco + _parametrize = _no_parametrize + NUM_LAYERS = 3 CONV_WIDTH = 4 # conv_kernel - 1 + num_spec @@ -308,8 +313,10 @@ def _make_preprocess_case(token_bias): def test_preprocess_fused_align_matches_scalar_bookkeeping(monkeypatch, token_bias): block_size = 4 mamba_spec = SimpleNamespace(block_size=block_size, num_speculative_blocks=1) - cache_config = SimpleNamespace(enable_prefix_caching=True) - kv_cache_config = SimpleNamespace() + # Fakes stand in for real config/context objects. The fused path tests + # below only touch the attributes preprocess_mamba actually reads. + cache_config: Any = SimpleNamespace(enable_prefix_caching=True) + kv_cache_config: Any = SimpleNamespace() scalar_copy_calls = [] def fake_collect( @@ -340,7 +347,7 @@ def test_preprocess_fused_align_matches_scalar_bookkeeping(monkeypatch, token_bi scalar_case = _make_preprocess_case(token_bias) fused_case = _make_preprocess_case(token_bias) - scalar_copy_bufs = SimpleNamespace( + scalar_copy_bufs: Any = SimpleNamespace( mamba_group_ids=[0], mamba_spec=mamba_spec, offset=0, @@ -357,8 +364,8 @@ def test_preprocess_fused_align_matches_scalar_bookkeeping(monkeypatch, token_bi copy_bufs=scalar_copy_bufs, ) - ctx = _FakePrecopyContext(len(fused_case[1].req_ids)) - fused_copy_bufs = SimpleNamespace( + ctx: Any = _FakePrecopyContext(len(fused_case[1].req_ids)) + fused_copy_bufs: Any = SimpleNamespace( mamba_group_ids=[0], mamba_spec=mamba_spec, offset=0, diff --git a/tests/models/language/generation/test_mistral.py b/tests/models/language/generation/test_mistral.py index bc85d6f722..2bc9bc350f 100644 --- a/tests/models/language/generation/test_mistral.py +++ b/tests/models/language/generation/test_mistral.py @@ -261,7 +261,7 @@ def test_mistral_function_calling(vllm_runner, model: str, dtype: str) -> None: model_output = outputs[0].outputs[0].text.strip() assert model_output.startswith(tool_parser.bot_token), model_output - parsed_message = tool_parser.extract_tool_calls(model_output, None) + parsed_message = tool_parser.extract_tool_calls(model_output, None) # type: ignore[arg-type] assert parsed_message.tools_called @@ -304,7 +304,7 @@ def test_mistral_function_call_nested_json(): model_output = f"{parser.bot_token}get_current_weather{json.dumps(args_dict)}" - parsed = parser.extract_tool_calls(model_output, None) + parsed = parser.extract_tool_calls(model_output, None) # type: ignore[arg-type] # Assertions: the tool call is detected and the full nested JSON is parsed # without truncation. @@ -337,7 +337,7 @@ def test_mistral_function_call_nested_json(): ] ) - parsed = parser.extract_tool_calls(model_output, None) + parsed = parser.extract_tool_calls(model_output, None) # type: ignore[arg-type] # Assertions: the tool call is detected and the full nested JSON is parsed # without truncation. diff --git a/tests/models/quantization/test_bitsandbytes.py b/tests/models/quantization/test_bitsandbytes.py index 03c19b0bf6..3c2fd0dbd4 100644 --- a/tests/models/quantization/test_bitsandbytes.py +++ b/tests/models/quantization/test_bitsandbytes.py @@ -323,7 +323,7 @@ def test_bitsandbytes_passes_revision_by_name(): return_value=["/folder/model.safetensors"], ), ): - bnb.BitsAndBytesModelLoader._prepare_weights(fake_self, "org/model", "myrev") + bnb.BitsAndBytesModelLoader._prepare_weights(fake_self, "org/model", "myrev") # type: ignore[arg-type] mock_idx.assert_called_once() assert mock_idx.call_args.kwargs.get("revision") == "myrev" diff --git a/tests/plugins/bge_m3_sparse_plugin/bge_m3_sparse_processor/sparse_embeddings_processor.py b/tests/plugins/bge_m3_sparse_plugin/bge_m3_sparse_processor/sparse_embeddings_processor.py index a845dae77b..74cf122503 100644 --- a/tests/plugins/bge_m3_sparse_plugin/bge_m3_sparse_processor/sparse_embeddings_processor.py +++ b/tests/plugins/bge_m3_sparse_plugin/bge_m3_sparse_processor/sparse_embeddings_processor.py @@ -29,7 +29,7 @@ class BgeM3SparseEmbeddingsProcessor( self.online_requests: dict[str, SparseEmbeddingCompletionRequestMixin] = {} self.renderer: BaseRenderer = renderer self.default_pooling_params = {} - pooler_config: PoolerConfig = vllm_config.model_config.pooler_config + pooler_config: PoolerConfig | None = vllm_config.model_config.pooler_config if pooler_config is not None: for param in ["use_activation", "dimensions"]: if getattr(pooler_config, param, None) is None: @@ -91,11 +91,11 @@ class BgeM3SparseEmbeddingsProcessor( ) -> list[SparseEmbeddingTokenWeight]: token_ids = sparse_embedding.keys() token_weights = sparse_embedding.values() - tokens = [None] * len(token_ids) + tokens: Sequence[str | None] = [None] * len(token_ids) if return_tokens and self.renderer is not None: tokens = convert_ids_list_to_tokens( - self.renderer.get_tokenizer(), token_ids + self.renderer.get_tokenizer(), list(token_ids) ) sparse_embedding_output: list[SparseEmbeddingTokenWeight] = [] for token_id, weight, token in zip(token_ids, token_weights, tokens): diff --git a/tests/plugins/prithvi_io_processor_plugin/prithvi_io_processor/prithvi_processor.py b/tests/plugins/prithvi_io_processor_plugin/prithvi_io_processor/prithvi_processor.py index 89bdab8c39..d83399e07a 100644 --- a/tests/plugins/prithvi_io_processor_plugin/prithvi_io_processor/prithvi_processor.py +++ b/tests/plugins/prithvi_io_processor_plugin/prithvi_io_processor/prithvi_processor.py @@ -170,7 +170,7 @@ def load_image( list of meta info for each image in *file_paths* """ - imgs = [] + imgs: list[np.ndarray] = [] metas = [] temporal_coords = [] location_coords = [] @@ -209,11 +209,11 @@ def load_image( except Exception: logger.exception("Could not extract timestamp for %s", file) - imgs = np.stack(imgs, axis=0) # num_frames, H, W, C - imgs = np.moveaxis(imgs, -1, 0).astype("float32") # C, num_frames, H, W - imgs = np.expand_dims(imgs, axis=0) # add batch di + stacked = np.stack(imgs, axis=0) # num_frames, H, W, C + stacked = np.moveaxis(stacked, -1, 0).astype("float32") # C, num_frames, H, W + stacked = np.expand_dims(stacked, axis=0) # add batch di - return imgs, temporal_coords, location_coords, metas + return stacked, temporal_coords, location_coords, metas class PrithviMultimodalDataProcessor(IOProcessor[ImagePrompt, ImageRequestOutput]): @@ -327,7 +327,7 @@ class PrithviMultimodalDataProcessor(IOProcessor[ImagePrompt, ImageRequestOutput } ) - return prompts + return prompts # type: ignore[return-value] def post_process( self, diff --git a/tests/plugins/vllm_add_dummy_platform/vllm_add_dummy_platform/dummy_platform.py b/tests/plugins/vllm_add_dummy_platform/vllm_add_dummy_platform/dummy_platform.py index 8448003e70..11e78ccfc1 100644 --- a/tests/plugins/vllm_add_dummy_platform/vllm_add_dummy_platform/dummy_platform.py +++ b/tests/plugins/vllm_add_dummy_platform/vllm_add_dummy_platform/dummy_platform.py @@ -6,6 +6,8 @@ from vllm.platforms.interface import Platform, PlatformEnum if TYPE_CHECKING: from vllm.config import VllmConfig + from vllm.v1.attention.backends.registry import AttentionBackendEnum + from vllm.v1.attention.selector import AttentionSelectorConfig else: VllmConfig = None @@ -20,16 +22,11 @@ class DummyPlatform(Platform): def check_and_update_config(cls, vllm_config: VllmConfig) -> None: vllm_config.compilation_config.custom_ops = ["all"] + @classmethod def get_attn_backend_cls( - self, - backend_name, - head_size, - dtype, - kv_cache_dtype, - block_size, - use_mla, - has_sink, - use_sparse, - use_mm_prefix, - ): + cls, + selected_backend: "AttentionBackendEnum", + attn_selector_config: "AttentionSelectorConfig", + num_heads: int | None = None, + ) -> str: return "vllm_add_dummy_platform.dummy_attention_backend.DummyAttentionBackend" # noqa E501 diff --git a/tests/plugins/vllm_add_dummy_stat_logger/dummy_stat_logger/dummy_stat_logger.py b/tests/plugins/vllm_add_dummy_stat_logger/dummy_stat_logger/dummy_stat_logger.py index 66ec35c0d5..7ba2c09b28 100644 --- a/tests/plugins/vllm_add_dummy_stat_logger/dummy_stat_logger/dummy_stat_logger.py +++ b/tests/plugins/vllm_add_dummy_stat_logger/dummy_stat_logger/dummy_stat_logger.py @@ -17,7 +17,9 @@ class DummyStatLogger(StatLoggerBase): self.logged = False self.engine_initialized = False - def record(self, scheduler_stats, iteration_stats, mm_cache_stats, engine_idx): + def record( + self, scheduler_stats, iteration_stats, mm_cache_stats=None, engine_idx=0 + ): self.recorded.append( (scheduler_stats, iteration_stats, mm_cache_stats, engine_idx) ) diff --git a/tests/plugins_tests/gguf/test_gguf_plugin_multimodal.py b/tests/plugins_tests/gguf/test_gguf_plugin_multimodal.py index 56930a7d0b..5ebd7d36e8 100644 --- a/tests/plugins_tests/gguf/test_gguf_plugin_multimodal.py +++ b/tests/plugins_tests/gguf/test_gguf_plugin_multimodal.py @@ -92,7 +92,7 @@ def run_multimodal_gguf_test( num_logprobs: int, ): # Load images at runtime (inside subprocess) to avoid pickle issues - images = [ImageAsset(name).pil_image for name in model.image_names] + images = [ImageAsset(name).pil_image for name in model.image_names] # type: ignore[arg-type] size_factors = [0.25, 0.5, 1.0] inputs_per_image = [ ( diff --git a/tests/plugins_tests/lora_resolvers/test_hf_hub_resolver.py b/tests/plugins_tests/lora_resolvers/test_hf_hub_resolver.py index 6fa747211a..4590ae29c4 100644 --- a/tests/plugins_tests/lora_resolvers/test_hf_hub_resolver.py +++ b/tests/plugins_tests/lora_resolvers/test_hf_hub_resolver.py @@ -31,6 +31,7 @@ async def test_hf_resolver_with_direct_path(): assert hf_resolver is not None lora_request = await hf_resolver.resolve_lora(LORA_REPO_MODEL_NAME, LORA_REPO) + assert lora_request is not None assert lora_request.lora_name == LORA_REPO assert REPO_DOWNLOAD_DIR in lora_request.lora_path assert "adapter_config.json" in os.listdir(lora_request.lora_path) diff --git a/tests/spec_decode/test_custom_proposer.py b/tests/spec_decode/test_custom_proposer.py index acd6089fb9..1e42bde810 100755 --- a/tests/spec_decode/test_custom_proposer.py +++ b/tests/spec_decode/test_custom_proposer.py @@ -30,6 +30,7 @@ class DummyDraftProposer: Args: vllm_config: vLLM configuration containing model and speculative settings. """ + assert vllm_config.speculative_config is not None self.num_speculative_tokens = ( vllm_config.speculative_config.num_speculative_tokens ) diff --git a/tests/transformers_utils/test_processor.py b/tests/transformers_utils/test_processor.py index a3a1c78418..e9070619d9 100644 --- a/tests/transformers_utils/test_processor.py +++ b/tests/transformers_utils/test_processor.py @@ -44,7 +44,7 @@ class _ProcWithUnpack: def test_get_processor_kwargs_from_processor_unpack_path_returns_full_union(): proc = _ProcWithUnpack() - keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc)) + keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc)) # type: ignore[arg-type] _assert_has_all_expected(keys) @@ -63,5 +63,5 @@ def test_get_processor_kwargs_from_processor_module_scan_returns_full_union(): assert hasattr(mod, "_FakeProcessorKwargs") proc = _ProcWithoutUnpack() - keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc)) + keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc)) # type: ignore[arg-type] _assert_has_all_expected(keys) diff --git a/tests/v1/distributed/test_async_llm_dp.py b/tests/v1/distributed/test_async_llm_dp.py index 9269f294b8..711daaef74 100644 --- a/tests/v1/distributed/test_async_llm_dp.py +++ b/tests/v1/distributed/test_async_llm_dp.py @@ -12,13 +12,14 @@ import pytest from vllm import SamplingParams from vllm.config import VllmConfig +from vllm.config.parallel import DataParallelBackend from vllm.engine.arg_utils import AsyncEngineArgs from vllm.inputs import PromptType from vllm.outputs import RequestOutput from vllm.platforms import current_platform from vllm.sampling_params import RequestOutputKind from vllm.v1.engine.async_llm import AsyncLLM -from vllm.v1.engine.core_client import DPAsyncMPClient +from vllm.v1.engine.core_client import DPLBAsyncMPClient from vllm.v1.metrics.loggers import StatLoggerBase from vllm.v1.metrics.stats import IterationStats, MultiModalCacheStats, SchedulerStats @@ -82,7 +83,7 @@ async def generate( async def test_load( model: str, output_kind: RequestOutputKind, - data_parallel_backend: str, + data_parallel_backend: DataParallelBackend, async_scheduling: bool, ): if async_scheduling and data_parallel_backend == "ray": @@ -162,7 +163,8 @@ async def test_load( assert not engine.output_processor.has_unfinished_requests() # testing internals here which may break - core_client: DPAsyncMPClient = engine.engine_core + core_client = engine.engine_core + assert isinstance(core_client, DPLBAsyncMPClient) # the engines only synchronize stopping every N steps so # allow a small amount of time here. for _ in range(10): diff --git a/tests/v1/distributed/test_eagle_dp.py b/tests/v1/distributed/test_eagle_dp.py index 019f9c6f21..bb2b9f9fae 100644 --- a/tests/v1/distributed/test_eagle_dp.py +++ b/tests/v1/distributed/test_eagle_dp.py @@ -61,7 +61,7 @@ async def test_run_eagle_dp(monkeypatch: pytest.MonkeyPatch, attn_backend: str): data_parallel_backend="mp", # ray takes more time trust_remote_code=True, max_model_len=16384, - attention_config={"backend": attn_backend}, + attention_config={"backend": attn_backend}, # type: ignore[arg-type] ) eagle_engine_args = replace( diff --git a/tests/v1/shutdown/test_processor_error.py b/tests/v1/shutdown/test_processor_error.py index 0aba775e43..665d457097 100644 --- a/tests/v1/shutdown/test_processor_error.py +++ b/tests/v1/shutdown/test_processor_error.py @@ -9,7 +9,7 @@ import pytest from tests.v1.shutdown.utils import SHUTDOWN_TEST_TIMEOUT_SEC from vllm import SamplingParams from vllm.engine.arg_utils import AsyncEngineArgs -from vllm.inputs import TokensPrompt +from vllm.inputs import ExplicitEncoderDecoderPrompt from vllm.sampling_params import RequestOutputKind from vllm.v1.engine.async_llm import AsyncLLM from vllm.v1.engine.exceptions import EngineGenerateError @@ -29,9 +29,14 @@ async def test_async_llm_processor_error(model: str) -> None: async_llm = AsyncLLM.from_engine_args(engine_args) async def generate(request_id: str): - # [] is not allowed and will raise a ValueError in Processor. + # An encoder/decoder prompt is rejected by the Processor for a + # decoder only model. generator = async_llm.generate( - TokensPrompt([]), request_id=request_id, sampling_params=SamplingParams() + ExplicitEncoderDecoderPrompt( + encoder_prompt="Hello my name is", decoder_prompt=None + ), + request_id=request_id, + sampling_params=SamplingParams(), ) try: async for _ in generator: diff --git a/tools/pre_commit/mypy.py b/tools/pre_commit/mypy.py index c52e0e7ce6..585585e352 100755 --- a/tools/pre_commit/mypy.py +++ b/tools/pre_commit/mypy.py @@ -21,34 +21,55 @@ import sys import regex as re +# Paths verified clean under follow_imports="silent". Matched before +# SEPARATE_GROUPS, so these files join the default group and are checked at the +# stricter setting even while a parent directory remains in SEPARATE_GROUPS. +# +# Fixing a directory means moving it from SEPARATE_GROUPS to here. Without that +# move the fixes are not enforced because "tests" claims every file below it. +SILENT_GROUPS = [ + "tests/compile/correctness_e2e", + "tests/compile/fullgraph", + "tests/compile/fusions_e2e", + "tests/config", + "tests/entrypoints/generate", + "tests/entrypoints/tool_parsers", + "tests/entrypoints/weight_transfer", + "tests/kernels/core", + "tests/kernels/mamba", + "tests/models/language", + "tests/models/quantization", + "tests/plugins/bge_m3_sparse_plugin", + "tests/plugins/prithvi_io_processor_plugin", + "tests/plugins/vllm_add_dummy_platform", + "tests/plugins/vllm_add_dummy_stat_logger", + "tests/plugins_tests/gguf", + "tests/plugins_tests/lora_resolvers", + "tests/spec_decode", + "tests/transformers_utils", + "tests/v1/distributed", + "tests/v1/shutdown", +] + # After fixing errors resulting from changing follow_imports -# from "skip" to "silent", remove its directory from SEPARATE_GROUPS. +# from "skip" to "silent", move its directory to SILENT_GROUPS. SEPARATE_GROUPS = [ "tests", "tests/benchmarks", - "tests/compile/correctness_e2e", - "tests/config", "tests/compile", - "tests/compile/fullgraph", - "tests/compile/fusions_e2e", "tests/compile/passes", "tests/distributed", "tests/entrypoints/anthropic", - "tests/entrypoints/generate", "tests/entrypoints/llm", "tests/entrypoints/multimodal", "tests/entrypoints/openai", "tests/entrypoints/pooling", "tests/entrypoints/serve", "tests/entrypoints/speech_to_text", - "tests/entrypoints/tool_parsers", "tests/entrypoints/unit_tests", - "tests/entrypoints/weight_transfer", "tests/kernels", "tests/kernels/attention", - "tests/kernels/core", "tests/kernels/helion", - "tests/kernels/mamba", "tests/kernels/moe", "tests/kernels/quantization", "tests/lora", @@ -57,34 +78,23 @@ SEPARATE_GROUPS = [ "tests/model_executor/model_loader", "tests/models", "tests/models/test_initialization.py", - "tests/models/language", "tests/models/multimodal", - "tests/models/quantization", "tests/multimodal", "tests/parser", - "tests/plugins_tests/gguf", - "tests/plugins_tests/lora_resolvers", - "tests/plugins/bge_m3_sparse_plugin", - "tests/plugins/prithvi_io_processor_plugin", - "tests/plugins/vllm_add_dummy_platform", - "tests/plugins/vllm_add_dummy_stat_logger", "tests/plugins_tests", "tests/quantization", "tests/reasoning", "tests/renderers", "tests/samplers", - "tests/spec_decode", "tests/tokenizers_", "tests/tool_parsers", "tests/tool_use", - "tests/transformers_utils", "tests/utils_", "tests/v1", "tests/v1/attention", "tests/v1/core", "tests/v1/cudagraph", "tests/v1/determinism", - "tests/v1/distributed", "tests/v1/e2e", "tests/v1/ec_connector", "tests/v1/engine", @@ -94,7 +104,6 @@ SEPARATE_GROUPS = [ "tests/v1/logits_processors", "tests/v1/metrics", "tests/v1/sample", - "tests/v1/shutdown", "tests/v1/simple_kv_offload", "tests/v1/spec_decode", "tests/v1/streaming_input", @@ -142,14 +151,22 @@ def group_files(changed_files: list[str]) -> dict[str, list[str]]: A dictionary mapping file group names to lists of changed files. """ exclude_pattern = re.compile(f"^{'|'.join(EXCLUDE)}.*") - file_groups = {"": []} + silent_pattern = re.compile(f"^({'|'.join(SILENT_GROUPS)}).*") + file_groups: dict[str, list[str]] = {"": []} file_groups.update({k: [] for k in SEPARATE_GROUPS}) + # Longest path first so a sub-directory is not shadowed by its parent + separate_groups = sorted(SEPARATE_GROUPS, key=len, reverse=True) for changed_file in changed_files: # Skip files which should be ignored completely if exclude_pattern.match(changed_file): continue + # Already-fixed paths go in the default group, which runs at the + # stricter follow_imports setting from pyproject.toml + if silent_pattern.match(changed_file): + file_groups[""].append(changed_file) + continue # Group files by mypy call - for directory in SEPARATE_GROUPS: + for directory in separate_groups: if re.match(f"^{directory}.*", changed_file): file_groups[directory].append(changed_file) break