[MyPy][1/N] Fix mypy errors in some tests/ directories and enforce follow-imports=silent (#49570)
Signed-off-by: Martin Hickey <martin.hickey@ie.ibm.com> Co-authored-by: Harry Mellor <19981378+hmellor@users.noreply.github.com>
Martin Hickey committed
Jul 30, 2026 at 13:02 UTC
38a267cdd5b30841bb2e2913d67ba18544098c3a
30 files changed
+166
-101
tests/compile/correctness_e2e/test_sequence_parallel.py
+6
-2
@@ -348,10 +348,14 @@ def test_tp_sp_generation(
348
if use_inductor_graph_partition and not is_torch_equal_or_newer("2.9.0.dev"):
349
pytest.skip("inductor graph partition is only available in PyTorch 2.9+")
350
351
- # Skip FP8 SP-only test on sm89 (compute capability 8.9)
351
+ # Skip FP8 SP-only test on sm89 (compute capability 8.9).
352
+ # An unknown capability (None) is left to fail in the test body rather than
353
+ # being silently skipped here.
354
+ capability = current_platform.get_device_capability()
355
if (
356
"fp8" in model_id.lower()
354
- and current_platform.get_device_capability() < (9, 0)
357
+ and capability is not None
358
+ and capability < (9, 0)
359
and (not fuse_gemm_comms)
360
):
361
pytest.skip("FP8 reduction support begins with sm90 capable devices.")
tests/compile/fullgraph/test_full_cudagraph.py
+4
-2
@@ -9,7 +9,7 @@ import pytest
9
from tests.utils import wait_for_gpu_memory_to_clear
10
from tests.v1.attention.utils import full_cg_backend_configs as backend_configs
11
from vllm import LLM, SamplingParams
12
-from vllm.config import CompilationConfig
12
+from vllm.config import CompilationConfig, CUDAGraphMode
13
from vllm.platforms import current_platform
14
from vllm.utils.torch_utils import is_torch_equal_or_newer
15
from vllm.v1.attention.backends.registry import AttentionBackendEnum
@@ -97,7 +97,9 @@ def llm_pair(request):
97
trust_remote_code=True,
98
max_model_len=1024,
99
max_num_seqs=128,
100
- compilation_config=CompilationConfig(cudagraph_mode="PIECEWISE"),
100
+ compilation_config=CompilationConfig(
101
+ cudagraph_mode=CUDAGraphMode.PIECEWISE
102
+ ),
103
generation_config="vllm",
104
seed=42,
105
)
tests/compile/fullgraph/test_full_graph.py
+5
-3
@@ -75,7 +75,7 @@ def test_full_graph(
75
monkeypatch: pytest.MonkeyPatch,
76
model: str,
77
model_kwargs: dict[str, Any],
78
- compilation_mode: int,
78
+ compilation_mode: CompilationMode,
79
):
80
if (
81
"w8a8" in model
@@ -197,7 +197,7 @@ def test_custom_compile_config(
197
],
198
)
199
def test_fp8_kv_scale_compile(
200
- compilation_mode: int,
200
+ compilation_mode: CompilationMode,
201
model: str,
202
backend: AttentionBackendEnum | None,
203
):
@@ -213,7 +213,9 @@ def test_fp8_kv_scale_compile(
213
run_model(compilation_mode, model, **model_kwargs)
214
215
216
-def run_model(compile_config: int | CompilationConfig, model: str, **model_kwargs):
216
+def run_model(
217
+ compile_config: CompilationMode | CompilationConfig, model: str, **model_kwargs
218
+):
219
compilation_config = (
220
compile_config
221
if isinstance(compile_config, CompilationConfig)
tests/compile/fusions_e2e/conftest.py
+4
-2
@@ -12,7 +12,9 @@ from vllm.config import CompilationConfig, CompilationMode, CUDAGraphMode
12
from .common import FUSION_LOG_PATTERNS, AttentionBackendCase, Matches
13
14
15
-def run_model(compile_config: int | CompilationConfig, model: str, **model_kwargs):
15
+def run_model(
16
+ compile_config: CompilationMode | CompilationConfig, model: str, **model_kwargs
17
+):
18
"""Run a model with the given compilation config for E2E fusion tests."""
19
compilation_config = (
20
compile_config
@@ -54,7 +56,7 @@ def run_model(compile_config: int | CompilationConfig, model: str, **model_kwarg
56
)
57
58
# Fetch match table from each worker via RPC and sum across workers.
57
- worker_tables = llm.llm_engine.engine_core.collective_rpc(
59
+ worker_tables: list[dict[str, int]] = llm.llm_engine.engine_core.collective_rpc(
60
"get_compilation_match_table"
61
)
62
combined: defaultdict[str, int] = defaultdict(int)
tests/config/test_bailing_mtp_config.py
+3
-1
@@ -1,6 +1,8 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
+from typing import get_args
5
+
6
from transformers import PretrainedConfig
7
8
from vllm.config.speculative import MTPModelTypes, SpeculativeConfig
@@ -34,7 +36,7 @@ def test_bailing_hybrid_mtp_hf_config_override():
36
assert overridden.model_type == "bailing_hybrid_mtp"
37
assert overridden.architectures == ["BailingMoeV25MTPModel"]
38
assert overridden.n_predict == 1
37
- assert "bailing_hybrid_mtp" in MTPModelTypes.__args__
39
+ assert "bailing_hybrid_mtp" in get_args(MTPModelTypes)
40
41
42
def test_bailing_hybrid_mtp_model_arch_config():
tests/config/test_multimodal_config.py
+2
-2
@@ -15,13 +15,13 @@ from vllm.v1.attention.backends.registry import AttentionBackendEnum
15
16
17
def test_mm_encoder_attn_backend_str_conversion():
18
- config = MultiModalConfig(mm_encoder_attn_backend="FLASH_ATTN")
18
+ config = MultiModalConfig(mm_encoder_attn_backend="FLASH_ATTN") # type: ignore[arg-type]
19
assert config.mm_encoder_attn_backend == AttentionBackendEnum.FLASH_ATTN
20
21
22
def test_mm_encoder_attn_backend_invalid():
23
with pytest.raises(ValueError):
24
- MultiModalConfig(mm_encoder_attn_backend="not_a_backend")
24
+ MultiModalConfig(mm_encoder_attn_backend="not_a_backend") # type: ignore[arg-type]
25
26
27
def test_mm_encoder_attn_backend_hash_updates():
tests/config/test_speculative_draft_max_position_embeddings.py
+2
-1
@@ -14,6 +14,7 @@ methods only.
14
"""
15
16
import logging
17
+from typing import Literal
18
19
import pytest
20
from transformers import PretrainedConfig
@@ -77,7 +78,7 @@ def test_override_ignores_missing_attribute(vllm_caplog: pytest.LogCaptureFixtur
78
@pytest.mark.cpu_test
79
@pytest.mark.parametrize("method", ["eagle", "eagle3"])
80
def test_eagle_draft_inherits_target_max_model_len(
80
- method: str, vllm_caplog: pytest.LogCaptureFixture
81
+ method: Literal["eagle", "eagle3"], vllm_caplog: pytest.LogCaptureFixture
82
):
83
target_model_config = ModelConfig(LLAMA3_TARGET)
84
assert target_model_config.max_model_len > 2048
tests/entrypoints/generate/generative_scoring/test_generative_scoring.py
+1
-1
@@ -285,7 +285,7 @@ class TestPromptBuilding:
285
)
286
287
for i, exp in enumerate(expected):
288
- assert engine_inputs[i]["prompt_token_ids"] == exp
288
+ assert engine_inputs[i]["prompt_token_ids"] == exp # type: ignore[typeddict-item]
289
290
291
class TestGeneration:
tests/entrypoints/tool_parsers/test_hermes_tool_parser.py
+1
-1
@@ -45,7 +45,7 @@ class ServerConfig(TypedDict, total=False):
45
model: str
46
arguments: list[str]
47
model_arg: str
48
- tool_parser: ToolParser
48
+ tool_parser: type[ToolParser]
49
50
51
CONFIGS: dict[str, ServerConfig] = {
tests/entrypoints/weight_transfer/test_weight_transfer_llm.py
+1
@@ -329,4 +329,5 @@ def test_weight_transfer_config_backend():
329
)
330
331
config = llm.llm_engine.vllm_config.weight_transfer_config
332
+ assert config is not None
333
assert config.backend == "nccl"
tests/kernels/core/test_fused_qk_norm_rope.py
+2
@@ -35,10 +35,12 @@ def _apply_qk_norm_rope(
35
36
q_by_head = q.view(*q.shape[:-1], q.shape[-1] // head_dim, head_dim)
37
q_by_head = q_norm.forward_native(q_by_head)
38
+ assert isinstance(q_by_head, torch.Tensor)
39
q = q_by_head.view(q.shape)
40
41
k_by_head = k.view(*k.shape[:-1], k.shape[-1] // head_dim, head_dim)
42
k_by_head = k_norm.forward_native(k_by_head)
43
+ assert isinstance(k_by_head, torch.Tensor)
44
k = k_by_head.view(k.shape)
45
46
q, k = rope.forward_native(positions, q, k)
tests/kernels/core/test_vit_fp8_attn.py
+3
-4
@@ -34,10 +34,9 @@ NUM_HEADS = [16]
34
@pytest.fixture
35
def _fp8_attention():
36
"""Create FP8-enabled MMEncoderAttention via config."""
37
- from types import SimpleNamespace
38
- from unittest.mock import patch
37
+ from unittest.mock import MagicMock, patch
38
40
- from vllm.config import VllmConfig, set_current_vllm_config
39
+ from vllm.config import ModelConfig, VllmConfig, set_current_vllm_config
40
from vllm.config.multimodal import MultiModalConfig
41
42
if not is_flashinfer_cudnn_fp8_prefill_attn_supported():
@@ -45,7 +44,7 @@ def _fp8_attention():
44
45
mm_config = MultiModalConfig(mm_encoder_attn_dtype="fp8")
46
vllm_config = VllmConfig()
48
- vllm_config.model_config = SimpleNamespace(multimodal_config=mm_config)
47
+ vllm_config.model_config = MagicMock(spec=ModelConfig, multimodal_config=mm_config)
48
49
# MMEncoderAttention reads torch.get_default_dtype() during init
50
# to determine the output dtype. In real model loading this is bf16.
tests/kernels/core/test_vit_fp8_scaling.py
+5
-6
@@ -4,8 +4,7 @@
4
5
import contextlib
6
import json
7
-from types import SimpleNamespace
8
-from unittest.mock import patch
7
+from unittest.mock import MagicMock, patch
8
9
import pytest
10
import torch
@@ -48,7 +47,7 @@ def _build_attention(mm_config, attn_backend=None):
47
invokes ``process_weights_after_loading`` to simulate the model loader's
48
auto-scan. Yields ``None`` if FlashInfer cuDNN is not available.
49
"""
51
- from vllm.config import VllmConfig, set_current_vllm_config
50
+ from vllm.config import ModelConfig, VllmConfig, set_current_vllm_config
51
from vllm.model_executor.layers.attention.mm_encoder_attention import (
52
MMEncoderAttention,
53
)
@@ -65,7 +64,7 @@ def _build_attention(mm_config, attn_backend=None):
64
return
65
66
vllm_config = VllmConfig()
68
- vllm_config.model_config = SimpleNamespace(multimodal_config=mm_config)
67
+ vllm_config.model_config = MagicMock(spec=ModelConfig, multimodal_config=mm_config)
68
69
with (
70
set_current_vllm_config(vllm_config),
@@ -212,7 +211,7 @@ def test_aiter_static_scales_loaded(tmp_path) -> None:
211
212
def test_static_scales_missing_layer(tmp_path) -> None:
213
"""Verify error when requested layer is not in the scale file."""
215
- from vllm.config import VllmConfig, set_current_vllm_config
214
+ from vllm.config import ModelConfig, VllmConfig, set_current_vllm_config
215
from vllm.config.multimodal import MultiModalConfig
216
from vllm.v1.attention.backends.registry import AttentionBackendEnum
217
@@ -228,7 +227,7 @@ def test_static_scales_missing_layer(tmp_path) -> None:
227
mm_encoder_fp8_scale_path=str(scale_file),
228
)
229
vllm_config = VllmConfig()
231
- vllm_config.model_config = SimpleNamespace(multimodal_config=mm_config)
230
+ vllm_config.model_config = MagicMock(spec=ModelConfig, multimodal_config=mm_config)
231
232
from vllm.model_executor.layers.attention.mm_encoder_attention import (
233
MMEncoderAttention,
tests/kernels/mamba/cpu/test_cpu_gdn_ops.py
+24
-9
@@ -12,6 +12,7 @@ import vllm._custom_ops as ops
12
from vllm.model_executor.layers.mamba.ops.cpu import gdn_attention
13
from vllm.platforms import current_platform
14
from vllm.utils.torch_utils import set_random_seed
15
+from vllm.v1.attention.backends.gdn_attn import GDNAttentionMetadata
16
17
if not current_platform.is_cpu():
18
pytest.skip("skipping CPU-only tests", allow_module_level=True)
@@ -452,12 +453,17 @@ def test_spec_aware_mixed_routing_preserves_token_order(
453
454
spec_indices = torch.tensor([0, 2])
455
nonspec_indices = torch.tensor([1, 3])
455
- metadata = types.SimpleNamespace(
456
+ metadata = GDNAttentionMetadata(
457
+ num_prefills=1,
458
+ num_prefill_tokens=0,
459
+ num_decodes=0,
460
+ num_decode_tokens=0,
461
+ num_spec_decodes=0,
462
+ num_spec_decode_tokens=0,
463
+ num_actual_tokens=0,
464
spec_sequence_masks=torch.ones(1, dtype=torch.bool),
465
spec_token_indx=spec_indices,
466
non_spec_token_indx=nonspec_indices,
459
- num_prefills=1,
460
- num_decodes=0,
467
)
468
routed = []
469
@@ -501,13 +507,16 @@ def test_spec_aware_nonspec_materializes_state_indices(
507
state_indices = block_table[:, 0]
508
assert not state_indices.is_contiguous()
509
504
- metadata = types.SimpleNamespace(
505
- non_spec_state_indices_tensor=state_indices,
506
- non_spec_query_start_loc=torch.tensor([0, 2, 4], dtype=torch.int32),
507
- num_decodes=0,
508
- num_decode_tokens=0,
510
+ metadata = GDNAttentionMetadata(
511
num_prefills=2,
512
num_prefill_tokens=4,
513
+ num_decodes=0,
514
+ num_decode_tokens=0,
515
+ num_spec_decodes=0,
516
+ num_spec_decode_tokens=0,
517
+ num_actual_tokens=4,
518
+ non_spec_state_indices_tensor=state_indices,
519
+ non_spec_query_start_loc=torch.tensor([0, 2, 4], dtype=torch.int32),
520
has_initial_state=torch.tensor([False, False]),
521
)
522
@@ -575,8 +584,14 @@ def test_spec_forward_prepares_native_conv_metadata(
584
state_indices = block_table[:, 0]
585
accepted_counts = torch.tensor([1, 4], dtype=torch.int32)
586
assert not state_indices.is_contiguous()
578
- metadata = types.SimpleNamespace(
587
+ metadata = GDNAttentionMetadata(
588
+ num_prefills=0,
589
+ num_prefill_tokens=0,
590
+ num_decodes=0,
591
+ num_decode_tokens=0,
592
num_spec_decodes=2,
593
+ num_spec_decode_tokens=8,
594
+ num_actual_tokens=8,
595
spec_state_indices_tensor=block_table,
596
spec_query_start_loc=torch.tensor([0, 4, 8], dtype=torch.int32),
597
num_accepted_tokens=accepted_counts,
tests/kernels/mamba/test_gdn_forward_core_split.py
+5
-1
@@ -174,7 +174,9 @@ def test_forward_core_split_matches_unified(
174
batch = BatchSpec(seq_lens=seq_lens, query_lens=query_lens)
175
176
builder = GDNAttentionMetadataBuilder(
177
- kv_cache_spec=MambaSpec(
177
+ # GDNAttentionMetadataBuilder declares kv_cache_spec as AttentionSpec but
178
+ # asserts isinstance(kv_cache_spec, MambaSpec). MambaSpec is correct here.
179
+ kv_cache_spec=MambaSpec( # type: ignore[arg-type]
180
block_size=BLOCK_SIZE, shapes=((16, 64),), dtypes=(torch.float16,)
181
),
182
layer_names=[PREFIX],
@@ -198,6 +200,7 @@ def test_forward_core_split_matches_unified(
200
# Full-batch chunk metadata for the unified reference path, built the same
201
# way the builder would for a non-split batch (backend-matched).
202
cu_full = meta_split.non_spec_query_start_loc
203
+ assert cu_full is not None
204
if builder.gdn_prefill_backend == "cutedsl":
205
from vllm.model_executor.layers.mamba.ops.gdn_chunk_cutedsl import (
206
prepare_metadata_cutedsl,
@@ -227,6 +230,7 @@ def test_forward_core_split_matches_unified(
230
)
231
232
# Size the state pools from the indices the builder actually produced.
233
+ assert meta_split.non_spec_state_indices_tensor is not None
234
pool_size = int(meta_split.non_spec_state_indices_tensor.max().item()) + 1
235
conv_state_shape, temporal_state_shape = (
236
MambaStateShapeCalculator.gated_delta_net_state_shape(
tests/kernels/mamba/test_precopy_mamba_align.py
+14
-7
@@ -21,7 +21,9 @@ The kernel must also no-op when ``src_col < 0`` (fresh request) or
21
22
from __future__ import annotations
23
24
+from collections.abc import Callable
25
from types import SimpleNamespace
26
+from typing import Any
27
28
import numpy as np
29
import torch
@@ -31,6 +33,8 @@ from vllm.platforms import current_platform
33
from vllm.v1.worker import mamba_utils as worker_mamba_utils
34
from vllm.v1.worker.mamba_utils import precopy_mamba_align_fused_kernel
35
36
+_parametrize: Callable[..., Callable[[Any], Any]]
37
+
38
try:
39
import pytest
40
@@ -40,17 +44,18 @@ try:
44
)
45
_parametrize = pytest.mark.parametrize
46
except ModuleNotFoundError: # allow running directly as ``python <thisfile>``
43
- pytest = None
47
48
def _cuda_required(fn):
49
return fn
50
48
- def _parametrize(_name, _values):
51
+ def _no_parametrize(_name, _values):
52
def _deco(fn):
53
return fn
54
55
return _deco
56
57
+ _parametrize = _no_parametrize
58
+
59
60
NUM_LAYERS = 3
61
CONV_WIDTH = 4 # conv_kernel - 1 + num_spec
@@ -308,8 +313,10 @@ def _make_preprocess_case(token_bias):
313
def test_preprocess_fused_align_matches_scalar_bookkeeping(monkeypatch, token_bias):
314
block_size = 4
315
mamba_spec = SimpleNamespace(block_size=block_size, num_speculative_blocks=1)
311
- cache_config = SimpleNamespace(enable_prefix_caching=True)
312
- kv_cache_config = SimpleNamespace()
316
+ # Fakes stand in for real config/context objects. The fused path tests
317
+ # below only touch the attributes preprocess_mamba actually reads.
318
+ cache_config: Any = SimpleNamespace(enable_prefix_caching=True)
319
+ kv_cache_config: Any = SimpleNamespace()
320
scalar_copy_calls = []
321
322
def fake_collect(
@@ -340,7 +347,7 @@ def test_preprocess_fused_align_matches_scalar_bookkeeping(monkeypatch, token_bi
347
scalar_case = _make_preprocess_case(token_bias)
348
fused_case = _make_preprocess_case(token_bias)
349
343
- scalar_copy_bufs = SimpleNamespace(
350
+ scalar_copy_bufs: Any = SimpleNamespace(
351
mamba_group_ids=[0],
352
mamba_spec=mamba_spec,
353
offset=0,
@@ -357,8 +364,8 @@ def test_preprocess_fused_align_matches_scalar_bookkeeping(monkeypatch, token_bi
364
copy_bufs=scalar_copy_bufs,
365
)
366
360
- ctx = _FakePrecopyContext(len(fused_case[1].req_ids))
361
- fused_copy_bufs = SimpleNamespace(
367
+ ctx: Any = _FakePrecopyContext(len(fused_case[1].req_ids))
368
+ fused_copy_bufs: Any = SimpleNamespace(
369
mamba_group_ids=[0],
370
mamba_spec=mamba_spec,
371
offset=0,
tests/models/language/generation/test_mistral.py
+3
-3
@@ -261,7 +261,7 @@ def test_mistral_function_calling(vllm_runner, model: str, dtype: str) -> None:
261
262
model_output = outputs[0].outputs[0].text.strip()
263
assert model_output.startswith(tool_parser.bot_token), model_output
264
- parsed_message = tool_parser.extract_tool_calls(model_output, None)
264
+ parsed_message = tool_parser.extract_tool_calls(model_output, None) # type: ignore[arg-type]
265
266
assert parsed_message.tools_called
267
@@ -304,7 +304,7 @@ def test_mistral_function_call_nested_json():
304
305
model_output = f"{parser.bot_token}get_current_weather{json.dumps(args_dict)}"
306
307
- parsed = parser.extract_tool_calls(model_output, None)
307
+ parsed = parser.extract_tool_calls(model_output, None) # type: ignore[arg-type]
308
309
# Assertions: the tool call is detected and the full nested JSON is parsed
310
# without truncation.
@@ -337,7 +337,7 @@ def test_mistral_function_call_nested_json():
337
]
338
)
339
340
- parsed = parser.extract_tool_calls(model_output, None)
340
+ parsed = parser.extract_tool_calls(model_output, None) # type: ignore[arg-type]
341
342
# Assertions: the tool call is detected and the full nested JSON is parsed
343
# without truncation.
tests/models/quantization/test_bitsandbytes.py
+1
-1
@@ -323,7 +323,7 @@ def test_bitsandbytes_passes_revision_by_name():
323
return_value=["/folder/model.safetensors"],
324
),
325
):
326
- bnb.BitsAndBytesModelLoader._prepare_weights(fake_self, "org/model", "myrev")
326
+ bnb.BitsAndBytesModelLoader._prepare_weights(fake_self, "org/model", "myrev") # type: ignore[arg-type]
327
328
mock_idx.assert_called_once()
329
assert mock_idx.call_args.kwargs.get("revision") == "myrev"
tests/plugins/bge_m3_sparse_plugin/bge_m3_sparse_processor/sparse_embeddings_processor.py
+3
-3
@@ -29,7 +29,7 @@ class BgeM3SparseEmbeddingsProcessor(
29
self.online_requests: dict[str, SparseEmbeddingCompletionRequestMixin] = {}
30
self.renderer: BaseRenderer = renderer
31
self.default_pooling_params = {}
32
- pooler_config: PoolerConfig = vllm_config.model_config.pooler_config
32
+ pooler_config: PoolerConfig | None = vllm_config.model_config.pooler_config
33
if pooler_config is not None:
34
for param in ["use_activation", "dimensions"]:
35
if getattr(pooler_config, param, None) is None:
@@ -91,11 +91,11 @@ class BgeM3SparseEmbeddingsProcessor(
91
) -> list[SparseEmbeddingTokenWeight]:
92
token_ids = sparse_embedding.keys()
93
token_weights = sparse_embedding.values()
94
- tokens = [None] * len(token_ids)
94
+ tokens: Sequence[str | None] = [None] * len(token_ids)
95
96
if return_tokens and self.renderer is not None:
97
tokens = convert_ids_list_to_tokens(
98
- self.renderer.get_tokenizer(), token_ids
98
+ self.renderer.get_tokenizer(), list(token_ids)
99
)
100
sparse_embedding_output: list[SparseEmbeddingTokenWeight] = []
101
for token_id, weight, token in zip(token_ids, token_weights, tokens):
tests/plugins/prithvi_io_processor_plugin/prithvi_io_processor/prithvi_processor.py
+6
-6
@@ -170,7 +170,7 @@ def load_image(
170
list of meta info for each image in *file_paths*
171
"""
172
173
- imgs = []
173
+ imgs: list[np.ndarray] = []
174
metas = []
175
temporal_coords = []
176
location_coords = []
@@ -209,11 +209,11 @@ def load_image(
209
except Exception:
210
logger.exception("Could not extract timestamp for %s", file)
211
212
- imgs = np.stack(imgs, axis=0) # num_frames, H, W, C
213
- imgs = np.moveaxis(imgs, -1, 0).astype("float32") # C, num_frames, H, W
214
- imgs = np.expand_dims(imgs, axis=0) # add batch di
212
+ stacked = np.stack(imgs, axis=0) # num_frames, H, W, C
213
+ stacked = np.moveaxis(stacked, -1, 0).astype("float32") # C, num_frames, H, W
214
+ stacked = np.expand_dims(stacked, axis=0) # add batch di
215
216
- return imgs, temporal_coords, location_coords, metas
216
+ return stacked, temporal_coords, location_coords, metas
217
218
219
class PrithviMultimodalDataProcessor(IOProcessor[ImagePrompt, ImageRequestOutput]):
@@ -327,7 +327,7 @@ class PrithviMultimodalDataProcessor(IOProcessor[ImagePrompt, ImageRequestOutput
327
}
328
)
329
330
- return prompts
330
+ return prompts # type: ignore[return-value]
331
332
def post_process(
333
self,
tests/plugins/vllm_add_dummy_platform/vllm_add_dummy_platform/dummy_platform.py
+8
-11
@@ -6,6 +6,8 @@ from vllm.platforms.interface import Platform, PlatformEnum
6
7
if TYPE_CHECKING:
8
from vllm.config import VllmConfig
9
+ from vllm.v1.attention.backends.registry import AttentionBackendEnum
10
+ from vllm.v1.attention.selector import AttentionSelectorConfig
11
else:
12
VllmConfig = None
13
@@ -20,16 +22,11 @@ class DummyPlatform(Platform):
22
def check_and_update_config(cls, vllm_config: VllmConfig) -> None:
23
vllm_config.compilation_config.custom_ops = ["all"]
24
25
+ @classmethod
26
def get_attn_backend_cls(
24
- self,
25
- backend_name,
26
- head_size,
27
- dtype,
28
- kv_cache_dtype,
29
- block_size,
30
- use_mla,
31
- has_sink,
32
- use_sparse,
33
- use_mm_prefix,
34
- ):
27
+ cls,
28
+ selected_backend: "AttentionBackendEnum",
29
+ attn_selector_config: "AttentionSelectorConfig",
30
+ num_heads: int | None = None,
31
+ ) -> str:
32
return "vllm_add_dummy_platform.dummy_attention_backend.DummyAttentionBackend" # noqa E501
tests/plugins/vllm_add_dummy_stat_logger/dummy_stat_logger/dummy_stat_logger.py
+3
-1
@@ -17,7 +17,9 @@ class DummyStatLogger(StatLoggerBase):
17
self.logged = False
18
self.engine_initialized = False
19
20
- def record(self, scheduler_stats, iteration_stats, mm_cache_stats, engine_idx):
20
+ def record(
21
+ self, scheduler_stats, iteration_stats, mm_cache_stats=None, engine_idx=0
22
+ ):
23
self.recorded.append(
24
(scheduler_stats, iteration_stats, mm_cache_stats, engine_idx)
25
)
tests/plugins_tests/gguf/test_gguf_plugin_multimodal.py
+1
-1
@@ -92,7 +92,7 @@ def run_multimodal_gguf_test(
92
num_logprobs: int,
93
):
94
# Load images at runtime (inside subprocess) to avoid pickle issues
95
- images = [ImageAsset(name).pil_image for name in model.image_names]
95
+ images = [ImageAsset(name).pil_image for name in model.image_names] # type: ignore[arg-type]
96
size_factors = [0.25, 0.5, 1.0]
97
inputs_per_image = [
98
(
tests/plugins_tests/lora_resolvers/test_hf_hub_resolver.py
+1
@@ -31,6 +31,7 @@ async def test_hf_resolver_with_direct_path():
31
assert hf_resolver is not None
32
33
lora_request = await hf_resolver.resolve_lora(LORA_REPO_MODEL_NAME, LORA_REPO)
34
+ assert lora_request is not None
35
assert lora_request.lora_name == LORA_REPO
36
assert REPO_DOWNLOAD_DIR in lora_request.lora_path
37
assert "adapter_config.json" in os.listdir(lora_request.lora_path)
tests/spec_decode/test_custom_proposer.py
+1
@@ -30,6 +30,7 @@ class DummyDraftProposer:
30
Args:
31
vllm_config: vLLM configuration containing model and speculative settings.
32
"""
33
+ assert vllm_config.speculative_config is not None
34
self.num_speculative_tokens = (
35
vllm_config.speculative_config.num_speculative_tokens
36
)
tests/transformers_utils/test_processor.py
+2
-2
@@ -44,7 +44,7 @@ class _ProcWithUnpack:
44
45
def test_get_processor_kwargs_from_processor_unpack_path_returns_full_union():
46
proc = _ProcWithUnpack()
47
- keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc))
47
+ keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc)) # type: ignore[arg-type]
48
_assert_has_all_expected(keys)
49
50
@@ -63,5 +63,5 @@ def test_get_processor_kwargs_from_processor_module_scan_returns_full_union():
63
assert hasattr(mod, "_FakeProcessorKwargs")
64
65
proc = _ProcWithoutUnpack()
66
- keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc))
66
+ keys = get_processor_kwargs_keys(get_processor_kwargs_type(proc)) # type: ignore[arg-type]
67
_assert_has_all_expected(keys)
tests/v1/distributed/test_async_llm_dp.py
+5
-3
@@ -12,13 +12,14 @@ import pytest
12
13
from vllm import SamplingParams
14
from vllm.config import VllmConfig
15
+from vllm.config.parallel import DataParallelBackend
16
from vllm.engine.arg_utils import AsyncEngineArgs
17
from vllm.inputs import PromptType
18
from vllm.outputs import RequestOutput
19
from vllm.platforms import current_platform
20
from vllm.sampling_params import RequestOutputKind
21
from vllm.v1.engine.async_llm import AsyncLLM
21
-from vllm.v1.engine.core_client import DPAsyncMPClient
22
+from vllm.v1.engine.core_client import DPLBAsyncMPClient
23
from vllm.v1.metrics.loggers import StatLoggerBase
24
from vllm.v1.metrics.stats import IterationStats, MultiModalCacheStats, SchedulerStats
25
@@ -82,7 +83,7 @@ async def generate(
83
async def test_load(
84
model: str,
85
output_kind: RequestOutputKind,
85
- data_parallel_backend: str,
86
+ data_parallel_backend: DataParallelBackend,
87
async_scheduling: bool,
88
):
89
if async_scheduling and data_parallel_backend == "ray":
@@ -162,7 +163,8 @@ async def test_load(
163
assert not engine.output_processor.has_unfinished_requests()
164
165
# testing internals here which may break
165
- core_client: DPAsyncMPClient = engine.engine_core
166
+ core_client = engine.engine_core
167
+ assert isinstance(core_client, DPLBAsyncMPClient)
168
# the engines only synchronize stopping every N steps so
169
# allow a small amount of time here.
170
for _ in range(10):
tests/v1/distributed/test_eagle_dp.py
+1
-1
@@ -61,7 +61,7 @@ async def test_run_eagle_dp(monkeypatch: pytest.MonkeyPatch, attn_backend: str):
61
data_parallel_backend="mp", # ray takes more time
62
trust_remote_code=True,
63
max_model_len=16384,
64
- attention_config={"backend": attn_backend},
64
+ attention_config={"backend": attn_backend}, # type: ignore[arg-type]
65
)
66
67
eagle_engine_args = replace(
tests/v1/shutdown/test_processor_error.py
+8
-3
@@ -9,7 +9,7 @@ import pytest
9
from tests.v1.shutdown.utils import SHUTDOWN_TEST_TIMEOUT_SEC
10
from vllm import SamplingParams
11
from vllm.engine.arg_utils import AsyncEngineArgs
12
-from vllm.inputs import TokensPrompt
12
+from vllm.inputs import ExplicitEncoderDecoderPrompt
13
from vllm.sampling_params import RequestOutputKind
14
from vllm.v1.engine.async_llm import AsyncLLM
15
from vllm.v1.engine.exceptions import EngineGenerateError
@@ -29,9 +29,14 @@ async def test_async_llm_processor_error(model: str) -> None:
29
async_llm = AsyncLLM.from_engine_args(engine_args)
30
31
async def generate(request_id: str):
32
- # [] is not allowed and will raise a ValueError in Processor.
32
+ # An encoder/decoder prompt is rejected by the Processor for a
33
+ # decoder only model.
34
generator = async_llm.generate(
34
- TokensPrompt([]), request_id=request_id, sampling_params=SamplingParams()
35
+ ExplicitEncoderDecoderPrompt(
36
+ encoder_prompt="Hello my name is", decoder_prompt=None
37
+ ),
38
+ request_id=request_id,
39
+ sampling_params=SamplingParams(),
40
)
41
try:
42
async for _ in generator:
tools/pre_commit/mypy.py
+41
-24
@@ -21,34 +21,55 @@ import sys
21
22
import regex as re
23
24
+# Paths verified clean under follow_imports="silent". Matched before
25
+# SEPARATE_GROUPS, so these files join the default group and are checked at the
26
+# stricter setting even while a parent directory remains in SEPARATE_GROUPS.
27
+#
28
+# Fixing a directory means moving it from SEPARATE_GROUPS to here. Without that
29
+# move the fixes are not enforced because "tests" claims every file below it.
30
+SILENT_GROUPS = [
31
+ "tests/compile/correctness_e2e",
32
+ "tests/compile/fullgraph",
33
+ "tests/compile/fusions_e2e",
34
+ "tests/config",
35
+ "tests/entrypoints/generate",
36
+ "tests/entrypoints/tool_parsers",
37
+ "tests/entrypoints/weight_transfer",
38
+ "tests/kernels/core",
39
+ "tests/kernels/mamba",
40
+ "tests/models/language",
41
+ "tests/models/quantization",
42
+ "tests/plugins/bge_m3_sparse_plugin",
43
+ "tests/plugins/prithvi_io_processor_plugin",
44
+ "tests/plugins/vllm_add_dummy_platform",
45
+ "tests/plugins/vllm_add_dummy_stat_logger",
46
+ "tests/plugins_tests/gguf",
47
+ "tests/plugins_tests/lora_resolvers",
48
+ "tests/spec_decode",
49
+ "tests/transformers_utils",
50
+ "tests/v1/distributed",
51
+ "tests/v1/shutdown",
52
+]
53
+
54
# After fixing errors resulting from changing follow_imports
25
-# from "skip" to "silent", remove its directory from SEPARATE_GROUPS.
55
+# from "skip" to "silent", move its directory to SILENT_GROUPS.
56
SEPARATE_GROUPS = [
57
"tests",
58
"tests/benchmarks",
29
- "tests/compile/correctness_e2e",
30
- "tests/config",
59
"tests/compile",
32
- "tests/compile/fullgraph",
33
- "tests/compile/fusions_e2e",
60
"tests/compile/passes",
61
"tests/distributed",
62
"tests/entrypoints/anthropic",
37
- "tests/entrypoints/generate",
63
"tests/entrypoints/llm",
64
"tests/entrypoints/multimodal",
65
"tests/entrypoints/openai",
66
"tests/entrypoints/pooling",
67
"tests/entrypoints/serve",
68
"tests/entrypoints/speech_to_text",
44
- "tests/entrypoints/tool_parsers",
69
"tests/entrypoints/unit_tests",
46
- "tests/entrypoints/weight_transfer",
70
"tests/kernels",
71
"tests/kernels/attention",
49
- "tests/kernels/core",
72
"tests/kernels/helion",
51
- "tests/kernels/mamba",
73
"tests/kernels/moe",
74
"tests/kernels/quantization",
75
"tests/lora",
@@ -57,34 +78,23 @@ SEPARATE_GROUPS = [
78
"tests/model_executor/model_loader",
79
"tests/models",
80
"tests/models/test_initialization.py",
60
- "tests/models/language",
81
"tests/models/multimodal",
62
- "tests/models/quantization",
82
"tests/multimodal",
83
"tests/parser",
65
- "tests/plugins_tests/gguf",
66
- "tests/plugins_tests/lora_resolvers",
67
- "tests/plugins/bge_m3_sparse_plugin",
68
- "tests/plugins/prithvi_io_processor_plugin",
69
- "tests/plugins/vllm_add_dummy_platform",
70
- "tests/plugins/vllm_add_dummy_stat_logger",
84
"tests/plugins_tests",
85
"tests/quantization",
86
"tests/reasoning",
87
"tests/renderers",
88
"tests/samplers",
76
- "tests/spec_decode",
89
"tests/tokenizers_",
90
"tests/tool_parsers",
91
"tests/tool_use",
80
- "tests/transformers_utils",
92
"tests/utils_",
93
"tests/v1",
94
"tests/v1/attention",
95
"tests/v1/core",
96
"tests/v1/cudagraph",
97
"tests/v1/determinism",
87
- "tests/v1/distributed",
98
"tests/v1/e2e",
99
"tests/v1/ec_connector",
100
"tests/v1/engine",
@@ -94,7 +104,6 @@ SEPARATE_GROUPS = [
104
"tests/v1/logits_processors",
105
"tests/v1/metrics",
106
"tests/v1/sample",
97
- "tests/v1/shutdown",
107
"tests/v1/simple_kv_offload",
108
"tests/v1/spec_decode",
109
"tests/v1/streaming_input",
@@ -142,14 +151,22 @@ def group_files(changed_files: list[str]) -> dict[str, list[str]]:
151
A dictionary mapping file group names to lists of changed files.
152
"""
153
exclude_pattern = re.compile(f"^{'|'.join(EXCLUDE)}.*")
145
- file_groups = {"": []}
154
+ silent_pattern = re.compile(f"^({'|'.join(SILENT_GROUPS)}).*")
155
+ file_groups: dict[str, list[str]] = {"": []}
156
file_groups.update({k: [] for k in SEPARATE_GROUPS})
157
+ # Longest path first so a sub-directory is not shadowed by its parent
158
+ separate_groups = sorted(SEPARATE_GROUPS, key=len, reverse=True)
159
for changed_file in changed_files:
160
# Skip files which should be ignored completely
161
if exclude_pattern.match(changed_file):
162
continue
163
+ # Already-fixed paths go in the default group, which runs at the
164
+ # stricter follow_imports setting from pyproject.toml
165
+ if silent_pattern.match(changed_file):
166
+ file_groups[""].append(changed_file)
167
+ continue
168
# Group files by mypy call
152
- for directory in SEPARATE_GROUPS:
169
+ for directory in separate_groups:
170
if re.match(f"^{directory}.*", changed_file):
171
file_groups[directory].append(changed_file)
172
break