[CI] Ignore ruff D209, rejoin the docstrings it split, and silence incompatible-rule warnings (#57212)
Signed-off-by: Harry Mellor <19981378+hmellor@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Harry Mellor committed
Sep 16, 2026 at 18:57 UTC
651a88c09ac6cbb13c5dd36f2fdbe61a2c68eeef
693 files changed
+2088
-4171
benchmarks/benchmark_hidden_state_extraction.py
+1
-2
@@ -136,8 +136,7 @@ async def _client_loop(
136
client_id: int,
137
):
138
"""A single async client: pulls prompts, submits to engine, consumes
139
- hidden states as soon as each request finishes.
140
- """
139
+ hidden states as soon as each request finishes."""
140
loop = asyncio.get_event_loop()
141
while True:
142
item = await prompt_queue.get()
benchmarks/fused_kernels/merge_attn_states_benchmarks.py
+1
-2
@@ -84,8 +84,7 @@ def make_inputs(
84
85
def build_configs(head_configs, num_tokens_list, input_dtypes, tp_sizes):
86
"""Build (num_tokens, num_heads, head_size, dtype_str) config tuples,
87
- applying TP division to num_heads and skipping invalid combos.
88
- """
87
+ applying TP division to num_heads and skipping invalid combos."""
88
configs = []
89
for (_, nh, hs), nt, dtype, tp in itertools.product(
90
head_configs, num_tokens_list, input_dtypes, tp_sizes
benchmarks/kernels/benchmark_moe_defaults.py
+1
-2
@@ -32,8 +32,7 @@ FP8_DTYPE = current_platform.fp8_dtype()
32
33
def old_default_config(M, E, N, K, topk, dtype=None, block_shape=None):
34
"""The original defaults before https://github.com/vllm-project/vllm/pull/34846,
35
- for comparison.
36
- """
35
+ for comparison."""
36
if dtype == "fp8_w8a8" and block_shape is not None:
37
return {
38
"BLOCK_SIZE_M": 64,
benchmarks/kernels/benchmark_vocab_parallel_embedding.py
+1
-2
@@ -97,8 +97,7 @@ def graph_replay(fn):
97
98
def calculate_diff(vocab_size, hidden_size, tp_size, num_tokens):
99
"""The fused kernel must be bit-exact with the path it replaces, on every
100
- rank of the shard.
101
- """
100
+ rank of the shard."""
101
dtype = torch.bfloat16
102
for tp_rank in range(tp_size):
103
input_ids, weight, shard_indices = make_inputs(
docs/mkdocs/gen_files/generate_examples.py
+2
-4
@@ -75,8 +75,7 @@ class Example:
75
76
If path is a file, it returns the path itself. If path is a directory, it
77
searches for Markdown files (*.md) in the directory and returns the first one
78
- found. If no Markdown files are found, it returns None.
79
- """
78
+ found. If no Markdown files are found, it returns None."""
79
# Single file example
80
if self.path.is_file():
81
return self.path
@@ -91,8 +90,7 @@ class Example:
90
"""Determine other files in the directory excluding the main file.
91
92
If path is a file, it returns an empty list. Otherwise, it returns every file
94
- in the directory except the main file in a list.
95
- """
93
+ in the directory except the main file in a list."""
94
# Single file example
95
if self.path.is_file():
96
return []
examples/features/logits_processor/custom_req.py
+2
-4
@@ -55,8 +55,7 @@ logger = init_logger(__name__)
55
56
class DummyPerReqLogitsProcessor:
57
"""The request-level logits processor masks out all logits except the
58
- token id identified by `target_token`
59
- """
58
+ token id identified by `target_token`"""
59
60
def __init__(self, target_token: int) -> None:
61
"""Specify `target_token`."""
@@ -75,8 +74,7 @@ class DummyPerReqLogitsProcessor:
74
75
class WrappedPerReqLogitsProcessor(AdapterLogitsProcessor):
76
"""Example of wrapping a fake request-level logit processor to create a
78
- batch-level logits processor
79
- """
77
+ batch-level logits processor"""
78
79
@classmethod
80
def validate_params(cls, params: SamplingParams):
examples/features/logits_processor/custom_req_init.py
+2
-4
@@ -56,8 +56,7 @@ logger = init_logger(__name__)
56
57
class DummyPerReqLogitsProcessor:
58
"""The request-level logits processor masks out all logits except the
59
- token id identified by `target_token`
60
- """
59
+ token id identified by `target_token`"""
60
61
def __init__(self, target_token: int) -> None:
62
"""Specify `target_token`."""
@@ -76,8 +75,7 @@ class DummyPerReqLogitsProcessor:
75
76
class WrappedPerReqLogitsProcessor(AdapterLogitsProcessor):
77
"""Example of overriding the wrapper class `__init__()` in order to utilize
79
- info about the device type
80
- """
78
+ info about the device type"""
79
80
@classmethod
81
def validate_params(cls, params: SamplingParams):
examples/rl/rlhf_sharded_rdt_small_ep.py
+1
-2
@@ -101,8 +101,7 @@ PROMPTS = ["The capital of France is", "The future of AI is"]
101
class FSDPTrainWorker:
102
"""One FSDP2 rank per GPU. Identical to the 8-GPU example's worker: the
103
sharded-RDT engine owns the NIXL serve surface, so this stays a plain Ray
104
- actor with no producer mixin.
105
- """
104
+ actor with no producer mixin."""
105
106
def __init__(self, model_name, rank, world_size, master_addr, master_port):
107
self.rank = rank
pyproject.toml
+3
-1
@@ -90,7 +90,9 @@ ignore = [
90
# don't enforce that everything has a docstring
91
"D100", "D101", "D102", "D103", "D104", "D105", "D106", "D107",
92
# unwanted pydocstyle rules
93
- "D205", "D301", "D400", "D401", "D404", "D415",
93
+ "D205", "D209", "D301", "D400", "D401", "D404", "D415",
94
+ # incompatible pydocstyle pairs; pin the half `ruff` already picks
95
+ "D203", "D213",
96
# star imports
97
"F405", "F403",
98
# lambda expression assignment
setup.py
+1
-2
@@ -724,8 +724,7 @@ class precompiled_wheel_utils:
724
wheels: list[dict], repo_url: str, arch: str
725
) -> None:
726
"""Warn if installed torch differs from the custom ROCm build on
727
- wheels.vllm.ai and suggest the correct install command.
728
- """
727
+ wheels.vllm.ai and suggest the correct install command."""
728
try:
729
installed = torch.__version__
730
except Exception:
tests/basic_correctness/test_mem.py
+1
-2
@@ -112,8 +112,7 @@ def test_basic_cumem():
112
@create_new_process_for_each_test("fork" if current_platform.is_cuda() else "spawn")
113
def test_discard_tags():
114
"""Test that discard(tags) selectively frees GPU memory for specific
115
- tags while keeping other tags mapped and usable.
116
- """
115
+ tags while keeping other tags mapped and usable."""
116
allocator = get_mem_allocator_instance()
117
118
with allocator.use_memory_pool("weights"):
tests/benchmarks/test_bfcl_dataset.py
+6
-12
@@ -13,8 +13,7 @@ from vllm.benchmarks.datasets import BFCLDataset, get_samples
13
14
def _patch_hf_api(side_effect):
15
"""Return a patch context that swaps `hf_api()` to a stub whose
16
- `.hf_hub_download` attribute uses `side_effect`.
17
- """
16
+ `.hf_hub_download` attribute uses `side_effect`."""
17
fake_api = MagicMock()
18
fake_api.hf_hub_download.side_effect = side_effect
19
return patch("vllm.benchmarks.datasets.datasets.hf_api", return_value=fake_api)
@@ -116,8 +115,7 @@ def test_bfcl_dataset_translates_schema_and_attaches_tools(
115
) -> None:
116
"""BFCLDataset should translate schemas to OpenAI tool format, set
117
`messages` directly on SampleRequest, and attach tools/tool_choice via
119
- request_overrides.
120
- """
118
+ request_overrides."""
119
paths = _write_fake_files(tmp_path)
120
121
def fake_download(_repo, filename, **_kwargs):
@@ -168,8 +166,7 @@ def test_bfcl_dataset_missing_category_raises_clear_error(
166
hf_tokenizer: PreTrainedTokenizerBase,
167
) -> None:
168
"""A typo'd category should produce an actionable ValueError, not an
171
- opaque huggingface_hub exception.
172
- """
169
+ opaque huggingface_hub exception."""
170
from huggingface_hub.errors import EntryNotFoundError
171
172
args = _args_for_bfcl(categories=["simpl"]) # typo
@@ -187,8 +184,7 @@ def test_bfcl_dataset_missing_category_raises_clear_error(
184
@pytest.mark.benchmark
185
def test_chat_backend_uses_messages_field_when_set() -> None:
186
"""When RequestFuncInput.chat_messages is set, the chat backend must use
190
- it verbatim and skip default content construction from `prompt`.
191
- """
187
+ it verbatim and skip default content construction from `prompt`."""
188
import asyncio
189
190
from vllm.benchmarks.lib.endpoint_request_func import (
@@ -248,8 +244,7 @@ def test_chat_backend_uses_messages_field_when_set() -> None:
244
def test_bfcl_prompt_len_includes_tools(tmp_path: Path) -> None:
245
"""prompt_len must reflect tokens from both messages *and* tool schemas,
246
so percentile buckets and input-distribution summaries aren't biased
251
- low for tool-heavy traffic.
252
- """
247
+ low for tool-heavy traffic."""
248
paths = _write_fake_files(tmp_path)
249
250
def fake_download(_repo, filename, **_kwargs):
@@ -296,8 +291,7 @@ def test_bfcl_prompt_len_falls_back_when_tokenizer_rejects_tools(
291
tmp_path: Path,
292
) -> None:
293
"""Older tokenizers don't accept tools=; fallback must still produce a
299
- non-zero prompt_len without crashing.
300
- """
294
+ non-zero prompt_len without crashing."""
295
paths = _write_fake_files(tmp_path)
296
297
def fake_download(_repo, filename, **_kwargs):
tests/benchmarks/test_custom_dataset_chat_template_kwargs.py
+1
-2
@@ -12,8 +12,7 @@ from vllm.benchmarks.datasets import get_samples
12
class _RecordingTokenizer:
13
"""Minimal tokenizer stub that records the kwargs forwarded to
14
apply_chat_template, so we can assert chat_template_kwargs propagation
15
- without loading a real model/template.
16
- """
15
+ without loading a real model/template."""
16
17
def __init__(self) -> None:
18
self.captured_kwargs: dict | None = None
tests/benchmarks/test_sampling_params.py
+3
-6
@@ -10,8 +10,7 @@ from vllm.tokenizers import TokenizerLike
10
11
class _FakeTokenizer(TokenizerLike):
12
"""Minimal tokenizer implementing the TokenizerLike protocol
13
- for testing get_sampling_params.
14
- """
13
+ for testing get_sampling_params."""
14
15
def __init__(self, vocab_size: int = 1000, num_special_tokens: int = 0) -> None:
16
self._vocab_size = vocab_size
@@ -172,8 +171,7 @@ class TestGetSamplingParams:
171
172
def test_output_low_clamped_to_one(self):
173
"""Even with a high ratio that would push output_low to 0,
175
- the function clamps it to 1.
176
- """
174
+ the function clamps it to 1."""
175
rng = np.random.default_rng(0)
176
# output_len=1, ratio=0.99 → floor(1*0.01)=0, should clamp to 1
177
_, output_lens, _ = get_sampling_params(
@@ -235,8 +233,7 @@ class TestGetSamplingParams:
233
234
def test_input_len_zero_with_special_tokens(self):
235
"""input_len < num_special_tokens → real_input_len = 0, which is fine
238
- (range [0, 0]).
239
- """
236
+ (range [0, 0])."""
237
rng = np.random.default_rng(0)
238
input_lens, _, _ = get_sampling_params(
239
rng, 5, 0.0, 5, 50, self._tok(num_special=10)
tests/benchmarks/test_skip_tokenizer_init.py
+1
-2
@@ -52,8 +52,7 @@ def _write_dataset(path: Path) -> None:
52
53
def _args(dataset_path: str) -> argparse.Namespace:
54
"""Reproduce the argparse.Namespace that serve.py builds from the
55
- failing command, including skip_tokenizer_init=True.
56
- """
55
+ failing command, including skip_tokenizer_init=True."""
56
return argparse.Namespace(
57
# dataset
58
dataset_name="custom",
tests/compile/passes/test_fusion.py
+1
-2
@@ -732,8 +732,7 @@ def test_aiter_fusion_rmsnorm_gated_quant_no_gdn_layers(
732
monkeypatch: pytest.MonkeyPatch,
733
):
734
"""Verify that without GDN layers in static_forward_context,
735
- the gated pattern is not registered and no matches occur.
736
- """
735
+ the gated pattern is not registered and no matches occur."""
736
group_shape = GroupShape(1, 128)
737
vllm_config = VllmConfig(
738
model_config=ModelConfig(dtype=dtype),
tests/compile/passes/test_split_coalescing.py
+1
-2
@@ -15,8 +15,7 @@ DEVICE_TYPE = current_platform.device_type
15
16
class SplitCoalescingModel(torch.nn.Module):
17
"""Model with 3 separate split_with_sizes calls on the same input,
18
- simulating the B200+FP8 graph where CSE fails to merge them.
19
- """
18
+ simulating the B200+FP8 graph where CSE fails to merge them."""
19
20
def __init__(self, q_size: int, kv_size: int) -> None:
21
super().__init__()
tests/compile/test_codegen.py
+10
-20
@@ -77,8 +77,7 @@ def test_non_primitive_kwargs_lifted_to_consts(
77
into the namespace, so ``device`` is unbound. The fix collects such
78
objects into ``__vllm_consts__`` and references them by index. The
79
unqualified ``device(type=...)`` form must never appear in the
80
- generated source.
81
- """
80
+ generated source."""
81
split_gm = _trace_and_split(model_fn, (x,), split_ops)
82
code, submod_names, consts = generate_execution_code(split_gm)
83
@@ -99,8 +98,7 @@ def test_dtype_singleton_deduped(x: torch.Tensor) -> None:
98
"""``torch.float16`` is a process-wide singleton, so two ops referring
99
to it in the traced graph share a single consts slot via ``id()``-based
100
dedup. Distinct expressions (``x.to(...)`` vs ``(x*2).to(...)``) ensure
102
- the tracer can't CSE the two ops into a single node.
103
- """
101
+ the tracer can't CSE the two ops into a single node."""
102
103
def model_fn(x: torch.Tensor) -> torch.Tensor:
104
return x.to(dtype=torch.float16) + (x * 2).to(dtype=torch.float16)
@@ -149,8 +147,7 @@ def test_distinct_dtypes_get_distinct_slots(x: torch.Tensor) -> None:
147
def test_consts_ordering_deterministic(x: torch.Tensor) -> None:
148
"""Two independent traces of the same model must produce equal consts
149
lists *in the same order*. Cache artifacts identify const slots by
152
- index, so a non-deterministic order would invalidate cached code.
153
- """
150
+ index, so a non-deterministic order would invalidate cached code."""
151
152
def model_fn(x: torch.Tensor) -> torch.Tensor:
153
# Multiple distinct non-primitives encountered in a fixed graph order.
@@ -188,8 +185,7 @@ def test_consts_shared_across_split_submods(x: torch.Tensor) -> None:
185
The function below splits into three inlined submods, two of which
186
independently reference ``torch.float16``. The shared ``const_index``
187
threaded through recursive ``generate_execution_code_with_name`` calls
191
- must collapse the dtype to a single slot used from both submods.
192
- """
188
+ must collapse the dtype to a single slot used from both submods."""
189
190
def model_fn(x: torch.Tensor) -> torch.Tensor:
191
a = x.to(dtype=torch.float16) # submod_0: _to_copy(fp16)
@@ -234,8 +230,7 @@ def test_non_graphmodule_submod_uses_indexed_callable(x: torch.Tensor) -> None:
230
"""When a child of split_gm is *not* a ``torch.fx.GraphModule`` — as
231
happens in production once ``PiecewiseBackend`` replaces submods —
232
codegen emits ``__vllm_submods__[idx](...)`` instead of inlining, and
237
- the runtime callable is bound from ``submod_callables``.
238
- """
233
+ the runtime callable is bound from ``submod_callables``."""
234
235
def model_fn(x: torch.Tensor) -> torch.Tensor:
236
return x.relu().sigmoid()
@@ -285,8 +280,7 @@ def test_non_graphmodule_submod_uses_indexed_callable(x: torch.Tensor) -> None:
280
def test_getitem_in_stitching_graph(x: torch.Tensor) -> None:
281
"""``operator.getitem`` on submod tuple returns is the ``call_function``
282
special case at codegen.py — emitted as ``name = source[index]``
288
- rather than a function call.
289
- """
283
+ rather than a function call."""
284
285
def model_fn(x: torch.Tensor) -> torch.Tensor:
286
return x.relu().sigmoid()
@@ -304,8 +298,7 @@ def test_getitem_in_stitching_graph(x: torch.Tensor) -> None:
298
def test_del_emitted_for_intermediate_values(x: torch.Tensor) -> None:
299
"""The codegen schedules ``del`` after a value's last use to free
300
memory early. Multi-submod splits naturally have intermediates whose
307
- last use is not the output node.
308
- """
301
+ last use is not the output node."""
302
303
def model_fn(x: torch.Tensor) -> torch.Tensor:
304
return x.relu().sigmoid().tanh()
@@ -325,8 +318,7 @@ def test_with_submod_false_rejects_call_module() -> None:
318
"""``generate_execution_code_with_name(with_submod=False)`` is the
319
recursive entry for inlining a GraphModule into its parent. It must
320
refuse a graph that itself contains ``call_module`` nodes — the parent
328
- is responsible for handling those.
329
- """
321
+ is responsible for handling those."""
322
g = fx.Graph()
323
x_node = g.placeholder("x")
324
root = torch.nn.Module()
@@ -343,8 +335,7 @@ def test_node_ref_recurses_through_containers() -> None:
335
"""``_node_ref`` is the recursive walker that lifts non-primitives
336
nested inside list/tuple/dict args. Real aten ops rarely produce such
337
structures, but the path is needed for DTensor placement lists and
346
- other future cases — unit-test the walker directly.
347
- """
338
+ other future cases — unit-test the walker directly."""
339
consts: list = []
340
const_index: dict[int, int] = {}
341
cpu = torch.device("cpu")
@@ -368,8 +359,7 @@ def test_node_ref_recurses_through_containers() -> None:
359
def test_legacy_code_without_consts() -> None:
360
"""``compile_execution_fn(consts=None)`` must still load code that has
361
no ``__vllm_consts__`` reference, so older serialized cache artifacts
371
- keep working.
372
- """
362
+ keep working."""
363
# Pre-consts codegen: no __vllm_consts__ reference, only torch/operator.
364
legacy_code = (
365
"import torch\n"
tests/compile/test_compile_ranges.py
+2
-4
@@ -129,8 +129,7 @@ def test_compile_config_get_compile_ranges():
129
130
class PostGradStaticShapeChecker(InductorPass):
131
"""Asserts that compile_sizes entries produce graphs with fully concrete
132
- (non-symbolic) shapes, and compile_ranges entries have symbolic shapes.
133
- """
132
+ (non-symbolic) shapes, and compile_ranges entries have symbolic shapes."""
133
134
def __init__(self):
135
self.num_static_calls = 0
@@ -171,8 +170,7 @@ class PostGradStaticShapeChecker(InductorPass):
170
171
def test_compile_sizes_produce_static_shapes(disable_vllm_compile_cache):
172
"""Verify that compile_sizes entries are compiled with fully concrete
174
- shapes (no SymInts), while compile_ranges entries retain dynamic shapes.
175
- """
173
+ shapes (no SymInts), while compile_ranges entries retain dynamic shapes."""
174
checker = PostGradStaticShapeChecker()
175
torch.set_default_device("cuda")
176
vllm_config = VllmConfig(
tests/compile/test_config.py
+3
-6
@@ -1229,8 +1229,7 @@ def test_compile_sizes_padding_validation():
1229
1230
def test_inductor_asserts_default_disabled(monkeypatch):
1231
"""Test that inductor runtime asserts are disabled by default
1232
- (INFO logging level) on torch < 2.12.
1233
- """
1232
+ (INFO logging level) on torch < 2.12."""
1233
monkeypatch.setenv("VLLM_LOGGING_LEVEL", "INFO")
1234
1235
import importlib
@@ -1248,8 +1247,7 @@ def test_inductor_asserts_default_disabled(monkeypatch):
1247
1248
def test_inductor_asserts_enabled_in_debug(monkeypatch):
1249
"""Test that VLLM_LOGGING_LEVEL=DEBUG enables inductor runtime asserts
1251
- on torch < 2.12.
1252
- """
1250
+ on torch < 2.12."""
1251
monkeypatch.setenv("VLLM_LOGGING_LEVEL", "DEBUG")
1252
1253
import importlib
@@ -1285,8 +1283,7 @@ def test_get_inductor_factors_includes_configs():
1283
1284
def test_inductor_asserts_user_override(monkeypatch):
1285
"""Test that explicit inductor_compile_config overrides the
1288
- debug-logging default.
1289
- """
1286
+ debug-logging default."""
1287
monkeypatch.setenv("VLLM_LOGGING_LEVEL", "INFO")
1288
1289
import importlib
tests/compile/test_inductor_fallback_allow_list_patch.py
+1
-2
@@ -236,8 +236,7 @@ class TestInductorFallbackFastPath:
236
237
def test_inner_set_membership_still_works_for_standard_ops(self):
238
"""The patch must not break Inductor's existing fallback decisions
239
- for non-vllm ops such as ``torchvision::roi_align``.
240
- """
239
+ for non-vllm ops such as ``torchvision::roi_align``."""
240
import torch._inductor.lowering as _lowering
241
242
allow_list = _lowering.FALLBACK_ALLOW_LIST
tests/config/test_model_arch_config.py
+2
-4
@@ -372,8 +372,7 @@ class _HeterogeneousConfig(PretrainedConfig):
372
"""A heterogeneous config with no convertor of its own.
373
374
Mirrors the parts vLLM uses: per-layer configs are shallow copies with the
375
- varying attributes applied and heterogeneity stripped, so they do not recurse.
376
- """
375
+ varying attributes applied and heterogeneity stripped, so they do not recurse."""
376
377
is_heterogeneous = True
378
@@ -472,8 +471,7 @@ def test_deepseek_v4_convertor_splits_vision_architecture():
471
"""The vision checkpoint shares model_type/architectures with the
472
text-only DeepSeek-V4; the convertor routes it to the VL wrapper class
473
by rewriting hf_config.architectures (model-class resolution reads the
475
- raw attribute).
476
- """
474
+ raw attribute)."""
475
from vllm.transformers_utils.configs.deepseek_v4 import DeepseekV4Config
476
from vllm.transformers_utils.model_arch_config_convertor import (
477
DeepseekV4ModelArchConfigConvertor,
tests/config/test_multimodal_config.py
+5
-10
@@ -42,8 +42,7 @@ def test_mm_encoder_attn_backend_hash_updates():
42
43
def test_language_model_only_does_not_affect_mm_hash():
44
"""language_model_only does not affect the ViT computation graph,
45
- so it should not change the multimodal config hash.
46
- """
45
+ so it should not change the multimodal config hash."""
46
base_hash = MultiModalConfig().compute_hash()
47
lm_only_hash = MultiModalConfig(language_model_only=True).compute_hash()
48
assert base_hash == lm_only_hash
@@ -51,8 +50,7 @@ def test_language_model_only_does_not_affect_mm_hash():
50
51
def test_language_model_only_affects_model_hash():
52
"""language_model_only affects the LM computation graph,
54
- so it should change the model config hash.
55
- """
53
+ so it should change the model config hash."""
54
model = "llava-hf/llava-1.5-7b-hf"
55
base_hash = ModelConfig(model).compute_hash()
56
lm_only_hash = ModelConfig(model, language_model_only=True).compute_hash()
@@ -388,8 +386,7 @@ def _resolve_mm_video_decode_device(
386
torchcodec_available: bool = True,
387
) -> dict:
388
"""Run processor-device then video-decode-device resolution and report
391
- the resulting video media IO kwargs.
392
- """
389
+ the resulting video media IO kwargs."""
390
mm_config = MultiModalConfig(
391
mm_processor_kwargs={} if device is None else {"device": device},
392
mm_tensor_ipc=mm_tensor_ipc, # type: ignore[arg-type]
@@ -419,8 +416,7 @@ def _resolve_mm_video_decode_device(
416
417
def test_auto_video_decode_uses_nvdec_on_encoder_instance():
418
"""The processor runs on the accelerator there, so decoded frames should
422
- stay on-device too.
423
- """
419
+ stay on-device too."""
420
assert _resolve_mm_video_decode_device(ec_role="ec_producer") == {
421
"backend": "torchcodec",
422
"device": "cuda",
@@ -432,8 +428,7 @@ def test_auto_video_decode_stays_on_cpu_off_encoder_instance(
428
ec_role: ECRole | None,
429
):
430
"""The processor stays on CPU off encode-only instances, so video
435
- decoding should too.
436
- """
431
+ decoding should too."""
432
assert _resolve_mm_video_decode_device(ec_role=ec_role) == {}
433
434
tests/config/test_speculative_draft_hf_overrides.py
+4
-8
@@ -34,8 +34,7 @@ def _make_hf_config(**kwargs) -> PretrainedConfig:
34
@pytest.mark.cpu_test
35
def test_dict_overrides_are_not_forwarded_to_draft():
36
"""Dict overrides are target-specific key patches; the draft must get
37
- only the architecture-mapping override.
38
- """
37
+ only the architecture-mapping override."""
38
composed = SpeculativeConfig.compose_draft_hf_overrides(
39
{"max_position_embeddings": 1234}
40
)
@@ -51,8 +50,7 @@ def test_none_overrides_fall_back_to_arch_mapping():
50
@pytest.mark.cpu_test
51
def test_callable_overrides_reach_the_draft_config():
52
"""A callable override (config-to-config transform) composes with the
54
- architecture-mapping override and is applied to the draft config.
55
- """
53
+ architecture-mapping override and is applied to the draft config."""
54
55
def shrink(hf_config: PretrainedConfig) -> PretrainedConfig:
56
hf_config.num_hidden_layers = 1
@@ -69,8 +67,7 @@ def test_callable_overrides_reach_the_draft_config():
67
@pytest.mark.cpu_test
68
def test_arch_mapping_applies_before_callable_override():
69
"""The static arch-mapping override runs first, so the user callable
72
- observes (and may adjust) the post-mapping config.
73
- """
70
+ observes (and may adjust) the post-mapping config."""
71
seen_architectures: list[str] = []
72
73
def record(hf_config: PretrainedConfig) -> PretrainedConfig:
@@ -131,8 +128,7 @@ def test_composed_override_is_picklable():
128
the composed override must be picklable. A nested local closure is not
129
(it raised ``Can't get local object`` on DFlashDraftModel); a
130
``functools.partial`` over a module-referenceable static method is.
134
- Guard against regressing to a closure.
135
- """
131
+ Guard against regressing to a closure."""
132
composed = SpeculativeConfig.compose_draft_hf_overrides(_module_level_shrink)
133
134
assert isinstance(composed, functools.partial)
tests/config/test_speculative_draft_max_position_embeddings.py
+1
-2
@@ -99,8 +99,7 @@ def test_independent_draft_model_keeps_its_own_limit(
99
vllm_caplog: pytest.LogCaptureFixture,
100
):
101
"""An independent AR draft may genuinely have a smaller context than the
102
- target; its max_position_embeddings must not be resized.
103
- """
102
+ target; its max_position_embeddings must not be resized."""
103
target_model_config = ModelConfig(
104
AR_MODEL, hf_overrides={"max_position_embeddings": 8192}
105
)
tests/distributed/conftest.py
+1
-2
@@ -179,8 +179,7 @@ class MockSubscriber:
179
@pytest.fixture
180
def enable_ray_v2_backend():
181
"""Set env vars for the Ray V2 executor backend and shut down Ray
182
- between tests.
183
- """
182
+ between tests."""
183
import ray
184
185
saved = {
tests/distributed/test_eplb_quant_scale_consistency.py
+4
-8
@@ -124,8 +124,7 @@ def _build_processed_layer(
124
backend: str, raw: dict[str, torch.Tensor], device: torch.device
125
) -> tuple[CompressedTensorsW4A4Nvfp4MoEMethod, _RoutedExpertsStub]:
126
"""Create the method + layer, load ``raw`` and run the real
127
- process_weights_after_loading (which builds the flashinfer kernel).
128
- """
127
+ process_weights_after_loading (which builds the flashinfer kernel)."""
128
moe_config = _make_moe_config(backend)
129
method = CompressedTensorsW4A4Nvfp4MoEMethod(moe_config, "layer.0", use_a16=False)
130
layer = _RoutedExpertsStub(moe_config).to(device)
@@ -158,8 +157,7 @@ def _assert_tensors_equal(
157
158
def _simulate_eplb_rearrangement(layer: torch.nn.Module, perm: torch.Tensor) -> None:
159
"""Permute experts of every registered Parameter in place, the way
161
- EPLB's in-place rearrangement moves expert slices along dim 0.
162
- """
160
+ EPLB's in-place rearrangement moves expert slices along dim 0."""
161
with torch.no_grad():
162
for _, param in layer.named_parameters():
163
param.copy_(param[perm])
@@ -167,8 +165,7 @@ def _simulate_eplb_rearrangement(layer: torch.nn.Module, perm: torch.Tensor) ->
165
166
def _ensure_world1_distributed() -> None:
167
"""The enable_eplb config makes weight processing all-reduce activation
170
- scale amaxes over the EP group, so a (single-rank) EP group must exist.
171
- """
168
+ scale amaxes over the EP group, so a (single-rank) EP group must exist."""
169
from vllm.distributed.parallel_state import (
170
ensure_model_parallel_initialized,
171
init_distributed_environment,
@@ -256,8 +253,7 @@ def test_nvfp4_eplb_rearrangement_matches_reload(backend: str) -> None:
253
def test_fp8_per_tensor_alphas_registered_and_aliased() -> None:
254
"""CPU-only: the fp8 per-tensor oracle must register the fused
255
(w_scale * a_scale) products as layer Parameters aliased by the quant
259
- config, so EPLB rearrangement keeps kernels consistent.
260
- """
256
+ config, so EPLB rearrangement keeps kernels consistent."""
257
from vllm.model_executor.layers.fused_moe.oracle.fp8 import (
258
Fp8MoeBackend,
259
make_fp8_moe_quant_config,
tests/distributed/test_mnnvl_alltoall.py
+2
-4
@@ -160,8 +160,7 @@ def _make_forward_context(rank, world_size, num_tokens_per_rank):
160
class _AttnMeta:
161
"""Minimal placeholder so set_forward_context's
162
``attn_metadata is not None`` guard (forward_context.py:334)
163
- is satisfied. The real DPMetadata is built from num_tokens_across_dp.
164
- """
163
+ is satisfied. The real DPMetadata is built from num_tokens_across_dp."""
164
165
dp_metadata = None
166
@@ -460,8 +459,7 @@ def _one_sided_workspace_grow_worker(rank, world_size):
459
def test_one_sided_manager_workspace_grow(world_size):
460
"""A later initialize() with a larger per-token payload must grow the
461
workspace and rebuild MoeAlltoAll; a later initialize() with a smaller
463
- payload must no-op.
464
- """
462
+ payload must no-op."""
463
_spawn_workers(
464
_one_sided_workspace_grow_worker,
465
world_size,
tests/distributed/test_mq_connect_ip.py
+3
-6
@@ -21,8 +21,7 @@ from vllm.utils.network_utils import get_ip
21
22
def test_mq_bind_with_local_ip():
23
"""MessageQueue with remote readers should successfully bind
24
- when connect_ip is the local node's IP.
25
- """
24
+ when connect_ip is the local node's IP."""
25
# n_reader=2, n_local_reader=1 means 1 remote reader,
26
# which triggers the remote ZMQ socket bind.
27
mq = MessageQueue(
@@ -44,8 +43,7 @@ def test_mq_bind_with_local_ip():
43
def test_mq_bind_with_non_local_ip_fails():
44
"""MessageQueue should fail to bind when connect_ip is a
45
non-local IP address (simulating the bug where master_addr
47
- from a different node was used).
48
- """
46
+ from a different node was used)."""
47
# Use a non-local IP that we definitely can't bind to.
48
# 198.51.100.1 is from TEST-NET-2 (RFC 5737), never locally assigned.
49
non_local_ip = "198.51.100.1"
@@ -59,8 +57,7 @@ def test_mq_bind_with_non_local_ip_fails():
57
58
def test_mq_bind_defaults_to_local_ip():
59
"""When connect_ip is None, MessageQueue should auto-detect
62
- the local IP and bind successfully.
63
- """
60
+ the local IP and bind successfully."""
61
mq = MessageQueue(
62
n_reader=2,
63
n_local_reader=1,
tests/distributed/test_pynccl.py
+1
-2
@@ -495,8 +495,7 @@ def test_pynccl_suspend_resume_idempotent():
495
496
def test_pynccl_suspend_noop_without_symbol():
497
"""RCCL / NCCL < 2.29.7 lack ncclCommSuspend; suspend() must no-op, not
498
- crash, and resume() must then no-op too since nothing was suspended.
499
- """
498
+ crash, and resume() must then no-op too since nothing was suspended."""
499
from unittest.mock import Mock
500
501
comm = object.__new__(PyNcclCommunicator)
tests/distributed/test_ray_v2_executor_e2e.py
+1
-2
@@ -23,8 +23,7 @@ def _ray_init():
23
24
Without this, workers cannot unpickle actor classes defined in the
25
``tests`` package, causing FunctionActorManager to fall back to
26
- TemporaryActor which drops async method signatures.
27
- """
26
+ TemporaryActor which drops async method signatures."""
27
project_root = str(pathlib.Path(__file__).resolve().parents[2])
28
ray.init(
29
ignore_reinit_error=True,
tests/distributed/test_sharded_rdt_plan.py
+61
-122
@@ -53,8 +53,7 @@ META = torch.device("meta")
53
54
class _FakeLayer:
55
"""Stand-in for a leaf module. The planner only stores it and keys on
56
- ``id()``; nothing in the plan path touches its attributes.
57
- """
56
+ ``id()``; nothing in the plan path touches its attributes."""
57
58
def __init__(self, tag: str) -> None:
59
self.tag = tag
@@ -65,8 +64,7 @@ class _FakeLayer:
64
65
def _module(layer, copies):
66
"""What the bake records for one leaf module: a scatter list whose entries
68
- all carry that module as their ``layer``.
69
- """
67
+ all carry that module as their ``layer``."""
68
for c in copies:
69
c.layer = layer
70
return copies
@@ -83,8 +81,7 @@ def _copy(
81
dtype=torch.bfloat16,
82
):
83
"""A `_Scatter` as the bake would record it: source key, owning layer, and
86
- the meta destination region.
87
- """
84
+ the meta destination region."""
85
stride = (
86
(1,)
87
if len(shape) == 1
@@ -143,8 +140,7 @@ def _planner(baked, *, name_meta, live=None, held_by=None, group_lens=None):
140
141
def _one_module_per_layer(n_layers, *, dtype="bfloat16", numel=4):
142
"""`(baked, name_meta, names, group_lens)` for a pre / N-layer / post model
146
- where every gather group is one fully-baked leaf module.
147
- """
143
+ where every gather group is one fully-baked leaf module."""
144
names = ["embed.weight"]
145
names += [f"model.layers.{i}.w" for i in range(n_layers)]
146
names += ["norm.weight"]
@@ -165,8 +161,7 @@ def _one_module_per_layer(n_layers, *, dtype="bfloat16", numel=4):
161
class TestFakeOpChains:
162
"""Every allowlisted op must append itself to the chain and hand back a
163
child whose shape/dtype PyTorch itself computed. The chain is the wire
168
- format the producer replays, so its exact contents are load-bearing.
169
- """
164
+ format the producer replays, so its exact contents are load-bearing."""
165
166
def _fake(self, shape=(4, 6), dtype=torch.bfloat16, sink=None):
167
return FakeRDTTensor(
@@ -227,8 +222,7 @@ class TestFakeOpChains:
222
@pytest.mark.parametrize("op,n", [("chunk", 2), ("unbind", 4)])
223
def test_multi_return_op_emits_one_child_per_output(self, op, n):
224
"""chunk/unbind hand back a tuple; each child carries the base op plus a
230
- trailing __getitem__(i) so the producer can index the replayed result.
231
- """
225
+ trailing __getitem__(i) so the producer can index the replayed result."""
226
parts = getattr(self._fake(), op)(*((n,) if op == "chunk" else ()), 0)
227
assert isinstance(parts, tuple)
228
assert len(parts) == n
@@ -244,8 +238,7 @@ class TestFakeOpChains:
238
239
class TestFakeUnsupportedOps:
240
"""Anything that needs real data must fail loudly at bake time rather than
247
- silently transferring the wrong bytes.
248
- """
241
+ silently transferring the wrong bytes."""
242
243
def _fake(self):
244
return FakeRDTTensor(
@@ -285,8 +278,7 @@ class TestFakeUnsupportedOps:
278
279
class TestBakeRecording:
280
"""During the dry run the fake's ``copy_`` is the data sink: it records the
288
- source chain plus the meta destination's strided region and moves nothing.
289
- """
281
+ source chain plus the meta destination's strided region and moves nothing."""
282
283
def _recorder_and_fake(self, shape=(4, 6)):
284
rec = BakeSink()
@@ -322,8 +314,7 @@ class TestBakeRecording:
314
315
def test_unattributed_copy_is_live_but_unrecorded(self):
316
"""A copy_ with no loader stamp cannot be attributed to a param, so its
325
- module must fall back to the plain load — but the name still moved data.
326
- """
317
+ module must fall back to the plain load — but the name still moved data."""
318
rec, fake = self._recorder_and_fake()
319
rec.current = None
320
torch.empty((4, 6), dtype=torch.bfloat16, device=META).copy_(fake)
@@ -363,8 +354,7 @@ class TestBakeRecording:
354
producer packs what the replay yields, so the record must carry the
355
POST-chain dtype: taking it from the source name's metadata instead sizes
356
the slice with the wrong itemsize and shifts every later slice in the
366
- chunk, carving the packed blob differently on the two sides.
367
- """
357
+ chunk, carving the packed blob differently on the two sides."""
358
rec, fake = self._recorder_and_fake(shape=(4,))
359
layer = _FakeLayer("reinterpreted")
360
rec.current = (layer, "weight")
@@ -384,8 +374,7 @@ class TestBakeRecording:
374
the producer packs what the chain yields, and nothing downstream can
375
catch a mismatch — the consumer's buffer view is exactly prod(dest.shape)
376
elements, so it reshapes cleanly over bytes laid out at other offsets.
387
- So the bake refuses rather than recording a slice it cannot carve.
388
- """
377
+ So the bake refuses rather than recording a slice it cannot carve."""
378
rec, fake = self._recorder_and_fake(shape=(1, 6))
379
rec.current = (_FakeLayer("broadcast"), "weight")
380
param = torch.empty((4, 6), dtype=torch.bfloat16, device=META)
@@ -401,8 +390,7 @@ class TestBakeRecording:
390
class TestConsumerIdentity:
391
"""Every worker in the fleet needs a DISTINCT id in 0..C-1: it selects the
392
worker's producer block and keys the producer's per-consumer serve ring, so
404
- a collision silently serves two workers out of one ring.
405
- """
393
+ a collision silently serves two workers out of one ring."""
394
395
def _engine(self, *, dp_index, rank, world_size):
396
eng = object.__new__(ShardedRDTWeightTransferEngine)
@@ -439,8 +427,7 @@ class TestConsumerIdentity:
427
def test_independent_engines_offset_into_distinct_ranges(self):
428
"""A fleet of separate engines restarts _global_worker_index at 0 in
429
each, so without the replica offset every engine would claim 0..w-1.
442
- The driver sets replica_rank on the payload; these are the ids it buys.
443
- """
430
+ The driver sets replica_rank on the payload; these are the ids it buys."""
431
ids = [
432
self._ids(num_consumers=8, workers=range(4), replica_rank=r, num_replicas=2)
433
for r in (0, 1)
@@ -466,8 +453,7 @@ def _router(
453
group_lens=None,
454
):
455
"""A router over ``n`` single-name groups unless told otherwise, so a test
469
- can state expectations in group indices.
470
- """
456
+ can state expectations in group indices."""
457
if names is None:
458
n = len(name_owner_class or []) or (len(group_lens or []) or 1)
459
names = [f"g{i}" for i in range(n)]
@@ -496,8 +482,7 @@ class TestRdtRouter:
482
def test_every_producer_nic_carries_traffic(self):
483
"""16 producers / 8 consumers: the block rule spreads each consumer's
484
pulls over its block, alternating by group, so no producer sits idle.
499
- Plain `consumer_id % len(owners)` would idle half of them.
500
- """
485
+ Plain `consumer_id % len(owners)` would idle half of them."""
486
r = _router(16, 8, group_lens=[1] * 95)
487
names = [f"g{i}" for i in range(95)]
488
for c in range(8):
@@ -515,8 +500,7 @@ class TestRdtRouter:
500
501
def test_pipeline_stages_route_to_the_owning_stage(self):
502
"""2 stages x 8 ranks: groups 0-2 on stage 0, 3-5 on stage 1. Two owner
518
- sets, one per stage; each consumer reaches both.
519
- """
503
+ sets, one per stage; each consumer reaches both."""
504
r = _router(
505
16,
506
8,
@@ -532,8 +516,7 @@ class TestRdtRouter:
516
517
def test_expert_names_route_to_the_holding_ranks(self):
518
"""A name held by only some ranks routes to those; a replicated name
535
- keeps the full set.
536
- """
519
+ keeps the full set."""
520
r = RdtRouter(
521
8,
522
4,
@@ -552,8 +535,7 @@ class TestRdtRouter:
535
536
def test_consumers_spread_over_an_owner_set(self):
537
"""Several ranks hold a name (its TP peers); the block rule must spread
555
- consumers across them, not funnel through one.
556
- """
538
+ consumers across them, not funnel through one."""
539
r = _router(
540
4, 4, owner_sets=[[0, 1]], name_owner_class=[0] * 6, group_lens=[1] * 6
541
)
@@ -562,8 +544,7 @@ class TestRdtRouter:
544
545
def test_a_group_frees_at_every_owner_of_any_of_its_names(self):
546
"""The free barrier is per group, so its fan-out is the UNION over the
565
- group's names: a rank holding none of them is not signalled.
566
- """
547
+ group's names: a rank holding none of them is not signalled."""
548
r = RdtRouter(4, 2, [[0, 1], [2, 3]], [0, 1, 0], ["a", "b", "c"], [2, 1])
549
assert r.group_owners(0) == [0, 1, 2, 3]
550
assert r.group_owners(1) == [0, 1]
@@ -633,8 +614,7 @@ class TestReplicaOverlay:
614
615
def test_adding_a_deployment_does_not_move_the_first_one(self):
616
"""The strongest form: an existing consumer's routes are byte-identical
636
- before and after another deployment is provisioned.
637
- """
617
+ before and after another deployment is provisioned."""
618
one, names = self._fleet(16, 8, 1)
619
two, _ = self._fleet(16, 8, 2)
620
for consumer_id in range(8):
@@ -644,8 +624,7 @@ class TestReplicaOverlay:
624
625
def test_one_deployment_is_the_historical_carve(self):
626
"""Default (no width) and width == the whole fleet must agree with the
647
- plain block rule, so a single-deployment fleet is untouched.
648
- """
627
+ plain block rule, so a single-deployment fleet is untouched."""
628
plain = _router(16, 8, group_lens=[1] * 6)
629
explicit, names = self._fleet(16, 8, 1)
630
for consumer_id in range(8):
@@ -659,8 +638,7 @@ class TestReplicaOverlay:
638
def test_the_overlay_holds_for_partially_owned_names(self):
639
"""Pipeline stages and experts too: two owner sets, one narrow. The
640
narrow one already forced agreement (one owner, no block to carve); the
662
- wide one is what the carve decides.
663
- """
641
+ wide one is what the carve decides."""
642
r, names = self._fleet(
643
8,
644
4,
@@ -676,16 +654,14 @@ class TestReplicaOverlay:
654
def test_a_width_that_does_not_divide_the_fleet_raises(self):
655
"""A uniform fleet is asserted upstream in ``get_world_size``; if it ever
656
is not, the overlay would map two workers of one deployment onto the same
679
- block index, so refuse rather than serve the wrong bytes.
680
- """
657
+ block index, so refuse rather than serve the wrong bytes."""
658
with pytest.raises(ValueError, match="does not divide"):
659
RdtRouter(4, 6, None, None, ["a"], [1], workers_per_replica=4)
660
661
def test_pulls_still_carry_the_global_consumer_id(self):
662
"""The carve uses the index WITHIN a deployment, but the wire must keep
663
the fleet-global id: it is what lets the producer tell the sharers of a
687
- slot apart, and count their arrivals separately.
688
- """
664
+ slot apart, and count their arrivals separately."""
665
666
class _Method:
667
def __init__(self):
@@ -728,8 +704,7 @@ def _producer_pack_offsets(slices):
704
class TestPackedLayout:
705
def test_consumer_layout_matches_the_producer_rule(self):
706
"""Mixed dtypes, sizes that do not land on 16B — i.e. the Kimi-style
731
- group (fp8 weights + fp32 scales + bf16 norms) that exposes alignment.
732
- """
707
+ group (fp8 weights + fp32 scales + bf16 norms) that exposes alignment."""
708
specs = [
709
("w.fp8", "float8_e4m3fn", [17]),
710
("w.scale", "float32", [3]),
@@ -804,8 +779,7 @@ class TestPackedLayout:
779
class TestChunkModuleScatters:
780
"""The chunk cut: one chunk per distinct owner class present in the copies,
781
ascending by class index. Derived purely from the bake plus the ownership
807
- table, so vLLM's expert placement needs no cases.
808
- """
782
+ table, so vLLM's expert placement needs no cases."""
783
784
def test_unstamped_copies_form_one_chunk(self):
785
layer = _FakeLayer("l")
@@ -819,8 +793,7 @@ class TestChunkModuleScatters:
793
"""Classes are numbered by first appearance in metadata order, so the
794
replicated class (0) leads and the rest follow — the ordering the old
795
"-1 first, then ascending stamp" rule produced, now falling out of the
822
- table instead of a special case.
823
- """
796
+ table instead of a special case."""
797
layer = _FakeLayer("moe")
798
names = ["norm", "e5", "e0", "e2"]
799
copies = [_copy(n, shape=(4,)) for n in names]
@@ -840,8 +813,7 @@ class TestChunkModuleScatters:
813
814
def test_copy_order_within_a_chunk_is_bake_order(self):
815
"""Scatter order within a chunk must follow the bake, not the stamp
843
- sort: the packed layout and the producer's replay agree on keys order.
844
- """
816
+ sort: the packed layout and the producer's replay agree on keys order."""
817
layer = _FakeLayer("moe")
818
names = ["e3", "e1", "e2"] # one stamp, deliberately unsorted names
819
copies = [_copy(n, shape=(4,)) for n in names]
@@ -855,8 +827,7 @@ class TestChunkModuleScatters:
827
828
def test_stamps_interleave_across_modules_without_reordering_within(self):
829
"""Two modules' copies bucket by stamp; within each bucket the order is
858
- module-then-bake order.
859
- """
830
+ module-then-bake order."""
831
a, b = _FakeLayer("a"), _FakeLayer("b")
832
mods = [
833
_module(a, [_copy("a0", shape=(4,)), _copy("a1", shape=(4,))]),
@@ -876,8 +847,7 @@ class TestChunkModuleScatters:
847
def test_scatters_carry_their_own_dtype(self):
848
"""Dtype rides the record from the bake, where it is the fake's dtype
849
AFTER its op chain — not a plan-time lookup of the source name, which
879
- would be wrong for any chain that reinterprets dtype.
880
- """
850
+ would be wrong for any chain that reinterprets dtype."""
851
layer = _FakeLayer("l")
852
eng = _planner({}, name_meta={"w": ("float32", [10])})
853
((_er, scatters),) = eng._chunk_module_scatters(
@@ -916,8 +886,7 @@ class TestBuildCallPlan:
886
887
def test_materialize_fires_on_a_modules_first_chunk_only(self):
888
"""Empty HF params are allocated once per module, by construction —
919
- including a FusedMoE-like module whose copies span owner-class chunks.
920
- """
889
+ including a FusedMoE-like module whose copies span owner-class chunks."""
890
layer = _FakeLayer("spanning")
891
names = [f"w{i}" for i in range(4)]
892
copies = [_copy(n, shape=(4,)) for n in names]
@@ -952,8 +921,7 @@ class TestBuildCallPlan:
921
def test_free_signal_waits_for_a_groups_last_chunk_when_it_is_split(self):
922
"""The load-bearing case: with the group cut across owner-class chunks the
923
signal must hang off the LAST one. Signaling earlier lets the producers
955
- drop the gather buffers while a later chunk's RDMA is still reading.
956
- """
924
+ drop the gather buffers while a later chunk's RDMA is still reading."""
925
layer = _FakeLayer("l")
926
names = [f"w{i}" for i in range(4)]
927
copies = [_copy(n, shape=(4,)) for n in names]
@@ -969,8 +937,7 @@ class TestBuildCallPlan:
937
938
def test_free_signal_timing_across_two_split_groups(self):
939
"""Two groups x 2 owner-class chunks each: signals land on each group's
972
- last chunk only.
973
- """
940
+ last chunk only."""
941
names_a = [f"model.layers.0.w{i}" for i in range(4)]
942
names_b = [f"model.layers.1.w{i}" for i in range(4)]
943
baked, name_meta, stamps = {}, {}, {}
@@ -988,8 +955,7 @@ class TestBuildCallPlan:
955
def test_a_group_with_nothing_local_is_signaled_at_sync_start(self):
956
"""The owners still published it, so this consumer must signal it —
957
immediately, before the pipeline (signal-before-publish is tolerated),
991
- never hung off another group's chunk.
992
- """
958
+ never hung off another group's chunk."""
959
baked, name_meta, names, group_lens = _one_module_per_layer(2)
960
del baked["model.layers.1.w"] # nothing baked, and not live => no pull
961
eng = _planner(
@@ -1010,8 +976,7 @@ class TestBuildCallPlan:
976
977
def test_modules_are_deduped_within_a_group(self):
978
"""Several names of one fused module map to the same scatter list; the
1013
- plan must not chunk it twice.
1014
- """
979
+ plan must not chunk it twice."""
980
layer = _FakeLayer("fused")
981
names = ["qkv.q", "qkv.k", "qkv.v"]
982
copies = [_copy(n, shape=(4,)) for n in names]
@@ -1027,8 +992,7 @@ class TestBuildCallPlan:
992
993
def test_plan_is_a_pure_function_of_its_inputs(self):
994
"""Called twice with the same arguments it must produce the same plan —
1030
- that is what lets the engine build it once and reuse it every sync.
1031
- """
995
+ that is what lets the engine build it once and reuse it every sync."""
996
baked, name_meta, names, group_lens = _one_module_per_layer(2)
997
eng = _planner(baked, name_meta=name_meta)
998
a = eng._build_call_plan(names, group_lens)
@@ -1048,8 +1012,7 @@ class TestBuildCallPlan:
1012
class TestUnbakedNamesGuard:
1013
"""A live name with no baked plan has no way to load — there is no fallback,
1014
and its pull would target groups the pipeline already freed — so the plan
1051
- build fails at init, naming the names.
1052
- """
1015
+ build fails at init, naming the names."""
1016
1017
def test_a_live_unbaked_name_fails_the_plan_build(self):
1018
baked, name_meta, names, group_lens = _one_module_per_layer(2)
@@ -1060,8 +1023,7 @@ class TestUnbakedNamesGuard:
1023
1024
def test_never_copied_names_are_dropped_entirely(self):
1025
"""Experts owned by another EP rank no-op in their loader: not an error,
1063
- and not a chunk — their group is pre-freed if nothing else fills it.
1064
- """
1026
+ and not a chunk — their group is pre-freed if nothing else fills it."""
1027
baked, name_meta, names, group_lens = _one_module_per_layer(2)
1028
del baked["norm.weight"]
1029
eng = _planner(baked, name_meta=name_meta, live=set(names) - {"norm.weight"})
@@ -1073,15 +1035,13 @@ class TestUnbakedNamesGuard:
1035
class TestCallPlanRouting:
1036
"""Under partial ownership each chunk must be pulled from a producer that
1037
actually holds every name in it. Consumers bind EVERY producer (signals fan
1076
- out to all owners), so local index == trainer rank.
1077
- """
1038
+ out to all owners), so local index == trainer rank."""
1039
1040
def _routed_planner(
1041
self, held_by_group, num_consumers, consumer_id, *, held_by=None
1042
):
1043
"""``held_by_group[g]`` = the ranks holding group g's names, so a test
1083
- can still speak in groups; ``held_by`` overrides individual names.
1084
- """
1044
+ can still speak in groups; ``held_by`` overrides individual names."""
1045
baked, name_meta, names, group_lens = _one_module_per_layer(
1046
len(held_by_group) - 2
1047
)
@@ -1108,16 +1068,14 @@ class TestCallPlanRouting:
1068
1069
def test_two_stage_ownership_splits_chunks_between_owners(self):
1070
"""Two PP stages, 4 groups: stage 0 holds the first half, stage 1 the
1111
- second. Every chunk goes to a holder of its names.
1112
- """
1071
+ second. Every chunk goes to a holder of its names."""
1072
eng, names, group_lens = self._routed_planner([[0], [0], [1], [1]], 1, 0)
1073
plan = eng._build_call_plan(names, group_lens)
1074
assert [c.owner for c in plan.chunks] == [0, 0, 1, 1]
1075
1076
def test_a_multi_owner_group_still_resolves_to_one_producer(self):
1077
"""Every chunk is served by exactly ONE producer: splitting a pull only
1119
- multiplies produce calls, since the consumer's NIC bounds it.
1120
- """
1078
+ multiplies produce calls, since the consumer's NIC bounds it."""
1079
eng, names, group_lens = self._routed_planner([[0, 1]] * 4, 1, 0)
1080
plan = eng._build_call_plan(names, group_lens)
1081
assert all(0 <= c.owner < 2 for c in plan.chunks)
@@ -1125,8 +1083,7 @@ class TestCallPlanRouting:
1083
def test_an_expert_name_routes_to_the_rank_holding_it(self):
1084
"""PP ∩ EP: stage 0 = ranks 0-1, stage 1 = ranks 2-3, and one expert
1085
name inside a stage-1 group is held by rank 3 alone. The name's own owner
1128
- set is what routes it.
1129
- """
1086
+ set is what routes it."""
1087
eng, names, group_lens = self._routed_planner(
1088
[[0, 1], [0, 1], [2, 3], [2, 3]],
1089
1,
@@ -1141,8 +1098,7 @@ class TestCallPlanRouting:
1098
def test_an_unheld_name_is_rejected_at_init(self):
1099
"""A name no rank holds can never be served. The trainer raises when it
1100
transposes the holdings; the router's validate() is the consumer-side
1144
- backstop, and either way it fails at init rather than at first pull.
1145
- """
1101
+ backstop, and either way it fails at init rather than at first pull."""
1102
with pytest.raises(ValueError, match="empty"):
1103
RdtRouter(2, 1, [[]], [0], ["w"], [1]).validate()
1104
@@ -1151,16 +1107,14 @@ class TestSignalCompleteness:
1107
"""Every gather group is signaled exactly once — after its last chunk when
1108
the worker pulls from it, at sync start otherwise — for ANY expert
1109
placement. A group signaled twice over-credits the barrier; a group never
1154
- signaled parks a producer credit and hangs end_sync.
1155
- """
1110
+ signaled parks a producer credit and hangs end_sync."""
1111
1112
def _moe_planner(self, worker_experts, *, ep_size=4, n_experts=8, n_layers=2):
1113
"""Pre / n_layers MoE layers / post. Each layer: one norm (its own
1114
module, stamp -1) + n_experts expert names stamped ``e // n_local``.
1115
The worker's bake covers only ``worker_experts`` (its placement);
1116
foreign expert names never copied => dropped entirely, as in the real
1162
- bake.
1163
- """
1117
+ bake."""
1118
n_local = n_experts // ep_size
1119
names = ["embed.weight"]
1120
group_lens = [1]
@@ -1220,8 +1174,7 @@ class TestSignalCompleteness:
1174
1175
def test_placement_changes_only_the_chunk_count_never_the_signals(self):
1176
"""Linear experts 0-3 hit 2 owner classes; round_robin 0,2,4,6
1223
- hits all 4. More chunks per group, identical signal set.
1224
- """
1177
+ hits all 4. More chunks per group, identical signal set."""
1178
plans = {}
1179
for label, experts in (("linear", [0, 1, 2, 3]), ("round_robin", [0, 2, 4, 6])):
1180
eng, names, group_lens = self._moe_planner(worker_experts=experts)
@@ -1235,8 +1188,7 @@ class TestSignalCompleteness:
1188
1189
def test_the_fused_module_materializes_first_and_quants_last_across_chunks(self):
1190
"""The FusedMoE shape: one module's copies span every owner-class chunk of
1238
- its group; materialize on its first, quant on its last.
1239
- """
1191
+ its group; materialize on its first, quant on its last."""
1192
eng, names, group_lens = self._moe_planner(
1193
worker_experts=[0, 2, 4, 6], n_layers=1
1194
)
@@ -1294,8 +1246,7 @@ class TestLayerwiseGroups:
1246
def test_flattening_a_partition_returns_the_input_order(self):
1247
"""Un-indexed names group by POSITION, not by name class — so one that
1248
looks like a pre-block name still lands after the layers it follows.
1297
- Group index therefore means the same thing on every rank.
1298
- """
1249
+ Group index therefore means the same thing on every rank."""
1250
names = [
1251
"embed.weight",
1252
"model.layers.0.a",
@@ -1313,8 +1264,7 @@ class TestLayerwiseGroups:
1264
1265
def test_stacks_keep_prefix_appearance_order_and_sort_within(self):
1266
"""Two stacks stay in the order they appear — the vision tower before the
1316
- text stack — while each sorts by index internally.
1317
- """
1267
+ text stack — while each sorts by index internally."""
1268
names = [
1269
"visual.blocks.1.w",
1270
"visual.blocks.0.w",
@@ -1331,8 +1281,7 @@ class TestLayerwiseGroups:
1281
def test_the_post_block_lands_last_however_early_it_arrives(self):
1282
"""Megatron-Bridge streams the last pipeline stage's output block before
1283
its layers. Sweeping un-indexed names after the first layer into a
1334
- trailing group is what lets the gather loop walk groups ascending.
1335
- """
1284
+ trailing group is what lets the gather loop walk groups ascending."""
1285
names = ["model.layers.0.w", "model.norm.weight", "model.layers.1.w"]
1286
assert layerwise_groups(names) == [
1287
["model.layers.0.w"],
@@ -1342,8 +1291,7 @@ class TestLayerwiseGroups:
1291
1292
def test_names_sharing_a_layer_coalesce_when_the_source_interleaves(self):
1293
"""A raw-checkpoint source may yield in shard-packing order. Coalescing on
1345
- the key keeps that from shattering one layer into many groups.
1346
- """
1294
+ the key keeps that from shattering one layer into many groups."""
1295
names = [
1296
"model.layers.0.a",
1297
"model.layers.1.a",
@@ -1385,15 +1333,13 @@ class TestLayerwiseGroups:
1333
def test_every_supported_naming_convention_partitions_per_layer(self, prefix):
1334
"""One decoder layer per group under any prefix, with no per-architecture
1335
table. A literal `model.layers.` match silently yields one whole-model
1388
- group for most of these.
1389
- """
1336
+ group for most of these."""
1337
names = [f"{prefix}{i}.self_attn.q_proj.weight" for i in range(3)]
1338
assert layerwise_groups(names) == [[n] for n in names]
1339
1340
def test_a_moe_layer_stays_whole(self):
1341
"""The OUTERMOST index wins, so per-expert names group by layer. Splitting
1395
- on the expert would cut FusedMoE — one leaf module — across groups.
1396
- """
1342
+ on the expert would cut FusedMoE — one leaf module — across groups."""
1343
names = [
1344
"model.layers.0.mlp.experts.0.w1.weight",
1345
"model.layers.0.mlp.experts.1.w1.weight",
@@ -1410,8 +1356,7 @@ class TestLayerwiseGroups:
1356
def test_a_vlm_partitions_the_vision_tower_and_the_text_stack(self):
1357
"""Qwen-VL layout. Today's literal `model.layers.` match puts every one of
1358
these in ONE group — the whole model — because the text stack ships as
1413
- `model.language_model.layers.`.
1414
- """
1359
+ `model.language_model.layers.`."""
1360
names = [
1361
"visual.patch_embed.proj.weight",
1362
"visual.blocks.0.attn.qkv.weight",
@@ -1430,8 +1375,7 @@ class TestLayerwiseGroups:
1375
1376
def test_two_stacks_sharing_an_index_do_not_merge(self):
1377
"""The key carries the prefix, so vision block 0 and text layer 0 are
1433
- different groups even though both are index 0.
1434
- """
1378
+ different groups even though both are index 0."""
1379
names = [
1380
"visual.blocks.0.attn.qkv.weight",
1381
"model.language_model.layers.0.self_attn.q_proj.weight",
@@ -1468,23 +1412,20 @@ class TestOpAllowlistAgreement:
1412
1413
def test_every_bake_recordable_op_is_replayable(self):
1414
"""Anything the bake can record must be serveable, or the failure lands a
1471
- whole sync later than the mistake.
1472
- """
1415
+ whole sync later than the mistake."""
1416
assert not set(SUPPORTED_OPS.values()) - set(ALLOWED_OPS)
1417
1418
def test_the_producer_allows_nothing_the_consumer_cannot_emit(self):
1419
"""The allowlist is also a guard against a misbehaving or spoofed
1420
consumer invoking arbitrary methods on trainer tensors, so it must not be
1421
wider than the ops the bake can actually produce. ``to`` in particular
1479
- would let a replay change dtype or device.
1480
- """
1422
+ would let a replay change dtype or device."""
1423
assert not set(ALLOWED_OPS) - set(SUPPORTED_OPS.values())
1424
assert "to" not in ALLOWED_OPS
1425
1426
def test_transpose_via_t_is_serveable(self):
1427
"""The specific regression: a chain recorded from ``.t()`` must pass the
1486
- producer's guard.
1487
- """
1428
+ producer's guard."""
1429
fake = FakeRDTTensor(
1430
name="w",
1431
shape=torch.Size((4, 6)),
@@ -1529,8 +1470,7 @@ BAKE_MODELS = [
1470
class TestRequiresTheRayExecutor:
1471
"""The engine's data plane is Ray's, so a non-Ray executor cannot work. The
1472
check is at construction because the alternative is an opaque failure during
1532
- the first handshake, long after the misconfiguration.
1533
- """
1473
+ the first handshake, long after the misconfiguration."""
1474
1475
def _construct(self, backend):
1476
cfg = SimpleNamespace(
@@ -1557,8 +1497,7 @@ class TestRequiresTheRayExecutor:
1497
1498
def test_a_custom_executor_class_is_left_alone(self):
1499
"""A `type[Executor]` override is deliberate and unjudgeable here, so it
1560
- must not be rejected for merely not being the string "ray".
1561
- """
1500
+ must not be rejected for merely not being the string "ray"."""
1501
1502
class _CustomExecutor:
1503
pass
tests/distributed/test_sharded_rdt_producer.py
+39
-78
@@ -236,8 +236,7 @@ class TestPublishAndRebuild:
236
def test_views_of_one_storage_do_not_overlap(self, server_factory):
237
"""One IPC export per storage, one as_strided view per name — the whole
238
point of the storage/view split. Overlapping views would serve the same
239
- bytes for two different weights.
240
- """
239
+ bytes for two different weights."""
240
server = server_factory()
241
server.begin_sync(1)
242
_publish(server, GI_A, GROUP_A, nbytes=64)
@@ -260,8 +259,7 @@ class TestPublishAndRebuild:
259
def test_the_default_lookahead_is_one(self):
260
"""1 is the sweet spot: group N+1 is gathered AND pullable while N is
261
being pulled, with resident memory at its floor of 2 groups — the bound
263
- the larger-model runs size against.
264
- """
262
+ the larger-model runs size against."""
263
assert DEFAULT_GATHER_LOOKAHEAD == 1
264
265
@@ -276,8 +274,7 @@ class TestFreeBarrier:
274
275
def test_group_is_held_until_the_last_live_consumer_signals(self, server_factory):
276
"""Every live consumer signals every owner; releasing on the first
279
- signal would drop storage other consumers are still reading.
280
- """
277
+ signal would drop storage other consumers are still reading."""
278
server = server_factory()
279
server.begin_sync(3)
280
_publish(server, GI_A, GROUP_A)
@@ -304,8 +301,7 @@ class TestFreeBarrier:
301
):
302
"""A consumer with nothing to pull from a group signals it at sync
303
start, which can precede the publish. The publish must then release the
307
- group rather than wait for a signal that will never come again.
308
- """
304
+ group rather than wait for a signal that will never come again."""
305
server = server_factory()
306
server.begin_sync(1)
307
server.free_group(GI_A)
@@ -328,8 +324,7 @@ class TestFreeBarrier:
324
the server says the group is gone — and it hears that ONLY through
325
``wait_freed`` / ``end_sync``, never a publish return (a freed notice
326
riding an unharvested async publish while the engine blocks in
331
- ``wait_freed`` would wedge the loop).
332
- """
327
+ ``wait_freed`` would wedge the loop)."""
328
server = server_factory()
329
server.begin_sync(1)
330
_publish(server, GI_A, GROUP_A)
@@ -358,8 +353,7 @@ class TestFreeBarrier:
353
354
class _CountingSource:
355
"""`iter_groups` yielding one CPU-tensor group per call, built lazily so a
361
- group's tensors exist only once the engine's credit gate lets it gather.
362
- """
356
+ group's tensors exist only once the engine's credit gate lets it gather."""
357
358
def __init__(self, groups):
359
self._groups = groups
@@ -372,8 +366,7 @@ class _CountingSource:
366
class _ResidencyDict(dict):
367
"""The engine's `_inflight`, instrumented: `max_len` is the high-water mark
368
of groups whose CUDA-IPC export refs were alive at once — the trainer's
375
- resident-memory bound in groups.
376
- """
369
+ resident-memory bound in groups."""
370
371
def __init__(self):
372
super().__init__()
@@ -387,8 +380,7 @@ class _ResidencyDict(dict):
380
def _loop_engine(server, n_groups, *, lookahead):
381
"""A real engine wired straight to a real (non-Ray) server, with only the
382
state `_run_gather_loop` reads. The `_rpc` seam dispatches inline;
390
- `_publish_async` sees no `.remote` and runs inline too.
391
- """
383
+ `_publish_async` sees no `.remote` and runs inline too."""
384
groups = [(f"model.layers.{gi}.w",) for gi in range(n_groups)]
385
e = ShardedRDTTrainerWeightTransferEngine.__new__(
386
ShardedRDTTrainerWeightTransferEngine
@@ -411,16 +403,14 @@ class TestGatherCredit:
403
serveable immediately, and the ENGINE's loop stops gathering while more than
404
`gather_lookahead` groups are unfreed. So at most `lookahead + 1` groups are
405
resident — two at the default — while group N+1 is pulled the instant N's
414
- pulls finish.
415
- """
406
+ pulls finish."""
407
408
@pytest.fixture
409
def gather_engine(self, monkeypatch):
410
"""Neutralize the two CUDA touches in the export path so the REAL
411
gather loop runs on CPU: `.cuda()` becomes identity, and the storage
412
export ships the `(nbytes, ..., device, ...)` tuple the fixture's
422
- stubbed `rebuild_cuda_tensor` expects.
423
- """
413
+ stubbed `rebuild_cuda_tensor` expects."""
414
monkeypatch.setattr(torch.Tensor, "cuda", lambda self: self)
415
monkeypatch.setattr(
416
trainer_mod,
@@ -432,8 +422,7 @@ class TestGatherCredit:
422
def test_publish_never_blocks(self, server_factory):
423
"""Publishing must not park on a credit: the whole point is that a
424
gathered group becomes serveable immediately. Three publishes with no
435
- frees, inline on this thread — a block here hangs the test.
436
- """
425
+ frees, inline on this thread — a block here hangs the test."""
426
server = server_factory(gather_lookahead=1)
427
server.begin_sync(1)
428
for gi in range(3):
@@ -447,8 +436,7 @@ class TestGatherCredit:
436
than 2 groups of gathered weights, no matter how the consumer paces —
437
and the pipeline still overlaps, because the consumer here refuses to
438
free group N until N+1 is already published (pullable). A gate an
450
- off-by-one too tight deadlocks this test; too loose fails max_len.
451
- """
439
+ off-by-one too tight deadlocks this test; too loose fails max_len."""
440
server = server_factory(gather_lookahead=1)
441
n_groups = 8
442
engine = gather_engine(server, n_groups, lookahead=1)
@@ -490,8 +478,7 @@ class TestGatherCredit:
478
):
479
"""0 is the serialized baseline: the loop waits for group N to be freed
480
before gathering N+1, so exactly ONE group is ever resident and nothing
493
- overlaps. A floor of 1 on the bound would silently pipeline instead.
494
- """
481
+ overlaps. A floor of 1 on the bound would silently pipeline instead."""
482
server = server_factory(gather_lookahead=0)
483
engine = gather_engine(server, 4, lookahead=0)
484
@@ -517,8 +504,7 @@ class TestGatherCredit:
504
self, server_factory, gather_engine
505
):
506
"""Lookahead + 1, not a hardcoded 2: at lookahead=2 a free-nothing
520
- consumer sees exactly 3 groups gathered before the loop parks.
521
- """
507
+ consumer sees exactly 3 groups gathered before the loop parks."""
508
server = server_factory(gather_lookahead=2)
509
engine = gather_engine(server, 8, lookahead=2)
510
@@ -554,8 +540,7 @@ class TestGatherCredit:
540
def test_a_gather_error_releases_a_blocked_wait_freed(self, server_factory):
541
"""Otherwise a trainer-side failure on another rank deadlocks this one
542
inside its credit gate. It must RAISE, not return empty — an empty
557
- return would spin the engine straight back into the wait.
558
- """
543
+ return would spin the engine straight back into the wait."""
544
server = server_factory()
545
server.begin_sync(1)
546
_publish(server, GI_A, GROUP_A)
@@ -636,8 +621,7 @@ class TestBeginSync:
621
622
def test_the_target_is_floored_at_one(self, server_factory):
623
"""A bare/zero call must not make every group free instantly (or divide
639
- the barrier by zero).
640
- """
624
+ the barrier by zero)."""
625
server = server_factory()
626
server.begin_sync(0)
627
assert server._live_count == 1
@@ -645,8 +629,7 @@ class TestBeginSync:
629
def test_a_degraded_sync_lowers_the_target(self, server_factory):
630
"""FT degraded sync: the live count is the WHOLE degraded-sync
631
mechanism on this side — the group releases after the live consumers
648
- alone.
649
- """
632
+ alone."""
633
server = server_factory()
634
server.begin_sync(2) # 4 provisioned, 2 alive
635
_publish(server, GI_A, GROUP_A)
@@ -670,8 +653,7 @@ class TestBeginSync:
653
def test_a_straggler_signal_cannot_credit_the_next_sync(self, server_factory):
654
"""begin_sync resets the counts, so a signal that leaked past the sync
655
boundary would over-credit — the reason the consumer drains its fired
673
- signals before finishing. Pin the reset side of that contract.
674
- """
656
+ signals before finishing. Pin the reset side of that contract."""
657
server = server_factory()
658
server.begin_sync(2)
659
_publish(server, GI_A, GROUP_A)
@@ -693,8 +675,7 @@ class TestBeginSync:
675
self, server_factory
676
):
677
"""The packed layout repeats every sync — that is what makes caching the
696
- destination views worth ~5ms per 384-spec group.
697
- """
678
+ destination views worth ~5ms per 384-spec group."""
679
server = server_factory()
680
server._pack_dsts[("sentinel",)] = (0, [])
681
server.begin_sync(1)
@@ -705,8 +686,7 @@ class TestServedNamesGuard:
686
"""A producer serves only the names it holds: its stage's groups, and
687
within them its own EP coordinate's experts plus the replicated names.
688
Without this guard a misrouted pull would block forever in the cache wait
708
- for a name this rank never publishes.
709
- """
689
+ for a name this rank never publishes."""
690
691
def test_a_pull_for_an_unserved_name_fails_loudly(self, server_factory):
692
server = server_factory(served_names=list(GROUP_A))
@@ -722,8 +702,7 @@ class TestServedNamesGuard:
702
703
def test_served_names_none_accepts_anything(self, server_factory):
704
"""Gather-to-all: every producer holds every group, so there is nothing
725
- to guard. The call proceeds to the cache wait (not exercised here).
726
- """
705
+ to guard. The call proceeds to the cache wait (not exercised here)."""
706
server = server_factory(served_names=None)
707
assert server._served_names is None
708
@@ -770,8 +749,7 @@ class TestStallWatchdog:
749
750
def test_end_sync_fails_when_a_consumer_never_signals(self, server_factory):
751
"""The exact mid-sync death signature: the group is published, one of
773
- the two live consumers that owed a signal is gone.
774
- """
752
+ the two live consumers that owed a signal is gone."""
753
server = server_factory(stall_timeout_s=0.3)
754
server.begin_sync(2)
755
_publish(server, GI_A, GROUP_A)
@@ -785,8 +763,7 @@ class TestStallWatchdog:
763
"""The watchdog fires on the existing `set_gather_error` channel, so one
764
stall unwinds the whole rank through one path rather than each waiter
765
timing out separately — here both a consumer parked in the serve cache
788
- wait and the engine parked in its credit gate.
789
- """
766
+ wait and the engine parked in its credit gate."""
767
server = server_factory(gather_lookahead=1, stall_timeout_s=0.3)
768
server.begin_sync(1)
769
_publish(server, GI_A, GROUP_A)
@@ -819,8 +796,7 @@ class TestStallWatchdog:
796
"""A consumer that is slow but signaling must never trip it: the stamp
797
is global to the producer, so a steady trickle of signals holds the
798
whole rank open. Nine sequential publishes with a 0.3s timeout each take
822
- longer in total than the timeout, and none may fire.
823
- """
799
+ longer in total than the timeout, and none may fire."""
800
server = server_factory(gather_lookahead=1, stall_timeout_s=0.3)
801
server.begin_sync(1)
802
for gi in range(9):
@@ -833,8 +809,7 @@ class TestStallWatchdog:
809
810
def test_begin_sync_resets_the_progress_stamp(self, server_factory):
811
"""Syncs are minutes apart. Without the reset the first publish of sync N+1
836
- would measure its stall from somewhere inside sync N and fire immediately.
837
- """
812
+ would measure its stall from somewhere inside sync N and fire immediately."""
813
server = server_factory(gather_lookahead=1, stall_timeout_s=0.3)
814
server.begin_sync(1)
815
_publish(server, GI_A, GROUP_A)
@@ -856,8 +831,7 @@ class TestConcurrentPublishAndFree:
831
self, server_factory
832
):
833
"""Every group published must end up freed and out of the cache, with
859
- end_sync returning cleanly — the property whose violation is a hang.
860
- """
834
+ end_sync returning cleanly — the property whose violation is a hang."""
835
server = server_factory(gather_lookahead=2)
836
server.begin_sync(1)
837
groups = [(gi, (f"model.layers.{gi}.w",)) for gi in range(12)]
@@ -892,8 +866,7 @@ class TestConcurrentPublishAndFree:
866
):
867
"""All live consumers signaling at once: the release must happen on the
868
last signal and only once, or the engine drops IPC refs twice (or
895
- never).
896
- """
869
+ never)."""
870
server = server_factory()
871
server.begin_sync(8)
872
_publish(server, GI_A, GROUP_A)
@@ -920,8 +893,7 @@ class TestFakeServerAgreesWithTheRealOne:
893
"""`test_sharded_rdt_trainer.py`'s `_FakeProducerServer` is a second,
894
independent model of this protocol that the engine-side tests assert on. Pin
895
the two against each other so the fake cannot silently drift from the
923
- semantics the real server enforces.
924
- """
896
+ semantics the real server enforces."""
897
898
@staticmethod
899
def _fake():
@@ -952,8 +924,7 @@ class TestExportRing:
924
"""The packed export path. Its one hard invariant is that the trainer packs
925
a group exactly the way ``publish_group`` rebuilds it — a layout
926
disagreement would serve the wrong bytes with nothing downstream to catch
955
- it.
956
- """
927
+ it."""
928
929
@staticmethod
930
def _engine():
@@ -1045,8 +1016,7 @@ class TestExportRingSlotSafety:
1016
):
1017
"""Free the later group of each pair first and hold the earlier one live
1018
until the NEXT group is gathered -- the window a modular slot counter got
1048
- wrong (at lookahead=1 there are 2 slots, so group 2 took group 0's).
1049
- """
1019
+ wrong (at lookahead=1 there are 2 slots, so group 2 took group 0's)."""
1020
server = server_factory(gather_lookahead=1)
1021
n_groups = 8
1022
engine = gather_engine(server, n_groups, lookahead=1)
@@ -1170,8 +1140,7 @@ class TestSharedServeSlots:
1140
1141
def test_one_deployment_never_shares(self, sharing_server):
1142
"""With the width equal to the live count every group is a singleton, so
1173
- each call packs for itself out of its own ring.
1174
- """
1143
+ each call packs for itself out of its own ring."""
1144
server = sharing_server(workers_per_replica=2)
1145
server.begin_sync(2, [0, 1])
1146
_publish(server, GI_A, GROUP_A)
@@ -1251,8 +1220,7 @@ class TestSharedServeSlots:
1220
1221
def test_a_seqless_call_is_refused(self, sharing_server):
1222
"""The slot comes from ``seq``, so a caller that sends none cannot be
1254
- served safely.
1255
- """
1223
+ served safely."""
1224
server = sharing_server(workers_per_replica=2)
1225
server.begin_sync(1, [0])
1226
_publish(server, GI_A, GROUP_A)
@@ -1262,8 +1230,7 @@ class TestSharedServeSlots:
1230
1231
def test_a_failed_pack_reaches_every_sharer(self, sharing_server):
1232
"""Only the packer touches the buffer, so its failure has to be
1265
- republished: a waiter must raise rather than read a half-written slot.
1266
- """
1233
+ republished: a waiter must raise rather than read a half-written slot."""
1234
server = sharing_server(workers_per_replica=2)
1235
server.begin_sync(4, [0, 1, 2, 3])
1236
_publish(server, GI_A, GROUP_A)
@@ -1287,8 +1254,7 @@ class TestSharedServeSlots:
1254
1255
def test_a_degraded_sync_narrows_the_rendezvous(self, sharing_server):
1256
"""A dead deployment must not be waited for: a survivor left alone in
1290
- its group packs for itself instead of blocking on the corpse.
1291
- """
1257
+ its group packs for itself instead of blocking on the corpse."""
1258
server = sharing_server(workers_per_replica=2, stall_timeout_s=30.0)
1259
server.begin_sync(3, [0, 1, 3]) # consumer 2 died
1260
_publish(server, GI_A, GROUP_A)
@@ -1302,8 +1268,7 @@ class TestSharedServeSlots:
1268
1269
def test_a_sharer_that_never_arrives_trips_the_watchdog(self, sharing_server):
1270
"""A consumer that dies INSIDE the sync window has no detector, exactly
1305
- as for the free barrier; the rendezvous waits on the same channel.
1306
- """
1271
+ as for the free barrier; the rendezvous waits on the same channel."""
1272
server = sharing_server(workers_per_replica=2, stall_timeout_s=0.3)
1273
server.begin_sync(4, [0, 1, 2, 3])
1274
_publish(server, GI_A, GROUP_A)
@@ -1315,8 +1280,7 @@ class TestSharedServeSlots:
1280
1281
class TestSharedReservation:
1282
"""``reserve_serve_buffer`` under sharing: one ring per GROUP, and the
1318
- init-time check that the group's members pull the same chunks.
1319
- """
1283
+ init-time check that the group's members pull the same chunks."""
1284
1285
def test_matching_plans_reserve_one_ring_between_them(self, sharing_server):
1286
server = sharing_server(workers_per_replica=2)
@@ -1338,8 +1302,7 @@ class TestSharedReservation:
1302
def test_mismatched_plans_fail_at_reservation(self, sharing_server):
1303
"""Sharing rests on the sharers pulling the same chunks. Checked here,
1304
where it names both consumers, rather than at serve time, where it is a
1341
- rendezvous nobody completes.
1342
- """
1305
+ rendezvous nobody completes."""
1306
server = sharing_server(workers_per_replica=2)
1307
server.reserve_serve_buffer(0, 1024, "plan-a")
1308
@@ -1348,8 +1311,7 @@ class TestSharedReservation:
1311
1312
def test_different_groups_may_differ(self, sharing_server):
1313
"""Only the members of ONE group have to agree; worker 0 and worker 1 of
1351
- the same deployment hold different slices and never share a slot.
1352
- """
1314
+ the same deployment hold different slices and never share a slot."""
1315
server = sharing_server(workers_per_replica=2)
1316
server.reserve_serve_buffer(0, 1024, "plan-a")
1317
server.reserve_serve_buffer(1, 1024, "plan-b")
@@ -1358,8 +1320,7 @@ class TestSharedReservation:
1320
1321
def test_a_missing_digest_skips_the_check(self, sharing_server):
1322
"""The digest is optional on the wire, so an engine that does not send
1361
- one still reserves.
1362
- """
1323
+ one still reserves."""
1324
server = sharing_server(workers_per_replica=2)
1325
server.reserve_serve_buffer(0, 1024, None)
1326
server.reserve_serve_buffer(2, 1024, None)
tests/distributed/test_sharded_rdt_trainer.py
+12
-24
@@ -34,8 +34,7 @@ from vllm.distributed.weight_transfer.sharded_rdt_trainer import (
34
35
class _ListSource(WeightSource):
36
"""A WeightSource over an explicit ordered (name, cpu-tensor) list, so the
37
- sharded-RDT group/order logic can be tested without a real model.
38
- """
37
+ sharded-RDT group/order logic can be tested without a real model."""
38
39
def __init__(self, pairs):
40
self._pairs = list(pairs)
@@ -55,8 +54,7 @@ class _FakeProducerServer:
54
per-group barrier: publish/free are keyed by GROUP INDEX, signals count
55
to the ``begin_sync`` live total, publish_group returns nothing, and freed
56
groups flow back only through wait_freed / end_sync (see
58
- test_sharded_rdt_producer.TestFakeServerAgreesWithTheRealOne).
59
- """
57
+ test_sharded_rdt_producer.TestFakeServerAgreesWithTheRealOne)."""
58
59
def __init__(self, auto_free=True):
60
self.order: list[str] = []
@@ -100,8 +98,7 @@ class _FakeProducerServer:
98
must already have a banked credit when the gate asks (auto_free, or a
99
test's own free_group) — anything else is the deadlock the real
100
watchdog would kill, so fail loudly. Not appended to ``order``: it is
103
- pacing, not a lifecycle milestone.
104
- """
101
+ pacing, not a lifecycle milestone."""
102
assert self._pending_freed, (
103
"wait_freed with nothing freed: the gather loop would deadlock"
104
)
@@ -124,8 +121,7 @@ def _rdt_engine_with_fake_server(
121
):
122
"""Build a ShardedRDTTrainerWeightTransferEngine wired to an in-process fake
123
server (no Ray, no CUDA IPC): bypass trainer_init's spawn, set the
127
- group-major metadata, and route _rpc to the fake.
128
- """
124
+ group-major metadata, and route _rpc to the fake."""
125
import vllm.distributed.weight_transfer.sharded_rdt_trainer as mod
126
127
# reduce_tensor needs CUDA; the fake server never rebuilds, so stub it.
@@ -325,8 +321,7 @@ def test_sharded_rdt_send_weights_surfaces_update_error(monkeypatch):
321
322
class _OwnedSource(_ListSource):
323
"""A source holding only some groups' names, like a pipeline-parallel rank.
328
- Takes group indices for convenience and declares the names inside them.
329
- """
324
+ Takes group indices for convenience and declares the names inside them."""
325
326
def __init__(self, pairs, owned_group_idx):
327
super().__init__(pairs)
@@ -392,8 +387,7 @@ def test_sharded_rdt_owned_group_order_mismatch_raises(monkeypatch):
387
)
388
def test_sharded_rdt_begin_sync_carries_the_live_count(monkeypatch):
389
"""The free barrier's target is one integer per sync: the live consumer
395
- count, defaulting to the whole provisioned fleet.
396
- """
390
+ count, defaulting to the whole provisioned fleet."""
391
server = _FakeProducerServer(auto_free=True)
392
engine = _rdt_engine_with_fake_server(
393
_rdt_source_two_layers(),
@@ -411,8 +405,7 @@ def test_sharded_rdt_begin_sync_carries_the_live_count(monkeypatch):
405
class TestLiveCountPlumbing:
406
"""``send_weights(live_consumer_ids)`` -> the barrier target. The
407
provisioned geometry is frozen; a degraded sync only lowers the target and
414
- narrows each slot-sharing group's rendezvous.
415
- """
408
+ narrows each slot-sharing group's rendezvous."""
409
410
@staticmethod
411
def _engine(num_consumers, world=2, rank=0):
@@ -445,8 +438,7 @@ class TestLiveCountPlumbing:
438
439
def test_which_consumers_died_does_not_matter_only_how_many(self):
440
"""The whole point of the barrier: no routed per-producer targets, so
448
- the identity of the dead consumer is irrelevant to the producers.
449
- """
441
+ the identity of the dead consumer is irrelevant to the producers."""
442
counts = []
443
for live in ([0, 1, 2, 3], [4, 5, 6, 7], [0, 2, 4, 6]):
444
engine, got = self._engine(num_consumers=8)
@@ -457,8 +449,7 @@ class TestLiveCountPlumbing:
449
def test_the_live_ids_travel_with_the_count(self):
450
"""The count sizes the free barrier, the ids size the slot-sharing
451
rendezvous, so a producer that shares slots can tell WHICH consumers it
460
- is still waiting for. They must describe the same set.
461
- """
452
+ is still waiting for. They must describe the same set."""
453
engine, got = self._engine(num_consumers=8)
454
engine.send_weights([6, 0, 2, 2])
455
((count, ids),) = got
@@ -526,8 +517,7 @@ def test_sharded_rdt_rejects_a_rank_holding_nothing(monkeypatch):
517
518
def test_sharded_rdt_rejects_a_name_no_rank_holds(monkeypatch):
519
"""Every name must be held somewhere or it can never be served — caught
529
- when the holdings are transposed, naming the orphan.
530
- """
520
+ when the holdings are transposed, naming the orphan."""
521
with pytest.raises(ValueError, match="no trainer rank holds"):
522
_rdt_engine_with_fake_server(
523
_OwnedSource(_rdt_source_two_layers()._pairs, [0, 1]),
@@ -541,8 +531,7 @@ def test_sharded_rdt_rejects_a_name_no_rank_holds(monkeypatch):
531
532
def test_sharded_rdt_rejects_metadata_disagreement_across_ranks(monkeypatch):
533
"""Only the sender's metadata reaches the consumers, so a rank describing
544
- just its own share must fail loudly rather than silently drop the rest.
545
- """
534
+ just its own share must fail loudly rather than silently drop the rest."""
535
engine = _rdt_engine_with_fake_server(
536
_OwnedSource(_rdt_source_two_layers()._pairs, [1, 2]),
537
is_sender=False,
@@ -565,8 +554,7 @@ def _serve_ring_server(src_name, src):
554
"""A producer server with one cached tensor and a pre-seeded serve ring, so a
555
pull needs no Ray and no NIXL registration. Returns (server, serve) where
556
``serve(chain)`` packs one spec into the SAME ring slot every time — which is
568
- what puts the destination-view cache, and only it, under test.
569
- """
557
+ what puts the destination-view cache, and only it, under test."""
558
from vllm.distributed.weight_transfer.sharded_rdt_trainer import (
559
_RDTProducerServer,
560
)
tests/distributed/test_shm_broadcast.py
+3
-6
@@ -419,8 +419,7 @@ def test_tensor_broadcast():
419
420
def _dumps_oob(obj) -> tuple[bytes, list]:
421
"""Pickle `obj` the same way `MessageQueue.enqueue` does: tensor
422
- dispatch table + out-of-band buffers >= 1MiB.
423
- """
422
+ dispatch table + out-of-band buffers >= 1MiB."""
423
buffers = []
424
425
def callback(buf: pickle.PickleBuffer) -> bool:
@@ -491,8 +490,7 @@ def test_tensor_pickle_roundtrip(case: str):
490
@pytest.mark.parametrize("case", ["cuda", "requires_grad", "conj"])
491
def test_reduce_tensor_fallback(case: str):
492
"""Tensors the zero-copy reducer can't safely alias must fall back to
494
- torch's default reduction.
495
- """
493
+ torch's default reduction."""
494
if case == "cuda":
495
if not torch.cuda.is_available():
496
pytest.skip("requires CUDA")
@@ -755,8 +753,7 @@ def test_remote_subscribe_addr_unique_concurrent_writers(
753
Pre-fix, the writer probed a port with get_open_port() and bound it
754
afterwards; pinning the probe to one free port makes every writer
755
bind the same port and fail deterministically on that code path,
758
- while the late-binding implementation never consults the probe.
759
- """
756
+ while the late-binding implementation never consults the probe."""
757
from vllm.distributed.device_communicators import shm_broadcast
758
759
colliding_port = get_open_port()
tests/distributed/test_utils.py
+1
-2
@@ -31,8 +31,7 @@ class _CUDADeviceCountStatelessTestActor:
31
32
def test_cuda_device_count_stateless():
33
"""Test that cuda_device_count_stateless changes return value if
34
- CUDA_VISIBLE_DEVICES is changed.
35
- """
34
+ CUDA_VISIBLE_DEVICES is changed."""
35
if current_platform.is_rocm():
36
pytest.skip("Skip for ROCm because Ray uses HIP_VISIBLE_DEVICES.")
37
actor = _CUDADeviceCountStatelessTestActor.options( # type: ignore
tests/distributed/test_weight_transfer.py
+22
-44
@@ -1166,8 +1166,7 @@ class RecordingClient:
1166
1167
def _module_with(*pairs):
1168
"""A tiny nn.Module exposing the given (name, tensor) pairs as parameters,
1169
- so trainer tests can build a ModuleSource without a real model.
1170
- """
1169
+ so trainer tests can build a ModuleSource without a real model."""
1170
module = torch.nn.Module()
1171
for name, tensor in pairs:
1172
module.register_parameter(name, torch.nn.Parameter(tensor, requires_grad=False))
@@ -1288,8 +1287,7 @@ class TestModuleSource:
1287
1288
def test_metadata_agrees_with_iteration(self):
1289
"""The two channels must line up element-for-element: engines declare
1291
- the round from `metadata()` and then send what iteration yields.
1292
- """
1290
+ the round from `metadata()` and then send what iteration yields."""
1291
source = ModuleSource(
1292
_module_with(("w", torch.zeros(2, 3)), ("b", torch.zeros(3)))
1293
)
@@ -1303,13 +1301,11 @@ class TestModuleSource:
1301
class TestWeightSourceGroupContract:
1302
"""`groups()` / `iter_groups()` on the WeightSource ABC. Groups are what
1303
backends gather and free by, so the default must agree with
1306
- `layerwise_groups` over `metadata()`, restricted to what this rank holds.
1307
- """
1304
+ `layerwise_groups` over `metadata()`, restricted to what this rank holds."""
1305
1306
class _Source(WeightSource):
1307
"""Minimal source over an ordered (name, tensor) list, optionally holding
1311
- only some names (in which case it iterates only their groups).
1312
- """
1308
+ only some names (in which case it iterates only their groups)."""
1309
1310
def __init__(self, names, held=None, reverse=False):
1311
self._pairs = [(n, torch.full((2,), float(i))) for i, n in enumerate(names)]
@@ -1364,8 +1360,7 @@ class TestWeightSourceGroupContract:
1360
def test_groups_order_follows_metadata_not_the_declaration(self):
1361
"""The declaration is a SET of names; the groups it selects still come
1362
out in metadata order, so each pairs with the right ``iter_groups()``
1367
- batch however the source listed them.
1368
- """
1363
+ batch however the source listed them."""
1364
names = ["embed.w", "model.layers.0.a", "model.layers.1.a", "norm.w"]
1365
source = self._source(
1366
names, held=["model.layers.1.a", "model.layers.0.a", "model.layers.1.a"]
@@ -1399,16 +1394,14 @@ class TestWeightSourceGroupContract:
1394
1395
def test_out_of_order_iteration_raises(self):
1396
"""Materializing is usually a collective, so a rank that iterates out of
1402
- order deadlocks its peers -- fail loudly instead.
1403
- """
1397
+ order deadlocks its peers -- fail loudly instead."""
1398
source = self._source(["model.layers.0.a", "model.layers.0.b"], reverse=True)
1399
with pytest.raises(RuntimeError, match="iteration order must match"):
1400
list(source.iter_groups())
1401
1402
def test_a_source_may_override_iter_groups(self):
1403
"""The extension point: materialize a whole group in one step instead of
1410
- one generator resume per tensor.
1411
- """
1404
+ one generator resume per tensor."""
1405
calls = []
1406
1407
class _Batched(TestWeightSourceGroupContract._Source):
@@ -1429,8 +1422,7 @@ class TestDeferredProcessingContract:
1422
caller that takes over the update tail (running its own
1423
`finalize_layerwise_reload` instead of going through `finish_weight_update`)
1424
reads the flag and calls the method. Both must be answerable on any engine, or
1432
- that caller ends up reaching through a getattr.
1433
- """
1425
+ that caller ends up reaching through a getattr."""
1426
1427
def _engines(self):
1428
return {
@@ -1444,8 +1436,7 @@ class TestDeferredProcessingContract:
1436
1437
def test_every_engine_can_be_drained(self):
1438
"""The default is a no-op, so a caller never has to check whether the
1447
- method exists before calling it.
1448
- """
1439
+ method exists before calling it."""
1440
for name, cls in self._engines().items():
1441
assert callable(cls.drain_pending), name
1442
@@ -1539,8 +1530,7 @@ class TestTrainerEngineBase:
1530
)
1531
def test_ipc_trainer_send_weights_drives_client_in_order():
1532
"""send_weights issues start -> update -> finish and ships per-round metadata;
1542
- the packed wire param rides the init info, not the per-round update_info.
1543
- """
1533
+ the packed wire param rides the init info, not the per-round update_info."""
1534
client = RecordingClient()
1535
engine = IPCTrainerWeightTransferEngine(
1536
client=client,
@@ -1559,8 +1549,7 @@ def test_ipc_trainer_send_weights_drives_client_in_order():
1549
1550
def test_ipc_trainer_init_ships_packed_to_worker():
1551
"""trainer_init drives the inference-side init handshake and propagates the
1562
- must-agree `packed` flag to the worker.
1563
- """
1552
+ must-agree `packed` flag to the worker."""
1553
if torch.accelerator.device_count() < 1:
1554
pytest.skip("Need at least 1 GPU (CUDA IPC handles).")
1555
@@ -1581,8 +1570,7 @@ def test_ipc_trainer_init_ships_packed_to_worker():
1570
def test_nccl_trainer_init_ships_worker_init_info(monkeypatch):
1571
"""The sender's trainer_init drives the inference-side init handshake with
1572
the worker-shaped init info (rank_offset=1) while opening its own endpoint,
1584
- and propagates the must-agree wire params to the worker.
1585
- """
1573
+ and propagates the must-agree wire params to the worker."""
1574
import vllm.distributed.weight_transfer.nccl_engine as nccl_engine_mod
1575
1576
# Bypass the real NCCL rendezvous.
@@ -1623,8 +1611,7 @@ def test_nccl_trainer_init_ships_worker_init_info(monkeypatch):
1611
def test_nccl_worker_learns_wire_params_from_init_handshake(monkeypatch):
1612
"""The worker engine reads packed + buffer geometry from the
1613
trainer-supplied init info at the handshake, not from the config or the
1626
- per-round update info.
1627
- """
1614
+ per-round update info."""
1615
import vllm.distributed.weight_transfer.nccl_engine as nccl_engine_mod
1616
1617
monkeypatch.setattr(
@@ -1657,8 +1644,7 @@ def test_nccl_worker_learns_wire_params_from_init_handshake(monkeypatch):
1644
1645
def test_nccl_trainer_init_non_sender_skips_rendezvous_and_client():
1646
"""Non-sender trainer ranks build an engine without opening an endpoint or
1660
- touching the client; they only join the collectives in send_weights.
1661
- """
1647
+ touching the client; they only join the collectives in send_weights."""
1648
client = RecordingClient()
1649
engine = WeightTransferTrainerFactory.trainer_init(
1650
init_info=NCCLTrainerInitInfo(
@@ -1688,8 +1674,7 @@ def test_nccl_trainer_init_non_sender_skips_rendezvous_and_client():
1674
def test_nccl_trainer_send_weights_drives_client_in_order():
1675
"""send_weights issues start -> update -> finish and ships per-round
1676
metadata; the packed wire params ride the init handshake, not the
1691
- per-round update_info.
1692
- """
1677
+ per-round update_info."""
1678
client = RecordingClient()
1679
engine = NCCLTrainerWeightTransferEngine(
1680
client=client,
@@ -1710,8 +1695,7 @@ def test_nccl_trainer_send_weights_drives_client_in_order():
1695
1696
class _ScriptedSource(WeightSource):
1697
"""Declares `meta` but yields whatever `pairs` says — used to drive the
1713
- metadata/iteration agreement checks.
1714
- """
1698
+ metadata/iteration agreement checks."""
1699
1700
def __init__(self, meta, pairs):
1701
self._meta = meta
@@ -1747,8 +1731,7 @@ def test_nccl_trainer_init_requires_source():
1731
1732
def test_nccl_trainer_send_weights_rejects_reordered_source(monkeypatch):
1733
"""The worker sizes its buffers (and cuts packed chunks) from metadata(), so
1750
- iteration disagreeing with it must raise rather than corrupt the stream.
1751
- """
1734
+ iteration disagreeing with it must raise rather than corrupt the stream."""
1735
meta = [
1736
ParamMeta("w", torch.float32, (4,)),
1737
ParamMeta("b", torch.float32, (2,)),
@@ -1762,8 +1745,7 @@ def test_nccl_trainer_send_weights_rejects_reordered_source(monkeypatch):
1745
1746
def test_nccl_trainer_send_weights_rejects_dtype_disagreement(monkeypatch):
1747
"""A source that declares one wire dtype and materializes another would make
1765
- the two sides disagree on every byte offset.
1766
- """
1748
+ the two sides disagree on every byte offset."""
1749
meta = [ParamMeta("w", torch.float32, (4,))]
1750
engine = _mock_group_engine(
1751
_ScriptedSource(meta, [("w", torch.zeros(4, dtype=torch.bfloat16))]),
@@ -1790,8 +1772,7 @@ def test_nccl_trainer_send_weights_rejects_truncated_source(monkeypatch):
1772
1773
def test_nccl_trainer_send_weights_broadcasts_contiguous(monkeypatch):
1774
"""NCCL sends numel elements from data_ptr(), so a non-contiguous view must
1793
- be linearized first or the worker receives unrelated memory.
1794
- """
1775
+ be linearized first or the worker receives unrelated memory."""
1776
base = torch.arange(6, dtype=torch.float32).reshape(2, 3)
1777
view = base.t() # non-contiguous
1778
meta = [ParamMeta("w", torch.float32, tuple(view.shape))]
@@ -1861,8 +1842,7 @@ def _sparse_patch(device: str = "cpu") -> SparseWeightPatch:
1842
def test_sparse_nccl_trainer_init_ships_worker_init_info(monkeypatch):
1843
"""The sender's trainer_init drives the init handshake with the
1844
worker-shaped init info; sparse ships no packed wire params, so the worker
1864
- keeps its unpacked defaults. Sparse takes no `source`.
1865
- """
1845
+ keeps its unpacked defaults. Sparse takes no `source`."""
1846
import vllm.distributed.weight_transfer.sparse_nccl_engine as sparse_mod
1847
1848
monkeypatch.setattr(sparse_mod, "open_trainer_endpoint", lambda info: MagicMock())
@@ -1915,8 +1895,7 @@ def test_sparse_nccl_trainer_send_weights_drives_client_in_order(monkeypatch):
1895
1896
def test_sparse_nccl_trainer_send_weights_empty_round_is_noop():
1897
"""A round with no patches must not touch the client (an empty sparse
1918
- update info is invalid by construction).
1919
- """
1898
+ update info is invalid by construction)."""
1899
client = RecordingClient()
1900
engine = SparseNCCLTrainerWeightTransferEngine(client=client)
1901
engine.model_update_group = MagicMock()
@@ -1952,8 +1931,7 @@ def test_sparse_nccl_trainer_rejects_source():
1931
def test_sparse_nccl_trainer_validates_patch_before_any_rpc():
1932
"""Malformed patches must fail on the trainer, before start_weight_update:
1933
the worker's own checks only run once the broadcasts are already in flight,
1955
- where a size mismatch wedges both sides instead of raising.
1956
- """
1934
+ where a size mismatch wedges both sides instead of raising."""
1935
client = RecordingClient()
1936
engine = SparseNCCLTrainerWeightTransferEngine(client=client)
1937
engine.model_update_group = MagicMock()
tests/distributed/test_weight_transfer_nccl_uid.py
+3
-6
@@ -403,8 +403,7 @@ def trainer_broadcast_tensor_torch_free(
403
def _run_uid_transfer(trainer_task) -> None:
404
"""Mint a unique id, run the worker and the given trainer peer concurrently,
405
and assert the tensor round-trips. Both ranks must enter init together --
406
- there is no store barrier on the UID path.
407
- """
406
+ there is no store barrier on the UID path."""
407
from vllm.distributed.device_communicators.pynccl_wrapper import NCCLLibrary
408
409
_init_ray_for_weight_transfer()
@@ -451,8 +450,7 @@ def _run_uid_transfer(trainer_task) -> None:
450
)
451
def test_nccl_weight_transfer_between_processes_uid():
452
"""Weight transfer over a pre-shared ncclUniqueId (no TCPStore), with both
454
- ranks on vLLM's ``PyNcclCommunicator``.
455
- """
453
+ ranks on vLLM's ``PyNcclCommunicator``."""
454
_run_uid_transfer(trainer_broadcast_tensor_uid)
455
456
@@ -462,7 +460,6 @@ def test_nccl_weight_transfer_between_processes_uid():
460
)
461
def test_nccl_weight_transfer_torch_free_trainer():
462
"""UID weight transfer against a foreign peer that uses no torch and no vLLM
465
- communicator, only a cupy buffer and raw ``ncclBroadcast``.
466
- """
463
+ communicator, only a cupy buffer and raw ``ncclBroadcast``."""
464
pytest.importorskip("cupy")
465
_run_uid_transfer(trainer_broadcast_tensor_torch_free)
tests/engine/test_arg_utils.py
+5
-10
@@ -570,8 +570,7 @@ def test_attention_config():
570
def test_multi_node_world_size_includes_pcp(monkeypatch):
571
"""PCP expands the process world size, so the --nnodes divisibility check
572
must include it. Without this, TP=1/PCP=2 over 2 nodes computes a world
573
- size of 1 and the launch is rejected before the engine starts.
574
- """
573
+ size of 1 and the launch is rejected before the engine starts."""
574
import vllm.config.vllm
575
576
# PCP requires the V2 model runner, which is gated on Triton.
@@ -797,8 +796,7 @@ def test_expand_json_human_readable_numbers(input_json, expected_json):
796
)
797
def test_cloud_storage_uri_skips_get_model_path(uri, monkeypatch):
798
"""Cloud storage URIs should not be passed to get_model_path()
800
- when HF_HUB_OFFLINE=1, as they are not valid HF repo IDs.
801
- """
799
+ when HF_HUB_OFFLINE=1, as they are not valid HF repo IDs."""
800
import huggingface_hub
801
802
monkeypatch.setattr(huggingface_hub.constants, "HF_HUB_OFFLINE", True)
@@ -810,8 +808,7 @@ def test_cloud_storage_uri_skips_get_model_path(uri, monkeypatch):
808
809
def test_cloud_storage_tokenizer_skips_get_model_path(monkeypatch):
810
"""Cloud storage tokenizer URI should not be passed to
813
- get_model_path() when HF_HUB_OFFLINE=1.
814
- """
811
+ get_model_path() when HF_HUB_OFFLINE=1."""
812
import huggingface_hub
813
814
monkeypatch.setattr(huggingface_hub.constants, "HF_HUB_OFFLINE", True)
@@ -973,8 +970,7 @@ class TestDpDeviceIdSharding:
970
def test_dp_supervisor_device_ids_stay_env_relative(self):
971
"""Regression test: the DP supervisor must pass env-relative indices,
972
not physical IDs, because each child re-resolves --device-ids
976
- against its inherited device-control env var.
977
- """
973
+ against its inherited device-control env var."""
974
import argparse
975
976
from vllm.entrypoints.launchers.dp_supervisor import _build_device_ids
@@ -1001,8 +997,7 @@ class TestDpDeviceIdSharding:
997
998
def test_dp_rank_shards_user_assigned_gpu_ids(self):
999
"""get_physical_gpu_ids_for_local_dp_rank slices the user-provided
1004
- --device-ids list instead of recomputing from the env var.
1005
- """
1000
+ --device-ids list instead of recomputing from the env var."""
1001
from vllm.platforms import current_platform
1002
from vllm.v1.engine.utils import get_physical_gpu_ids_for_local_dp_rank
1003
tests/entrypoints/anthropic/test_anthropic_messages_conversion.py
+10
-20
@@ -241,8 +241,7 @@ class TestToolResultContent:
241
self, tool_result_content
242
) -> AnthropicMessagesRequest:
243
"""Build a request with assistant tool_use followed by user
244
- tool_result.
245
- """
244
+ tool_result."""
245
return _make_request(
246
[
247
{
@@ -327,8 +326,7 @@ class TestToolResultContent:
326
327
def test_tool_result_with_text_and_image(self):
328
"""Mixed text+image tool_result: text in tool msg, image in user
330
- msg.
331
- """
329
+ msg."""
330
request = self._make_tool_result_request(
331
[
332
{"type": "text", "text": "Here is the screenshot"},
@@ -425,8 +423,7 @@ class TestToolResultContent:
423
class TestAttributionHeaderStripping:
424
def test_billing_header_stripped_from_system(self):
425
"""Claude Code's x-anthropic-billing-header block should be
428
- stripped to preserve prefix caching.
429
- """
426
+ stripped to preserve prefix caching."""
427
request = _make_request(
428
[{"role": "user", "content": "Hello"}],
429
system=[
@@ -1150,8 +1147,7 @@ class TestMessageStreamConverterToolUseContentBuffering:
1147
async def test_buffered_content_flushed_on_done_without_usage_chunk(self):
1148
"""Content buffered during tool_use must be emitted even if the
1149
stream jumps straight from finish_reason to [DONE], skipping the
1153
- empty-choices usage chunk.
1154
- """
1150
+ empty-choices usage chunk."""
1151
1152
async def sse_input():
1153
yield _make_stream_chunk(
@@ -1255,8 +1251,7 @@ class TestStreamingCacheUsageSemantics:
1251
async def test_streaming_cache_fields_absent_then_populated(self):
1252
"""First chunk lacks prompt_tokens_details (vLLM contract);
1253
message_start omits cache fields. The final chunk carries
1258
- prompt_tokens_details, so message_delta carries resolved values.
1259
- """
1254
+ prompt_tokens_details, so message_delta carries resolved values."""
1255
1256
async def sse_input():
1257
yield _make_stream_chunk(
@@ -1301,8 +1296,7 @@ class TestStreamingCacheUsageSemantics:
1296
@pytest.mark.asyncio
1297
async def test_streaming_no_cache_hit(self):
1298
"""When the final chunk reports cached_tokens=0, message_delta carries
1304
- cache fields = 0 (cache miss); message_start still omits them.
1305
- """
1299
+ cache fields = 0 (cache miss); message_start still omits them."""
1300
1301
async def sse_input():
1302
yield _make_stream_chunk(
@@ -1343,8 +1337,7 @@ class TestStreamingCacheUsageSemantics:
1337
@pytest.mark.asyncio
1338
async def test_streaming_no_prompt_tokens_details_at_all(self):
1339
"""If --enable-prompt-tokens-details is off, no chunk carries cache
1346
- info; both message_start and message_delta omit cache fields.
1347
- """
1340
+ info; both message_start and message_delta omit cache fields."""
1341
1342
async def sse_input():
1343
yield _make_stream_chunk(
@@ -1465,8 +1458,7 @@ class TestMessagesFullConverter:
1458
class TestCacheSalt:
1459
def test_cache_salt_passed_through(self):
1460
"""cache_salt on the Anthropic request reaches the converted
1468
- ChatCompletionRequest so prefix-cache isolation works via /v1/messages.
1469
- """
1461
+ ChatCompletionRequest so prefix-cache isolation works via /v1/messages."""
1462
request = _make_request(
1463
[{"role": "user", "content": "Hello"}],
1464
cache_salt="tenant-abc-secret-salt",
@@ -1671,8 +1663,7 @@ class TestClientErrorResponses:
1663
@staticmethod
1664
def _conversion_error() -> ValidationError:
1665
"""A real pydantic ValidationError like the one ChatCompletionRequest
1674
- construction raises when Anthropic input violates the OpenAI schema.
1675
- """
1666
+ construction raises when Anthropic input violates the OpenAI schema."""
1667
1668
class _StubRequest(BaseModel):
1669
stop: Annotated[list[str], Field(max_length=4)] | None = None
@@ -1683,8 +1674,7 @@ class TestClientErrorResponses:
1674
1675
def test_validation_error_returns_bad_request(self):
1676
"""A pydantic ValidationError during Anthropic->OpenAI conversion is
1686
- surfaced as a 400 BadRequestError, not a 500.
1687
- """
1677
+ surfaced as a 400 BadRequestError, not a 500."""
1678
handler = MagicMock(spec=AnthropicServingMessages)
1679
handler.create_messages.side_effect = self._conversion_error()
1680
tests/entrypoints/cohere/test_serving_streaming.py
+2
-4
@@ -87,8 +87,7 @@ def _make_chunk(
87
citations: list[Any] | None = None,
88
) -> str:
89
"""Build the ``data: {...}\\n\\n`` SSE frame the production code
90
- consumes.
91
- """
90
+ consumes."""
91
delta: dict[str, Any] = {}
92
if role is not None:
93
delta["role"] = role
@@ -136,8 +135,7 @@ async def _stream_from(items: list[str]) -> AsyncGenerator[str, None]:
135
136
async def _drain(serving: CohereServingChatV2, items: list[str]) -> list[str]:
137
"""Drive ``_chat_completion_stream_to_v2`` over ``items`` and collect
139
- the emitted SSE frames.
140
- """
138
+ the emitted SSE frames."""
139
request = CohereChatV2Request(
140
model="m", messages=[{"role": "user", "content": "hi"}], stream=True
141
)
tests/entrypoints/launchers/api_server/test_api_server_process_manager.py
+4
-8
@@ -50,8 +50,7 @@ def update_admission_stats_worker(listen_address, sock, args, client_config):
50
# importable by `multiprocessing.spawn` (no closures, no nesting).
51
def defer_addresses_stub_worker(listen_address, sock, args, client_config):
52
"""Bind ROUTER/PULL with a kernel-assigned port, report the actual
53
- endpoints back via the pipe, then exit.
54
- """
53
+ endpoints back via the pipe, then exit."""
54
ctx = zmq.Context()
55
try:
56
in_sock = make_zmq_socket(
@@ -358,8 +357,7 @@ def test_external_process_monitoring(api_server_args):
357
def test_gather_actual_addresses_end_to_end():
358
"""Each child binds ROUTER/PULL with a kernel-picked port and reports
359
the bound endpoints back via its per-child pipe; the manager surfaces
361
- them via :py:meth:`gather_actual_addresses`.
362
- """
360
+ them via :py:meth:`gather_actual_addresses`."""
361
host = "127.0.0.1"
362
num_servers = 4
363
@@ -409,8 +407,7 @@ def test_gather_actual_addresses_end_to_end():
407
@pytest.mark.timeout(30)
408
def test_gather_actual_addresses_child_crash_before_report():
409
"""A child that exits before sending its endpoints must surface a
412
- clear ``RuntimeError`` rather than hang or return ``None`` slots.
413
- """
410
+ clear ``RuntimeError`` rather than hang or return ``None`` slots."""
411
host = "127.0.0.1"
412
num_servers = 2
413
placeholder_inputs = [
@@ -447,8 +444,7 @@ def test_gather_actual_addresses_child_crash_before_report():
444
445
def test_rust_frontend_launch_log_redacts_credentials(monkeypatch, caplog):
446
"""The Rust frontend command carries every non-default arg as JSON.
450
- Credentials must not reach the log line.
451
- """
447
+ Credentials must not reach the log line."""
448
import subprocess as subprocess_mod
449
450
from vllm.entrypoints.launchers.cli_args import make_arg_parser
tests/entrypoints/launchers/test_cli_args.py
+2
-4
@@ -186,8 +186,7 @@ def test_enable_auto_choice_fails_with_enable_reasoning(serve_parser):
186
187
def test_passes_with_reasoning_parser(serve_parser):
188
"""Ensure validation passes if reasoning is enabled
189
- with a reasoning parser
190
- """
189
+ with a reasoning parser"""
190
args = serve_parser.parse_args(
191
args=[
192
"--reasoning-parser",
@@ -382,8 +381,7 @@ def test_default_chat_template_kwargs_invalid_json(serve_parser):
381
)
382
def test_served_model_name_parsing(tmp_path, vllm_parser, args, raises):
383
"""Ensure that users don't misuse --served-model-name and end up with the default
385
- model tag instead of the one they intended to serve.
386
- """
384
+ model tag instead of the one they intended to serve."""
385
# Call the serve subparser
386
args.insert(0, "serve")
387
# Create a dummy config file if the test case includes it
tests/entrypoints/multimodal/openai/chat_completion/test_chat_completion_with_mixed_audio_embeds.py
+1
-2
@@ -2,8 +2,7 @@
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
"""E2E test for mixing `prompt_embeds` with `audio_embeds` in a single
5
-Chat Completions request.
6
-"""
5
+Chat Completions request."""
6
7
import json
8
tests/entrypoints/multimodal/openai/chat_completion/test_chat_completion_with_mixed_image_embeds.py
+1
-2
@@ -68,8 +68,7 @@ async def client(server):
68
def image_url() -> str:
69
"""Stable real image as a data URL, kept identical across both the
70
text and prompt_embeds requests so any output difference must come from
71
- how the text content is delivered.
72
- """
71
+ how the text content is delivered."""
72
return encode_image_url(ImageAsset("stop_sign").pil_image)
73
74
tests/entrypoints/multimodal/openai/chat_completion/test_vision.py
+2
-4
@@ -145,8 +145,7 @@ def describe_image_messages(
145
) -> list[dict]:
146
"""Build the system + user messages used by the completions-with-image
147
family of tests. *extra_image_fields* is merged into the top-level
148
- image content block (for uuid / bad-key tests).
149
- """
148
+ image content block (for uuid / bad-key tests)."""
149
image_block: dict = {
150
"type": "image_url",
151
"image_url": {"url": image_url},
@@ -176,8 +175,7 @@ async def complete_and_check(
175
temperature: float = 0.0,
176
) -> str:
177
"""Run a chat completion and assert the output is non-empty.
179
- Returns the content string.
180
- """
178
+ Returns the content string."""
179
chat_completion = await client.chat.completions.create(
180
model=model_name,
181
messages=messages,
tests/entrypoints/openai/chat_completion/test_chat_error.py
+2
-4
@@ -465,8 +465,7 @@ def test_system_message_warns_on_video(video_content):
465
def test_json_schema_response_format_missing_schema():
466
"""When response_format type is 'json_schema' but the json_schema field
467
is not provided, request construction should raise a validation error
468
- so the API returns 400 instead of 500.
469
- """
468
+ so the API returns 400 instead of 500."""
469
with pytest.raises(Exception, match="json_schema.*must be provided"):
470
ChatCompletionRequest(
471
model=MODEL_NAME,
@@ -520,8 +519,7 @@ def test_structured_outputs_structural_tag_invalid(structural_tag):
519
@pytest.mark.parametrize("field_name", ["prompt_logprobs", "top_logprobs"])
520
def test_non_numeric_logprobs_rejected(field_name):
521
"""A non-numeric logprobs value must be a clean 400 validation error, not a
523
- TypeError from the mode='before' comparison (which surfaces as HTTP 500).
524
- """
522
+ TypeError from the mode='before' comparison (which surfaces as HTTP 500)."""
523
with pytest.raises(VLLMValidationError, match=f"`{field_name}` must be an integer"):
524
ChatCompletionRequest(
525
model=MODEL_NAME,
tests/entrypoints/openai/chat_completion/test_chat_logit_bias_validation.py
+3
-6
@@ -81,8 +81,7 @@ async def test_chat_logit_bias_invalid(client):
81
@pytest.mark.asyncio
82
async def test_chat_logit_bias_non_integer_key(client):
83
"""Test that a non-integer logit_bias key is rejected with a clean,
84
- informative error instead of a raw 'invalid literal for int()' message.
85
- """
84
+ informative error instead of a raw 'invalid literal for int()' message."""
85
with pytest.raises(openai.BadRequestError) as excinfo:
86
await client.chat.completions.create(
87
model=MODEL_NAME,
@@ -102,8 +101,7 @@ async def test_chat_logit_bias_non_integer_key(client):
101
@pytest.mark.asyncio
102
async def test_chat_logit_bias_non_numeric_value(client):
103
"""Test that a non-numeric logit_bias value is rejected with a message
105
- that names the specific offending token, not just a generic TypeError.
106
- """
104
+ that names the specific offending token, not just a generic TypeError."""
105
with pytest.raises(openai.BadRequestError) as excinfo:
106
await client.chat.completions.create(
107
model=MODEL_NAME,
@@ -122,8 +120,7 @@ async def test_chat_logit_bias_non_numeric_value(client):
120
@pytest.mark.asyncio
121
async def test_chat_logit_bias_multiple_non_integer_keys(client):
122
"""Test that ALL invalid logit_bias keys are reported together,
125
- not just the first one encountered.
126
- """
123
+ not just the first one encountered."""
124
with pytest.raises(openai.BadRequestError) as excinfo:
125
await client.chat.completions.create(
126
model=MODEL_NAME,
tests/entrypoints/openai/chat_completion/test_extra_content_fields.py
+2
-4
@@ -54,8 +54,7 @@ def stop_sign_image_url():
54
async def test_translategemma_extra_lang_code_fields(client: openai.AsyncOpenAI):
55
"""En -> es translation through TranslateGemma's bundled chat template's
56
``text`` content branch, which depends on ``source_lang_code`` /
57
- ``target_lang_code`` extra fields being preserved on the content part.
58
- """
57
+ ``target_lang_code`` extra fields being preserved on the content part."""
58
completion = await client.chat.completions.create(
59
model=MODEL_NAME,
60
messages=[
@@ -99,8 +98,7 @@ async def test_translategemma_image_extra_lang_code_fields(
98
``source_lang_code`` / ``target_lang_code`` extras must survive parsing
99
and end up alongside the ``{"type": "image"}`` placeholder so the
100
template's image branch (``content["type"] == 'image'``) renders the
102
- right OCR-translation prompt.
103
- """
101
+ right OCR-translation prompt."""
102
completion = await client.chat.completions.create(
103
model=MODEL_NAME,
104
messages=[
tests/entrypoints/openai/chat_completion/test_logprob_token_ids.py
+1
-2
@@ -191,8 +191,7 @@ async def test_logprob_token_ids_stream_with_no_top_k(server):
191
async def test_logprob_token_ids_default_behavior_unchanged(server):
192
"""Without `logprob_token_ids`, the response carries the natural top-k
193
most-likely tokens. This guards against the new field accidentally
194
- changing the default-path output.
195
- """
194
+ changing the default-path output."""
195
async with server.get_async_client() as client:
196
resp = await client.chat.completions.create(
197
model=MODEL_NAME,
tests/entrypoints/openai/chat_completion/test_serving_chat.py
+4
-8
@@ -1406,8 +1406,7 @@ async def test_serving_chat_did_set_correct_cache_salt(model_type):
1406
@pytest.mark.asyncio
1407
async def test_serving_chat_data_parallel_rank_extraction():
1408
"""Test that data_parallel_rank is properly extracted from header and
1409
- passed to engine.
1410
- """
1409
+ passed to engine."""
1410
mock_engine = MagicMock(spec=AsyncLLM)
1411
mock_engine.errored = False
1412
mock_engine.model_config = MockModelConfig()
@@ -1729,8 +1728,7 @@ class TestServingChatWithHarmony:
1728
@pytest.mark.asyncio
1729
async def test_system_message_without_tools(self, serving_chat, stream):
1730
"""Leading system message produces a developer message with
1732
- DeveloperContent (# Instructions header).
1733
- """
1731
+ DeveloperContent (# Instructions header)."""
1732
messages = [
1733
{"role": "system", "content": "You are a helpful assistant."},
1734
{"role": "user", "content": "Hello"},
@@ -1752,8 +1750,7 @@ class TestServingChatWithHarmony:
1750
@pytest.mark.asyncio
1751
async def test_system_message_with_tools(self, serving_chat, stream, weather_tools):
1752
"""Leading system message is folded into the developer message
1755
- alongside tool definitions.
1756
- """
1753
+ alongside tool definitions."""
1754
messages = [
1755
{"role": "system", "content": "You are a helpful assistant."},
1756
{"role": "user", "content": "What's the weather?"},
@@ -2168,8 +2165,7 @@ class TestServingChatWithHarmony:
2165
@pytest.mark.asyncio
2166
async def test_tool_choice_validation_without_parser():
2167
"""Test that tool_choice='required' or named tool without tool_parser
2171
- returns an appropriate error message.
2172
- """
2168
+ returns an appropriate error message."""
2169
mock_engine = MagicMock(spec=AsyncLLM)
2170
mock_engine.errored = False
2171
mock_engine.model_config = MockModelConfig()
tests/entrypoints/openai/chat_completion/test_thinking_token_budget.py
+1
-2
@@ -151,8 +151,7 @@ async def client(request, server, server_with_auto_reasoning_config):
151
@pytest.mark.parametrize("client", ["default", "auto_config"], indirect=True)
152
async def test_thinking_token_budget_mixed_requests(client: openai.AsyncOpenAI):
153
"""Test that mixed requests (some with thinking_token_budget, some without)
154
- complete successfully without errors.
155
- """
154
+ complete successfully without errors."""
155
response_with_budget = await client.chat.completions.create(
156
model=MODEL_NAME,
157
messages=MESSAGES,
tests/entrypoints/openai/completion/test_completion_error.py
+3
-6
@@ -521,8 +521,7 @@ async def test_completion_error_stream():
521
def test_json_schema_response_format_missing_schema():
522
"""When response_format type is 'json_schema' but the json_schema field
523
is not provided, request construction should raise a validation error
524
- so the API returns 400 instead of 500.
525
- """
524
+ so the API returns 400 instead of 500."""
525
with pytest.raises(Exception, match="json_schema.*must be provided"):
526
CompletionRequest(
527
model=MODEL_NAME,
@@ -585,8 +584,7 @@ def test_negative_prompt_token_ids_flat():
584
def test_logprobs_minus_one_allowed():
585
"""logprobs=-1 means "return all logprobs". The sampling layer and the chat
586
top_logprobs / prompt_logprobs validators all accept -1, so the completion
588
- logprobs validator must accept it too instead of rejecting it as negative.
589
- """
587
+ logprobs validator must accept it too instead of rejecting it as negative."""
588
request = CompletionRequest(
589
model=MODEL_NAME,
590
prompt="Test prompt",
@@ -746,8 +744,7 @@ class TestCompletionPromptListLimit:
744
@pytest.mark.parametrize("field_name", ["prompt_logprobs", "logprobs"])
745
def test_non_numeric_logprobs_rejected(field_name):
746
"""A non-numeric logprobs value must be a clean 400 validation error, not a
749
- TypeError from the mode='before' comparison (which surfaces as HTTP 500).
750
- """
747
+ TypeError from the mode='before' comparison (which surfaces as HTTP 500)."""
748
with pytest.raises(VLLMValidationError, match=f"`{field_name}` must be an integer"):
749
CompletionRequest(
750
model=MODEL_NAME,
tests/entrypoints/openai/parser/test_harmony_render_parity.py
+4
-8
@@ -43,8 +43,7 @@ def _system():
43
44
class TestResponseInputToHarmonyRenderParity:
45
"""Each test drives the same conversation through both APIs and asserts
46
- identical Harmony messages and rendered token sequences.
47
- """
46
+ identical Harmony messages and rendered token sequences."""
47
48
# -----------------------------------------------------------------------
49
# Single-message cases
@@ -52,8 +51,7 @@ class TestResponseInputToHarmonyRenderParity:
51
52
def test_developer_message(self):
53
"""Both APIs must render developer messages identically using
55
- DeveloperContent (with the '# Instructions' header).
56
- """
54
+ DeveloperContent (with the '# Instructions' header)."""
55
chat_msgs = parse_chat_input_to_harmony_message(
56
{"role": "developer", "content": "Be concise."}
57
)
@@ -248,8 +246,7 @@ class TestResponseInputToHarmonyRenderParity:
246
def test_reasoning_combined_with_function_call(self):
247
"""Chat API packs reasoning + tool_calls into one dict; responses API
248
represents them as two separate items. Both must produce the same two
251
- Harmony messages in the same order: analysis then commentary.
252
- """
249
+ Harmony messages in the same order: analysis then commentary."""
250
chat_msgs = parse_chat_input_to_harmony_message(
251
{
252
"role": "assistant",
@@ -532,8 +529,7 @@ class TestResponseInputToHarmonyRenderParity:
529
def test_completed_turns_drop_reasoning(self):
530
"""Validates that reasoning from completed turns is dropped, while
531
reasoning from the current in-progress tool-call turn is preserved
535
- in both chat completions and responses previous_input_messages.
536
- """
532
+ in both chat completions and responses previous_input_messages."""
533
first_turn_reasoning = "FIRST_TURN_REASONING"
534
second_turn_reasoning = "SECOND_TURN_REASONING"
535
tests/entrypoints/openai/parser/test_harmony_utils.py
+1
-2
@@ -323,8 +323,7 @@ class TestCommonParseInputToHarmonyMessage:
323
324
def test_system_message(self, parse_function):
325
"""Test parsing system messages, which are parsed into developer messages
326
- with DeveloperContent.
327
- """
326
+ with DeveloperContent."""
327
chat_msg = {
328
"role": "system",
329
"content": "You are a helpful assistant",
tests/entrypoints/openai/responses/test_function_call_parsing.py
+3
-6
@@ -12,8 +12,7 @@ from vllm.entrypoints.openai.responses.protocol import ResponsesRequest
12
13
def test_function_call_dict_converted_to_object():
14
"""Test that function_call dictionaries are correctly parsed into
15
- ResponseFunctionToolCall objects.
16
- """
15
+ ResponseFunctionToolCall objects."""
16
# Create a request with function_call as dict
17
request_data = {
18
"model": "gpt-oss",
@@ -330,8 +329,7 @@ def test_validator_handles_empty_iterator():
329
330
def test_assistant_string_content_stays_easyinput():
331
"""EasyInput assistant message with plain string content is not
333
- coerced into a ResponseOutputMessage.
334
- """
332
+ coerced into a ResponseOutputMessage."""
333
request_data = {
334
"model": "test-model",
335
"input": [
@@ -353,8 +351,7 @@ def test_assistant_string_content_stays_easyinput():
351
352
def test_assistant_output_style_content_coerced():
353
"""Assistant message whose content is output-message-shaped (list of
356
- output_text items) should be coerced to ResponseOutputMessage.
357
- """
354
+ output_text items) should be coerced to ResponseOutputMessage."""
355
request_data = {
356
"model": "test-model",
357
"input": [
tests/entrypoints/openai/responses/test_response_input_to_harmony.py
+4
-8
@@ -67,8 +67,7 @@ class TestResponseInputToHarmonyMessage:
67
68
def test_system_message(self):
69
"""System messages carry developer instructions and must be rendered
70
- as developer messages with DeveloperContent.
71
- """
70
+ as developer messages with DeveloperContent."""
71
msg = response_input_to_harmony(
72
{"type": "message", "role": "system", "content": "Be helpful."},
73
prev_responses=[],
@@ -90,8 +89,7 @@ class TestResponseInputToHarmonyMessage:
89
90
def test_developer_message_gets_instructions_prefix(self):
91
"""Developer messages must use DeveloperContent which adds the
93
- '# Instructions' header the model was trained on.
94
- """
92
+ '# Instructions' header the model was trained on."""
93
msg = response_input_to_harmony(
94
{"type": "message", "role": "developer", "content": "Be concise."},
95
prev_responses=[],
@@ -121,8 +119,7 @@ class TestResponseInputToHarmonyMessage:
119
120
def test_developer_message_array_content_concatenated(self):
121
"""Array content in developer messages is flattened and rendered
124
- via DeveloperContent with the '# Instructions' header.
125
- """
122
+ via DeveloperContent with the '# Instructions' header."""
123
msg = response_input_to_harmony(
124
{
125
"type": "message",
@@ -213,8 +210,7 @@ class TestResponseInputToHarmonyMessage:
210
211
def test_function_call_output_uses_most_recent_matching_call(self):
212
"""When multiple prev_responses share a call_id, the last one wins
216
- because the search is reversed.
217
- """
213
+ because the search is reversed."""
214
earlier = ResponseFunctionToolCall(
215
id="fc_old",
216
call_id="call_test",
tests/entrypoints/openai/responses/test_responses_utils.py
+3
-6
@@ -839,13 +839,11 @@ class TestConstructChatMessagesCombinePolicy:
839
840
class TestConstructInputMessagesInstructionsLeak:
841
"""Regression tests for #37697: instructions from a prior response
842
- should NOT leak through previous_response_id.
843
- """
842
+ should NOT leak through previous_response_id."""
843
844
def test_old_instructions_stripped_from_prev_msg(self):
845
"""System message in prev_msg must be dropped so the new request's
847
- instructions are the only system message in the conversation.
848
- """
846
+ instructions are the only system message in the conversation."""
847
prev = [
848
{"role": "system", "content": "old instructions"},
849
{"role": "user", "content": "What is 2+2?"},
@@ -862,8 +860,7 @@ class TestConstructInputMessagesInstructionsLeak:
860
861
def test_no_instructions_in_new_request(self):
862
"""If the new request has no instructions, old ones should still
865
- be stripped -- they must not carry over.
866
- """
863
+ be stripped -- they must not carry over."""
864
prev = [
865
{"role": "system", "content": "old instructions"},
866
{"role": "user", "content": "Hi"},
tests/entrypoints/openai/responses/test_serving_responses.py
+6
-12
@@ -1163,8 +1163,7 @@ class TestHarmonyPreambleStreaming:
1163
1164
def test_preamble_done_emits_text_done_events(self) -> None:
1165
"""Completed preamble should emit text done + content_part done +
1166
- output_item done, same shape as final channel.
1167
- """
1166
+ output_item done, same shape as final channel."""
1167
from vllm.entrypoints.openai.responses.streaming_events import (
1168
emit_previous_item_done_events,
1169
)
@@ -1185,8 +1184,7 @@ class TestHarmonyPreambleStreaming:
1184
1185
def test_commentary_with_recipient_no_preamble_done(self) -> None:
1186
"""Commentary + recipient='functions.X' should route to function call
1188
- done, not preamble done.
1189
- """
1187
+ done, not preamble done."""
1188
from vllm.entrypoints.openai.responses.streaming_events import (
1189
emit_previous_item_done_events,
1190
)
@@ -1332,8 +1330,7 @@ def _mock_parser_with_reasoning(serving, delta_sequence: list[DeltaMessage]):
1330
class TestStreamingReasoningToContentTransition:
1331
"""Tests for _process_simple_streaming_events reasoning-to-content
1332
transition, specifically the fix for mixed deltas that carry both
1335
- reasoning and content simultaneously.
1336
- """
1333
+ reasoning and content simultaneously."""
1334
1335
@pytest.mark.asyncio
1336
async def test_mixed_delta_reasoning_and_content_emits_reasoning_delta(
@@ -1343,8 +1340,7 @@ class TestStreamingReasoningToContentTransition:
1340
and content set (e.g. reasoning end and content start in the same
1341
chunk), the trailing reasoning text must be emitted as a
1342
ResponseReasoningTextDeltaEvent and included in the
1346
- ResponseReasoningTextDoneEvent text.
1347
- """
1343
+ ResponseReasoningTextDoneEvent text."""
1344
monkeypatch.setattr(envs, "VLLM_USE_EXPERIMENTAL_PARSER_CONTEXT", False)
1345
serving = _make_serving_instance_with_reasoning()
1346
@@ -1413,8 +1409,7 @@ class TestStreamingReasoningToContentTransition:
1409
self, monkeypatch
1410
):
1411
"""When the transition from reasoning to content is clean (no mixed
1416
- delta), no extra reasoning delta event should be emitted.
1417
- """
1412
+ delta), no extra reasoning delta event should be emitted."""
1413
monkeypatch.setattr(envs, "VLLM_USE_EXPERIMENTAL_PARSER_CONTEXT", False)
1414
serving = _make_serving_instance_with_reasoning()
1415
@@ -1475,8 +1470,7 @@ class TestStreamingReasoningToContentTransition:
1470
async def test_reasoning_only_stream_no_content(self, monkeypatch):
1471
"""When the stream has only reasoning deltas and no content, the
1472
reasoning done event should be emitted at finalization with the
1478
- full accumulated text, and no text delta events should appear.
1479
- """
1473
+ full accumulated text, and no text delta events should appear."""
1474
monkeypatch.setattr(envs, "VLLM_USE_EXPERIMENTAL_PARSER_CONTEXT", False)
1475
serving = _make_serving_instance_with_reasoning()
1476
tests/entrypoints/openai/responses/test_simple.py
+1
-2
@@ -143,8 +143,7 @@ async def test_streaming_output_consistency(client: OpenAI, model_name: str):
143
@pytest.mark.parametrize("model_name", [MODEL_NAME])
144
async def test_streaming_logprobs(client: OpenAI, model_name: str):
145
"""Test that streaming with logprobs returns valid logprob data on
146
- output_text.delta events and that top_logprobs has the requested count.
147
- """
146
+ output_text.delta events and that top_logprobs has the requested count."""
147
response = await client.responses.create(
148
model=model_name,
149
input="Say hello.",
tests/entrypoints/openai/responses/test_streaming_events.py
+2
-4
@@ -124,8 +124,7 @@ class TestProcessorCompoundDeltas:
124
125
def test_split_name_and_args_same_index(self):
126
"""Regression: parsers like KimiK2 emit name and args as separate
127
- DeltaToolCalls at the same index within one DeltaMessage.
128
- """
127
+ DeltaToolCalls at the same index within one DeltaMessage."""
128
tc_name = _make_tool_call(0, name="get_weather")
129
tc_args = _make_tool_call(0, arguments='{"city":"SF"}')
130
delta = DeltaMessage(tool_calls=[tc_name, tc_args])
@@ -141,8 +140,7 @@ class TestProcessorCompoundDeltas:
140
141
def test_reasoning_to_content_transition(self):
142
"""Regression: the old special case in emit_delta handled this;
144
- now split_delta handles it generically.
145
- """
143
+ now split_delta handles it generically."""
144
processor = SimpleStreamingEventProcessor()
145
_run_through_processor(processor, DeltaMessage(reasoning="think"))
146
assert processor.state.current_state == _StateType.REASONING
tests/entrypoints/openai/test_render_token_offsets.py
+3
-6
@@ -25,8 +25,7 @@ def _model_config() -> Mock:
25
def test_completion_flag_forwarded_to_tok_params():
26
"""build_tok_params must forward return_token_offsets, defaulting to
27
False (zero behavioral change for existing callers) and coercing JSON
28
- null to False via the bool() guard.
29
- """
28
+ null to False via the bool() guard."""
29
cfg = _model_config()
30
31
default = CompletionRequest(model="m", prompt="hi")
@@ -41,8 +40,7 @@ def test_completion_flag_forwarded_to_tok_params():
40
41
def test_chat_flag_forwarded_to_tok_params():
42
"""Chat build_tok_params has its own (max_completion_tokens) branch, so
44
- its return_token_offsets forwarding is verified independently.
45
- """
43
+ its return_token_offsets forwarding is verified independently."""
44
cfg = _model_config()
45
messages = [{"role": "user", "content": "hi"}]
46
@@ -66,8 +64,7 @@ def test_generate_request_token_offsets_default_none():
64
65
def test_generate_request_token_offsets_survive_json_round_trip():
66
"""GenerateRequest crosses the disagg serialization boundary; the
69
- tuple[int, int] offsets must survive model_dump and re-validate.
70
- """
67
+ tuple[int, int] offsets must survive model_dump and re-validate."""
68
req = GenerateRequest(
69
token_ids=[10, 20],
70
sampling_params=SamplingParams(),
tests/entrypoints/pooling/embed/test_cohere_online.py
+2
-4
@@ -111,8 +111,7 @@ def test_basic_embed(server: RemoteOpenAIServer, model_name: str):
111
112
def test_unsupported_input_type_rejected(server: RemoteOpenAIServer, model_name: str):
113
"""An input_type not defined in the model's prompt config should be
114
- rejected with a 400 error.
115
- """
114
+ rejected with a 400 error."""
115
body = {
116
"model": model_name,
117
"input_type": "nonexistent_type",
@@ -139,8 +138,7 @@ def test_omitted_input_type_accepted(server: RemoteOpenAIServer, model_name: str
138
139
def test_v1_v2_parity(server: RemoteOpenAIServer, model_name: str):
140
"""v1 (OpenAI) and v2 (Cohere) endpoints should produce the same
142
- float embeddings for a generic model.
143
- """
141
+ float embeddings for a generic model."""
142
texts = ["hello world"]
143
v2 = _cohere_embed(server, model_name, texts=texts, embedding_types=["float"])
144
v1 = _openai_embed(server, model_name, texts)
tests/entrypoints/pooling/embed/test_cohere_openai_parity.py
+1
-2
@@ -76,8 +76,7 @@ def test_single_text_parity(server: RemoteOpenAIServer):
76
77
def test_batch_parity(server: RemoteOpenAIServer):
78
"""A batch of texts should produce equivalent embeddings via both APIs,
79
- in the same order.
80
- """
79
+ in the same order."""
80
texts = [
81
"machine learning",
82
"deep learning",
tests/entrypoints/pooling/embed/test_io_processor.py
+1
-2
@@ -241,8 +241,7 @@ class TestResolveTruncation:
241
242
def test_truncate_none_with_max_tokens(self):
243
"""truncate=NONE should NOT set truncate_prompt_tokens; the
244
- max_tokens limit is enforced separately via _check_max_tokens.
245
- """
244
+ max_tokens limit is enforced separately via _check_max_tokens."""
245
req = self._make_request(truncate="NONE", max_tokens=10)
246
tokens, side = EmbedIOProcessor._resolve_cohere_truncation(req)
247
assert tokens is None
tests/entrypoints/pooling/embed/test_online_long_text.py
+3
-6
@@ -240,8 +240,7 @@ async def test_long_text_embedding_1500_chars(
240
client_with_chunked_processing: openai.AsyncOpenAI, model_name: str
241
):
242
"""Test embedding processing for ~1500 character long text
243
- (~1028 tokens, exceeding 512 token limit).
244
- """
243
+ (~1028 tokens, exceeding 512 token limit)."""
244
# Verify text length
245
# Verify text has sufficient word count (approximately 1500 words)
246
word_count = len(LONG_TEXT_1500_WORDS.split())
@@ -289,8 +288,7 @@ async def test_long_text_embedding_2500_chars(
288
client_with_chunked_processing: openai.AsyncOpenAI, model_name: str
289
):
290
"""Test embedding processing for ~2500 character long text
292
- (~2048 tokens, requiring multiple chunks).
293
- """
291
+ (~2048 tokens, requiring multiple chunks)."""
292
# Verify text length
293
# Verify text has sufficient word count (approximately 2500 words)
294
word_count = len(LONG_TEXT_2500_WORDS.split())
@@ -382,8 +380,7 @@ async def test_chunked_vs_normal_consistency(
380
client_with_chunked_processing: openai.AsyncOpenAI, model_name: str
381
):
382
"""Test consistency between chunked and
385
- normal processing (using short text).
386
- """
383
+ normal processing (using short text)."""
384
# Use a short text within the 512 token limit
385
short_text = (
386
"Artificial intelligence technology is changing our world, "
tests/entrypoints/pooling/embed/test_protocol.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Unit tests for Cohere embed protocol: build_typed_embeddings and its
4
-underlying packing helpers, plus Cohere-specific serving helpers.
5
-"""
4
+underlying packing helpers, plus Cohere-specific serving helpers."""
5
6
import struct
7
tests/entrypoints/scale_out/derender/test_derender.py
+1
-2
@@ -454,8 +454,7 @@ async def test_derender_completion_empty_generate_responses(client):
454
@pytest.mark.asyncio
455
async def test_derender_completion_logprobs(client):
456
"""token_id:N placeholders in logprobs are resolved; CompletionLogProbs
457
- flat-list structure is returned with non-empty tokens and text_offsets.
458
- """
457
+ flat-list structure is returned with non-empty tokens and text_offsets."""
458
gr1 = await _render_completion(client, "Hello world")
459
ids1 = gr1["token_ids"][:3]
460
token_id = ids1[0]
tests/entrypoints/scale_out/derender/test_derender_parity.py
+3
-6
@@ -121,8 +121,7 @@ async def _disagg(
121
122
def _tool_sig(response_choice: dict) -> list[tuple[str, dict]]:
123
"""[(name, json normalized args)] so key ordering / whitespace don't
124
- cause false negatives.
125
- """
124
+ cause false negatives."""
125
return [
126
(tc["function"]["name"], json.loads(tc["function"]["arguments"]))
127
for tc in (response_choice["message"].get("tool_calls") or [])
@@ -144,8 +143,7 @@ async def _run_parity_case(
143
client: httpx.AsyncClient, messages: list[dict], **extra
144
) -> tuple[dict, dict]:
145
"""Run the coupled request then feed its generated tokens into the
147
- disaggregated derender endpoint. Returns (coupled, disagg).
148
- """
146
+ disaggregated derender endpoint. Returns (coupled, disagg)."""
147
coupled = await _coupled(client, messages, **extra)
148
ch = coupled["choices"][0]
149
chat_request = {"model": MODEL, "messages": messages, **extra}
@@ -205,8 +203,7 @@ async def test_parity_tool_call(client):
203
@pytest.mark.asyncio
204
async def test_parity_reasoning_and_tool_call(client):
205
"""Combined reasoning + tool call parity means the highest drift risk
208
- since it exercises both parser branches on the same output.
209
- """
206
+ since it exercises both parser branches on the same output."""
207
messages = [{"role": "user", "content": "What's the weather in Paris?"}]
208
coupled, disagg = await _run_parity_case(
209
client,
tests/entrypoints/scale_out/render/test_render.py
+4
-8
@@ -455,8 +455,7 @@ async def test_chat_completion_render_with_sampling_params(client):
455
@pytest.mark.asyncio
456
async def test_completion_render_emits_token_offsets(client):
457
"""With return_token_offsets, /v1/completions/render returns per-token
458
- (start, end) char offsets aligned with token_ids.
459
- """
458
+ (start, end) char offsets aligned with token_ids."""
459
prompt = "Hello, world."
460
response = await client.post(
461
"/v1/completions/render",
@@ -481,8 +480,7 @@ async def test_completion_render_emits_token_offsets(client):
480
@pytest.mark.asyncio
481
async def test_completion_render_default_no_token_offsets(client):
482
"""Without the flag, token_offsets must be null (existing responses
484
- unchanged).
485
- """
483
+ unchanged)."""
484
response = await client.post(
485
"/v1/completions/render",
486
json={
@@ -499,8 +497,7 @@ async def test_completion_render_default_no_token_offsets(client):
497
@pytest.mark.asyncio
498
async def test_chat_render_emits_token_offsets(client):
499
"""With return_token_offsets, /v1/chat/completions/render returns
502
- per-token offsets relative to the templated prompt string.
503
- """
500
+ per-token offsets relative to the templated prompt string."""
501
response = await client.post(
502
"/v1/chat/completions/render",
503
json={
@@ -674,8 +671,7 @@ async def test_chat_completion_render_assistant_tokens_mask_with_generation_tags
671
client,
672
):
673
"""With a ``{% generation %}``-enabled template, the mask marks assistant
677
- tokens and the masked tokens decode to the assistant content.
678
- """
674
+ tokens and the masked tokens decode to the assistant content."""
675
response = await client.post(
676
"/v1/chat/completions/render",
677
json={
tests/entrypoints/scale_out/token_in_token_out/test_protocol.py
+3
-6
@@ -25,8 +25,7 @@ def _base_payload() -> dict:
25
26
def test_omitted_max_tokens_is_not_provided():
27
"""Body without ``max_tokens`` must surface as 'not provided' so the
28
- server can apply its own default instead of the dataclass 16.
29
- """
28
+ server can apply its own default instead of the dataclass 16."""
29
req = GenerateRequest.model_validate(_base_payload())
30
# SamplingParams' dataclass default leaks through the parsed instance —
31
# this is exactly the bug the server-side defaulting works around.
@@ -36,8 +35,7 @@ def test_omitted_max_tokens_is_not_provided():
35
36
def test_explicit_max_tokens_is_provided():
37
"""Even when the client picks the same value as the dataclass default,
39
- it must register as explicitly set so the server won't override it.
40
- """
38
+ it must register as explicitly set so the server won't override it."""
39
payload = _base_payload()
40
payload["sampling_params"] = {"max_tokens": 16}
41
req = GenerateRequest.model_validate(payload)
@@ -69,8 +67,7 @@ def test_json_roundtrip_preserves_provided_keys():
67
def test_internal_instance_construction_treats_all_as_provided():
68
"""When internal callers build ``GenerateRequest`` from a pre-resolved
69
``SamplingParams`` instance, every field is considered explicitly set
72
- so server-side defaulting can't clobber values resolved upstream.
73
- """
70
+ so server-side defaulting can't clobber values resolved upstream."""
71
sp = SamplingParams(max_tokens=500, temperature=0.0)
72
req = GenerateRequest(token_ids=[1, 2, 3], sampling_params=sp)
73
assert req.is_sampling_param_provided("max_tokens")
tests/entrypoints/serve/exception_handling/test_error_sanitization.py
+2
-4
@@ -22,8 +22,7 @@ def test_sanitize_message():
22
23
class TestSanitizeMessageFilePaths:
24
"""sanitize_message should also strip file paths and traceback
25
- frames, not just memory addresses - see #31683.
26
- """
25
+ frames, not just memory addresses - see #31683."""
26
27
def test_strips_traceback_style_frame(self):
28
msg = (
@@ -45,8 +44,7 @@ class TestSanitizeMessageFilePaths:
44
45
def test_strips_single_parent_container_path(self):
46
"""Regression: /app/server.py and /workspace/server.py (common in
48
- container deployments) were missed by the original {2,} quantifier.
49
- """
47
+ container deployments) were missed by the original {2,} quantifier."""
48
assert "/app/" not in sanitize_message("Error in /app/server.py")
49
assert "/workspace/" not in sanitize_message("Error in /workspace/server.py")
50
tests/entrypoints/serve/exception_handling/test_validation_exception_handler.py
+5
-10
@@ -24,8 +24,7 @@ from vllm.entrypoints.serve.exception_handling.handlers.validation import (
24
25
def _fake_request(log_error_stack: bool = False) -> SimpleNamespace:
26
"""Minimal stand-in for a FastAPI Request - just enough for the
27
- handler to read req.app.state.args.log_error_stack.
28
- """
27
+ handler to read req.app.state.args.log_error_stack."""
28
return SimpleNamespace(
29
app=SimpleNamespace(
30
state=SimpleNamespace(args=SimpleNamespace(log_error_stack=log_error_stack))
@@ -36,8 +35,7 @@ def _fake_request(log_error_stack: bool = False) -> SimpleNamespace:
35
36
class TestValidationErrorParamFallback:
37
"""Ensure `param` falls back to the Pydantic error's `loc` when no
39
- custom VLLMValidationError context is present.
40
- """
38
+ custom VLLMValidationError context is present."""
39
40
@pytest.mark.parametrize(
41
("error_type", "msg"),
@@ -61,8 +59,7 @@ class TestValidationErrorParamFallback:
59
async def test_param_fallback_does_not_crash_on_non_dict_error(self):
60
"""Schemathesis fuzzing found that errors[0] isn't always a dict.
61
The fallback must not crash in that case - it should just leave
64
- param as None instead of raising.
65
- """
62
+ param as None instead of raising."""
63
exc = RequestValidationError(["some unexpected non-dict error"])
64
65
response = await validation_exception_handler(_fake_request(), exc)
@@ -100,8 +97,7 @@ class TestCleanLocForParam:
97
98
def test_all_internal_falls_back_to_raw_join(self):
99
"""If every loc segment looks internal, fall back to the raw
103
- dot-join rather than returning an empty string.
104
- """
100
+ dot-join rather than returning an empty string."""
101
loc = ("function-wrap[__log_extra_fields__()]",)
102
assert clean_loc_for_param(loc) == "function-wrap[__log_extra_fields__()]"
103
@@ -109,8 +105,7 @@ class TestCleanLocForParam:
105
class TestValidationErrorDoesNotLeakServerPaths:
106
"""FastAPI sets endpoint_file/line/function/path on the exception
107
during routing, not in the constructor - so we set them manually
112
- here to reproduce the real leak. See #31683.
113
- """
108
+ here to reproduce the real leak. See #31683."""
109
110
@pytest.mark.asyncio
111
async def test_handler_strips_endpoint_file_context(self):
tests/entrypoints/serve/lora/test_lora_adapters.py
+1
-2
@@ -245,8 +245,7 @@ async def test_multiple_lora_adapters(
245
client: openai.AsyncOpenAI, tmp_path, qwen3_lora_files
246
):
247
"""Validate that many loras can be dynamically registered and inferenced
248
- with concurrently
249
- """
248
+ with concurrently"""
249
250
# This test file configures the server with --max-cpu-loras=2 and this test
251
# will concurrently load 10 adapters, so it should flex the LRU cache
tests/entrypoints/serve/middleware/test_authentication_middleware.py
+3
-6
@@ -72,8 +72,7 @@ class MockModelConfig:
72
@pytest.fixture(params=get_args(SupportedTask))
73
def task_routes(request, monkeypatch) -> tuple[str, list[tuple[str, list[str]]]]:
74
"""For each supported task, build an app with only that task's routers,
75
- extract all routes, and return the task name and routes.
76
- """
75
+ extract all routes, and return the task name and routes."""
76
task = request.param
77
# Enable development mode to register all routes (including dev-only routes).
78
monkeypatch.setenv("VLLM_SERVER_DEV_MODE", "1")
@@ -99,8 +98,7 @@ def task_routes(request, monkeypatch) -> tuple[str, list[tuple[str, list[str]]]]
98
99
def test_auto_discovered_protected_routes_require_auth(task_routes):
100
"""For every auto-discovered route that starts with a guarded prefix,
102
- verify that authentication is enforced.
103
- """
101
+ verify that authentication is enforced."""
102
task, routes = task_routes
103
app = _create_app_with_mock_routes(routes)
104
client = TestClient(app)
@@ -134,8 +132,7 @@ def test_auto_discovered_protected_routes_require_auth(task_routes):
132
133
def test_auto_discovered_unprotected_routes_no_auth(task_routes):
134
"""For every auto-discovered route that does NOT start with a guarded
137
- prefix, verify that no authentication is required.
138
- """
135
+ prefix, verify that no authentication is required."""
136
task, routes = task_routes
137
app = _create_app_with_mock_routes(routes)
138
client = TestClient(app)
tests/entrypoints/serve/sagemaker/test_sagemaker_handler_overrides.py
+6
-12
@@ -114,8 +114,7 @@ class TestHandlerOverrideIntegration:
114
115
def test_customer_script_functions_auto_loaded(self, monkeypatch, tmp_path):
116
"""Test customer scenario: script functions automatically override
117
- framework defaults.
118
- """
117
+ framework defaults."""
118
try:
119
from model_hosting_container_standards.sagemaker.config import (
120
SageMakerEnvVars,
@@ -176,8 +175,7 @@ async def custom_sagemaker_invocation_handler(request: Request):
175
176
def test_customer_decorator_usage(self, monkeypatch, tmp_path):
177
"""Test customer scenario: using @custom_ping_handler and
179
- @custom_invocation_handler decorators.
180
- """
178
+ @custom_invocation_handler decorators."""
179
try:
180
from model_hosting_container_standards.sagemaker.config import (
181
SageMakerEnvVars,
@@ -233,8 +231,7 @@ async def my_invoke(request: Request):
231
232
def test_handler_priority_order(self, monkeypatch, tmp_path):
233
"""Test priority: @custom_ping_handler/@custom_invocation_handler
236
- decorators vs script functions.
237
- """
234
+ decorators vs script functions."""
235
try:
236
from model_hosting_container_standards.sagemaker.config import (
237
SageMakerEnvVars,
@@ -307,8 +304,7 @@ async def custom_sagemaker_invocation_handler(request: Request):
304
305
def test_environment_variable_script_loading(self, monkeypatch, tmp_path):
306
"""Test that environment variables correctly specify script location
310
- and loading.
311
- """
307
+ and loading."""
308
try:
309
from model_hosting_container_standards.sagemaker.config import (
310
SageMakerEnvVars,
@@ -420,8 +416,7 @@ async def custom_sagemaker_invocation_handler(request: Request):
416
417
def test_handler_env_var_override(self, monkeypatch, tmp_path):
418
"""Test CUSTOM_FASTAPI_PING_HANDLER and CUSTOM_FASTAPI_INVOCATION_HANDLER
423
- environment variable overrides.
424
- """
419
+ environment variable overrides."""
420
try:
421
from model_hosting_container_standards.common.fastapi.config import (
422
FastAPIEnvVars,
@@ -515,8 +510,7 @@ async def custom_sagemaker_invocation_handler(request: Request):
510
511
def test_env_var_priority_over_decorator_and_script(self, monkeypatch, tmp_path):
512
"""Test that environment variables have highest priority over decorators
518
- and script functions for both ping and invocation handlers.
519
- """
513
+ and script functions for both ping and invocation handlers."""
514
try:
515
from model_hosting_container_standards.common.fastapi.config import (
516
FastAPIEnvVars,
tests/entrypoints/serve/tokenize/test_tokenize_then_chat_vlm.py
+1
-2
@@ -51,8 +51,7 @@ async def test_tokenize_then_chat_completion_with_image(
51
local_asset_server,
52
):
53
"""Tokenize a multimodal message, then send the same message to chat
54
- completions. The chat completion must succeed (not 500).
55
- """
54
+ completions. The chat completion must succeed (not 500)."""
55
image_url = local_asset_server.url_for("stop_sign.jpg")
56
messages = [
57
{
tests/entrypoints/serve/utils/test_api_utils.py
+4
-8
@@ -36,13 +36,11 @@ def test_should_include_usage_force_enables_continuous_usage(stream_options, exp
36
class TestGetMaxTokens:
37
"""Tests for get_max_tokens() to ensure generation_config's max_tokens
38
acts as a default when from model author, and as a ceiling when
39
- explicitly set by the user.
40
- """
39
+ explicitly set by the user."""
40
41
def test_default_sampling_params_used_when_no_request_max_tokens(self):
42
"""When user doesn't specify max_tokens, generation_config default
44
- should apply.
45
- """
43
+ should apply."""
44
result = get_max_tokens(
45
max_model_len=24000,
46
max_tokens=None,
@@ -53,8 +51,7 @@ class TestGetMaxTokens:
51
52
def test_request_max_tokens_not_capped_by_default_sampling_params(self):
53
"""When user specifies max_tokens in request, model author's
56
- generation_config max_tokens must NOT cap it (fixes #34005).
57
- """
54
+ generation_config max_tokens must NOT cap it (fixes #34005)."""
55
result = get_max_tokens(
56
max_model_len=24000,
57
max_tokens=5000,
@@ -97,8 +94,7 @@ class TestGetMaxTokens:
94
95
def test_request_max_tokens_smaller_than_default(self):
96
"""When user explicitly requests fewer tokens than gen_config default,
100
- that should be respected.
101
- """
97
+ that should be respected."""
98
result = get_max_tokens(
99
max_model_len=24000,
100
max_tokens=512,
tests/entrypoints/serve/utils/test_request_logger.py
+1
-2
@@ -239,8 +239,7 @@ def test_request_logger_log_outputs_integration():
239
240
def test_streaming_complete_logs_full_text_content():
241
"""Test that streaming complete logging includes
242
- full accumulated text, not just token count.
243
- """
242
+ full accumulated text, not just token count."""
243
mock_logger = MagicMock()
244
245
with patch("vllm.entrypoints.serve.utils.request_logger.logger", mock_logger):
tests/entrypoints/serve/utils/test_sse_keep_alive.py
+8
-16
@@ -17,8 +17,7 @@ from vllm.entrypoints.serve.utils.sse_keep_alive import (
17
def test_disabled_returns_same_generator():
18
"""For 0, negative, and NaN intervals the exact same generator object must
19
be returned (identity), proving no wrapper or per-chunk overhead when
20
- disabled.
21
- """
20
+ disabled."""
21
22
async def gen():
23
yield "x"
@@ -34,8 +33,7 @@ def test_disabled_returns_same_generator():
33
@pytest.mark.asyncio
34
async def test_keep_alive_during_silent_start():
35
"""A silent start (queue wait / prefill) emits keep-alive comments before
37
- the first real chunk.
38
- """
36
+ the first real chunk."""
37
release = asyncio.Event()
38
39
async def gen():
@@ -57,8 +55,7 @@ async def test_keep_alive_during_silent_start():
55
@pytest.mark.asyncio
56
async def test_no_keep_alive_when_streaming_is_fast():
57
"""If chunks arrive faster than the interval, no comment is emitted and all
60
- data is forwarded.
61
- """
58
+ data is forwarded."""
59
60
async def gen():
61
for chunk in ["a", "b", "c"]:
@@ -72,8 +69,7 @@ async def test_no_keep_alive_when_streaming_is_fast():
69
@pytest.mark.asyncio
70
async def test_keep_alive_between_chunks_does_not_drop_data():
71
"""Keep-alives interleaved with real chunks must never drop or reorder
75
- data.
76
- """
72
+ data."""
73
release_b = asyncio.Event()
74
release_c = asyncio.Event()
75
@@ -139,8 +135,7 @@ async def test_upstream_cancelled_error_propagates():
135
@pytest.mark.asyncio
136
async def test_aclose_closes_upstream():
137
"""Closing a wrapper that is mid-stream must complete promptly and close
142
- the upstream generator (regression for the earlier leaked-task hang).
143
- """
138
+ the upstream generator (regression for the earlier leaked-task hang)."""
139
finalized = asyncio.Event()
140
141
async def gen():
@@ -159,8 +154,7 @@ async def test_aclose_closes_upstream():
154
@pytest.mark.asyncio
155
async def test_client_disconnect_cancels_upstream():
156
"""Cancelling the consumer mid-stream must cancel the pending anext and
162
- close the upstream generator so its cleanup runs.
163
- """
157
+ close the upstream generator so its cleanup runs."""
158
finalized = asyncio.Event()
159
160
async def gen():
@@ -187,8 +181,7 @@ async def test_client_disconnect_cancels_upstream():
181
@pytest.mark.asyncio
182
async def test_streaming_response_emits_comment():
183
"""A keep-alive comment must reach the client through the real
190
- StreamingResponse used by the routers.
191
- """
184
+ StreamingResponse used by the routers."""
185
release = asyncio.Event()
186
187
async def gen():
@@ -227,8 +220,7 @@ async def test_streaming_response_emits_comment():
220
async def test_streaming_response_disconnect_closes_upstream():
221
"""On the ASGI 2.3 disconnect path used by the pinned Uvicorn, Starlette
222
cancels streaming and the wrapper's finally must close the upstream
230
- generator.
231
- """
223
+ generator."""
224
finalized = asyncio.Event()
225
226
async def gen():
tests/entrypoints/speech_to_text/realtime/test_realtime_validation.py
+1
-2
@@ -295,8 +295,7 @@ async def test_session_update_invalid_model_returns_error(model_name):
295
@pytest.mark.parametrize("model_name", [MODEL_NAME])
296
async def test_commit_without_session_update_returns_error(model_name):
297
"""Test that committing before validating the model returns an error
298
- and does not fall through to processing.
299
- """
298
+ and does not fall through to processing."""
299
server_args = ["--enforce-eager", "--max-model-len", "2048"]
300
301
if model_name.startswith("mistralai"):
tests/entrypoints/unit_tests/test_context.py
+7
-14
@@ -51,8 +51,7 @@ async def generate_mock_outputs(
51
num_turns, prompt_token_counts, output_token_counts, cached_token_counts=None
52
):
53
"""Generate a sequence of mock RequestOutput objects to simulate multiple
54
- turns.
55
- """
54
+ turns."""
55
if cached_token_counts is None:
56
cached_token_counts = [0] * num_turns
57
@@ -271,8 +270,7 @@ def test_reasoning_tokens_counting():
270
271
def test_preamble_tokens_not_counted_as_reasoning():
272
"""Preambles (commentary with no recipient) are visible user text,
274
- not hidden reasoning. They must NOT inflate num_reasoning_tokens.
275
- """
273
+ not hidden reasoning. They must NOT inflate num_reasoning_tokens."""
274
context, parser = make_harmony_context()
275
parser.enqueue_chunk_result(reasoning_token_count=0)
276
@@ -289,8 +287,7 @@ def test_preamble_tokens_not_counted_as_reasoning():
287
288
def test_commentary_with_recipient_counted_as_reasoning():
289
"""Commentary directed at a tool (recipient != None) is hidden from
292
- the user, so it should still count as reasoning tokens.
293
- """
290
+ the user, so it should still count as reasoning tokens."""
291
context, parser = make_harmony_context()
292
parser.enqueue_chunk_result(reasoning_token_count=3)
293
@@ -349,8 +346,7 @@ async def test_single_turn_no_tool_output():
346
@pytest.mark.asyncio
347
async def test_negative_tool_tokens_edge_case():
348
"""Test edge case where calculation could result in negative tool
352
- tokens. We should log an error and clamp the value to 0.
353
- """
349
+ tokens. We should log an error and clamp the value to 0."""
350
# Use patch to check if logger.error was called
351
with patch("vllm.entrypoints.openai.responses.context.logger.error") as mock_log:
352
context, _ = make_harmony_context(available_tools=["browser"])
@@ -690,8 +686,7 @@ def create_simple_context_output(
686
finished=True,
687
):
688
"""Helper to create a RequestOutput with customizable text for
693
- SimpleContext tests.
694
- """
689
+ SimpleContext tests."""
690
if token_ids is None:
691
token_ids = []
692
return RequestOutput(
@@ -875,8 +870,7 @@ def test_simple_context_final_output():
870
871
def test_simple_context_output_messages_empty_text_with_tokens():
872
"""output_messages should be returned when tokens exist even if text is
878
- empty (e.g. special tokens).
879
- """
873
+ empty (e.g. special tokens)."""
874
context = SimpleContext()
875
context.append_output(
876
create_simple_context_output(
@@ -894,8 +888,7 @@ def test_simple_context_output_messages_empty_text_with_tokens():
888
889
def test_simple_context_output_messages_no_mutation():
890
"""Each call to output_messages returns a fresh list; callers can't
897
- corrupt internal state.
898
- """
891
+ corrupt internal state."""
892
context = SimpleContext()
893
context.append_output(
894
create_simple_context_output(
tests/entrypoints/weight_transfer/test_weight_transfer_llm.py
+1
-2
@@ -121,8 +121,7 @@ def test_get_world_size_tp1(vllm_runner):
121
@create_new_process_for_each_test()
122
def test_init_weight_transfer_engine_calls_engine(vllm_runner):
123
"""Test that init_weight_transfer_engine calls the engine's
124
- init_transfer_engine method.
125
- """
124
+ init_transfer_engine method."""
125
if torch.accelerator.device_count() < 1:
126
pytest.skip("Need at least 1 GPU for this test")
127
tests/fusion/test_quant_activation_contract.py
+1
-2
@@ -86,8 +86,7 @@ def _all_kernel_classes() -> list[type]:
86
87
def _probe(cls: type):
88
"""A bare kernel instance with a plausible config, so input_quant_key()
89
- can be queried without the hardware-gated constructor.
90
- """
89
+ can be queried without the hardware-gated constructor."""
90
obj = cls.__new__(cls) # type: ignore[call-overload]
91
if issubclass(cls, NvFp4LinearKernel):
92
obj.config = NvFp4LinearLayerConfig()
tests/kernels/attention/test_amx_mla.py
+3
-6
@@ -247,8 +247,7 @@ def test_extend_attention_cpu_matches_reference(prefix_lens, extend_lens):
247
248
class _FakeLinear:
249
"""Minimal duck-typed stand-in for kv_b_proj: only .weight and
250
- .quant_method are read by get_and_maybe_dequant_weights().
251
- """
250
+ .quant_method are read by get_and_maybe_dequant_weights()."""
251
252
def __init__(self, weight: torch.Tensor):
253
self.weight = weight
@@ -319,8 +318,7 @@ class _FakeAttnMetadata:
318
def test_amx_mla_impl_forward_mqa_matches_reference(default_vllm_config):
319
"""forward_mqa receives already-absorbed Q (as MLAAttention.forward_impl
320
would produce via layer.W_UK_T) and must reproduce plain per-head MLA
322
- decode attention through W_UK/W_UV.
323
- """
321
+ decode attention through W_UK/W_UV."""
322
set_random_seed(1)
323
num_heads, qk_nope_head_dim, v_head_dim, kv_lora_rank = 4, 32, 32, 64
324
impl, kv_b_weight = _make_amx_mla_impl(
@@ -386,8 +384,7 @@ def test_amx_mla_impl_forward_mqa_matches_reference(default_vllm_config):
384
def test_amx_mla_impl_forward_mha_matches_reference(default_vllm_config):
385
"""forward_mha receives raw unabsorbed Q and must attend correctly for a
386
prefill batch with a mix of fresh and continued (cached-prefix)
389
- sequences.
390
- """
387
+ sequences."""
388
set_random_seed(2)
389
num_heads, qk_nope_head_dim, v_head_dim, kv_lora_rank = 4, 32, 32, 64
390
impl, kv_b_weight = _make_amx_mla_impl(
tests/kernels/attention/test_attention_selector.py
+2
-4
@@ -616,8 +616,7 @@ def test_non_causal_autoselect_backend():
616
)
617
def test_flash_attn_rejects_unhandled_kv_cache_dtypes(kv_cache_dtype: str):
618
"""FlashAttentionBackend must not claim support for kv_cache dtypes
619
- that it cannot handle.
620
- """
619
+ that it cannot handle."""
620
from vllm.v1.attention.backends.flash_attn import FlashAttentionBackend
621
622
assert not FlashAttentionBackend.supports_kv_cache_dtype(kv_cache_dtype)
@@ -628,8 +627,7 @@ def test_flash_attn_accepts_handled_fp8_variants(
627
kv_cache_dtype: str, monkeypatch: pytest.MonkeyPatch
628
):
629
"""FlashAttentionBackend must accept the two fp8 dtypes it can actually
631
- handle: 'fp8' (alias for fp8_e4m3fn) and 'fp8_e4m3'.
632
- """
630
+ handle: 'fp8' (alias for fp8_e4m3fn) and 'fp8_e4m3'."""
631
import vllm.v1.attention.backends.fa_utils as fa_utils_mod
632
from vllm.v1.attention.backends.flash_attn import FlashAttentionBackend
633
tests/kernels/attention/test_cutlass_mla_decode.py
+1
-2
@@ -225,8 +225,7 @@ def test_cutlass_mla_decode_cross_layer_view():
225
"""The kernel must read the cache's page-dim stride instead of assuming
226
pages are packed back-to-back. A per-layer view into a cross-layer
227
(block-major) cache has stride(0) inflated by num_layers; outputs must
228
- match a contiguous cache holding the same data exactly.
229
- """
228
+ match a contiguous cache holding the same data exactly."""
229
device = torch.device("cuda:0")
230
torch.set_default_dtype(torch.bfloat16)
231
torch.set_default_device(device)
tests/kernels/attention/test_flashinfer.py
+1
-2
@@ -162,8 +162,7 @@ def test_fast_decode_plan_importable() -> None:
162
@torch.inference_mode
163
def test_fast_plan_decode_warmup_uses_full_plan(dtype: torch.dtype) -> None:
164
"""On the first call fast_plan_decode must route through self.plan() and
165
- flip vllm_first_call to False on the wrapper object.
166
- """
165
+ flip vllm_first_call to False on the wrapper object."""
166
from unittest.mock import patch
167
168
from vllm.v1.attention.backends.flashinfer import fast_plan_decode
tests/kernels/attention/test_flashinfer_trtllm_attention.py
+1
-2
@@ -134,8 +134,7 @@ def make_quantized_kv_cache(
134
head_size: int,
135
) -> tuple:
136
"""Quantize kv_cache based on dtype. Returns (kv_cache, kv_cache_sf,
137
- kv_scale, ref_kv_cache, is_nvfp4_kv).
138
- """
137
+ kv_scale, ref_kv_cache, is_nvfp4_kv)."""
138
is_nvfp4_kv = kv_quant_dtype == FP4_DTYPE
139
if is_nvfp4_kv:
140
data, scales, kv_scale, ref = make_nvfp4_kv_cache(
tests/kernels/attention/test_kimi_k3_mla_fused_epilogue.py
+1
-2
@@ -73,8 +73,7 @@ def _strided_context_inputs(
73
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
74
"""The real prefill-context layouts: ``k_nope``/``v`` as the two strided
75
halves of one kv_b_proj output and ``k_pe`` as a column slice of the gather
76
- workspace (left in the fp8 cache layout for a plain fp8 cache).
77
- """
76
+ workspace (left in the fp8 cache layout for a plain fp8 cache)."""
77
kv_nope = _randn(num_tokens, num_heads, 256, dtype=dtype)
78
k_nope, v = kv_nope.split((128, 128), dim=-1)
79
workspace = _randn(num_tokens, 576, dtype=dtype)
tests/kernels/attention/test_merge_attn_states.py
+1
-2
@@ -89,8 +89,7 @@ all_case_info: list[tuple] = []
89
@pytest.mark.parametrize("output_dtype", [torch.float32, torch.half, torch.bfloat16])
90
def test_merge_attn_states_both_empty(merge_fn, output_dtype) -> None:
91
"""When a token is empty on both sides (both LSE -inf), the 0/0 softmax
92
- scales must not surface as NaN in the merged output.
93
- """
92
+ scales must not surface as NaN in the merged output."""
93
num_tokens, num_heads, head_size = 6, 8, 128
94
prefix_output = torch.zeros(
95
num_tokens, num_heads, head_size, device=DEVICE, dtype=output_dtype
tests/kernels/attention/test_minimax_m3.py
+14
-28
@@ -45,8 +45,7 @@ def kv_layout(request) -> KVCacheLayout:
45
46
def _layer_stride_order(layout: KVCacheLayout, ndim: int) -> tuple[int, ...]:
47
"""Per-layer physical stride order for the given layout; the 3-dim
48
- indexer side cache (H=1) is contiguous, so identity.
49
- """
48
+ indexer side cache (H=1) is contiguous, so identity."""
49
if ndim == 3:
50
return (0, 1, 2)
51
stride_order = layout.layer_view_order
@@ -66,8 +65,7 @@ def _main_spec() -> FullAttentionSpec:
65
66
def _main_kv_logical_shape(num_pages: int) -> tuple[int, ...]:
67
"""Standardized per-layer logical shape [B, H, N, C] for the main cache,
69
- derived the same way the production allocator does.
70
- """
68
+ derived the same way the production allocator does."""
69
shape_bytes = compute_layer_kv_cache_shape_bytes(_main_spec(), num_pages)
70
return (*shape_bytes[:-1], shape_bytes[-1] // DTYPE.itemsize)
71
@@ -77,8 +75,7 @@ def _allocate_main_kv_via_contract(
75
) -> torch.Tensor:
76
"""Build the main KV cache exactly as the production allocator does for the
77
given layout: allocate the physical (permuted) tensor, then expose the
80
- inverse-permuted logical [B, H, N, C] view the backend sees.
81
- """
78
+ inverse-permuted logical [B, H, N, C] view the backend sees."""
79
logical_shape = _main_kv_logical_shape(num_pages)
80
stride_order = _layer_stride_order(layout, len(logical_shape))
81
physical_shape = tuple(logical_shape[i] for i in stride_order)
@@ -1379,8 +1376,7 @@ def test_amd_decode_index_topk_end_to_end(
1376
@pytest.mark.parametrize("num_idx_heads", [1, 4])
1377
def test_decode_index_topk_fp8(num_idx_heads: int):
1378
"""The standalone Triton path must score FP8 inputs in FP32 so its top-k
1382
- matches a reference computed from the dequantized FP8 values.
1383
- """
1379
+ matches a reference computed from the dequantized FP8 values."""
1380
torch.manual_seed(0)
1381
topk, init_blocks, local_blocks, head_dim = 8, 0, 1, 128
1382
decode_query_len = 1
@@ -1653,8 +1649,7 @@ def test_prefill_sparse_attention_correctness(
1649
def test_main_cache_layout_contract():
1650
"""The standardized per-layer logical shape is [B, H, N, C] with packed
1651
K/V content, and the legacy layout aliases resolve to the expected
1656
- per-layer stride orders.
1657
- """
1652
+ per-layer stride orders."""
1653
nb, bs, h, d = 7, BLOCK_SIZE, NUM_KV_HEADS, HEAD_DIM
1654
logical = _main_kv_logical_shape(nb)
1655
assert logical == (nb, h, bs, 2 * d)
@@ -1778,8 +1773,7 @@ def test_indexer_cache_squeezes_to_contiguous_3d():
1773
"""The indexer side cache is standardized 4D with H=1: under both layouts
1774
the allocator's logical view stays contiguous and squeezes (as
1775
`MiniMaxM3IndexerCache.bind_kv_cache` does) to the 3-dim
1781
- [num_blocks, block_size, head_dim] cache the kernels consume.
1782
- """
1776
+ [num_blocks, block_size, head_dim] cache the kernels consume."""
1777
nb = 5
1778
ispec = MLAAttentionSpec(
1779
block_size=BLOCK_SIZE, num_kv_heads=1, head_size=HEAD_DIM, dtype=DTYPE
@@ -1799,8 +1793,7 @@ def test_indexer_cache_squeezes_to_contiguous_3d():
1793
1794
def test_hnd_allocation_is_packed_head_major():
1795
"""Under HND the backend-visible logical view is the packed head-major
1802
- physical allocation.
1803
- """
1796
+ physical allocation."""
1797
nb, bs, h, d = 4, BLOCK_SIZE, NUM_KV_HEADS, HEAD_DIM
1798
logical = _main_kv_logical_shape(nb)
1799
stride_order = KVCacheLayout.LBHNC.layer_view_order
@@ -1828,8 +1821,7 @@ def test_hnd_allocation_is_packed_head_major():
1821
def test_main_cache_is_block_first_and_unpadded():
1822
"""The allocator's contiguous-view branch (not the padded-strided branch)
1823
is used for the main GQA cache: its spec is unpadded and the physical
1831
- layout keeps num_blocks as the first dimension under both layouts.
1832
- """
1824
+ layout keeps num_blocks as the first dimension under both layouts."""
1825
spec = _main_spec()
1826
# Unpadded -> allocator uses kv_tensor.view(...) rather than as_strided().
1827
assert spec.page_size_padded is None
@@ -1851,8 +1843,7 @@ def _build_decode_inputs(
1843
):
1844
"""Shared decode setup: uniform query tokens per request, a non-identity
1845
block table, and topk indices selecting the current block plus older causal
1854
- blocks for each query token.
1855
- """
1846
+ blocks for each query token."""
1847
active_batch = len(seq_lens_list)
1848
batch = active_batch + num_padded_reqs
1849
pages_per_req = [(s + BLOCK_SIZE - 1) // BLOCK_SIZE for s in seq_lens_list]
@@ -2188,8 +2179,7 @@ def test_decode_sparse_attention_correctness(
2179
):
2180
"""Decode (split-K) parity under both layouts: this is the only coverage of
2181
the decode-site cache feed, and the strided HND case fails if the kernel
2191
- ignores the cache strides.
2192
- """
2182
+ ignores the cache strides."""
2183
torch.manual_seed(0)
2184
q, block_table, seq_lens, topk_idx, num_pages = _build_decode_inputs(
2185
seq_lens_list, decode_query_len, num_padded_reqs
@@ -2239,8 +2229,7 @@ def test_decode_wrong_layout_breaks_parity():
2229
already contiguous-NHD (i.e. skipping the allocator's inverse permute)
2230
reorders the K/V content, so the decode output no longer matches the
2231
reference computed on the correct logical view. The mislabeled tensor keeps
2242
- the same shape as the correct view, so the kernel stays in bounds.
2243
- """
2232
+ the same shape as the correct view, so the kernel stays in bounds."""
2233
torch.manual_seed(0)
2234
seq_lens_list = (130, 257)
2235
q, block_table, seq_lens, topk_idx, num_pages = _build_decode_inputs(seq_lens_list)
@@ -2275,8 +2264,7 @@ def test_decode_wrong_layout_breaks_parity():
2264
def test_main_cache_byte_identical_through_production_allocator():
2265
"""AC-2: drive the real allocator (`create_kv_cache_views`) for the M3 main
2266
`FullAttentionSpec` under HND and assert the backend-visible view has the
2278
- same shape, stride, and storage offset as the packed-HND allocation.
2279
- """
2267
+ same shape, stride, and storage offset as the packed-HND allocation."""
2268
nb = 4
2269
spec = _main_spec()
2270
raw = torch.zeros(nb * spec.page_size_bytes, dtype=torch.int8)
@@ -2291,8 +2279,7 @@ def test_main_cache_byte_identical_through_production_allocator():
2279
def test_padded_main_cache_is_flagged():
2280
"""AC-2.1 negative: the M3 main cache relies on the allocator's
2281
contiguous-view branch (`page_size_padded is None`). A spec that sets
2294
- `page_size_padded` is explicitly flagged rather than silently wrong-strided.
2295
- """
2282
+ `page_size_padded` is explicitly flagged rather than silently wrong-strided."""
2283
2284
def _require_unpadded_block_first(spec, stride_order):
2285
inv_order = [stride_order.index(i) for i in range(len(stride_order))]
@@ -2329,8 +2316,7 @@ def test_padded_main_cache_is_flagged():
2316
def test_reshape_and_cache_flash_write_persists(kv_layout: KVCacheLayout):
2317
"""AC-5 write path: the `reshape_and_cache_flash` write site now consumes
2318
packed-content K/V split views. Writing through those views must persist
2332
- into the bound storage under both layouts.
2333
- """
2319
+ into the bound storage under both layouts."""
2320
torch.manual_seed(0)
2321
num_pages = 4
2322
kv_cache = _allocate_main_kv_via_contract(num_pages, kv_layout)
tests/kernels/attention/test_mla_cross_layer_kernel_equivalence.py
+8
-16
@@ -23,8 +23,7 @@ pytestmark = pytest.mark.skipif(
23
def test_concat_and_cache_mla_into_unified_slot_view():
24
"""concat_and_cache_mla must write correctly into a per-layer view whose
25
block stride is the full unified slot (block-major), with zero bleed into
26
- the other layers' segments of the same slot.
27
- """
26
+ the other layers' segments of the same slot."""
27
from vllm import _custom_ops as ops
28
29
torch.manual_seed(0)
@@ -86,8 +85,7 @@ def test_concat_and_cache_mla_into_unified_slot_view():
85
def test_flashmla_dense_decode_unified_slot_view():
86
"""FlashMLA dense decode (FLASHMLA backend, e.g. Kimi-K2-style dense MLA
87
on Hopper) must read a unified-slot block-major view bit-identically to a
89
- contiguous per-layer cache.
90
- """
88
+ contiguous per-layer cache."""
89
import vllm.v1.attention.ops.flashmla as fm
90
91
ok, reason = fm.is_flashmla_dense_supported()
@@ -152,8 +150,7 @@ def test_flashmla_dense_decode_unified_slot_view():
150
def test_flashinfer_mla_dense_decode_unified_slot_view():
151
"""FlashInfer MLA dense decode must read a unified-slot block-major view
152
(inflated stride(0), non-zero storage offset) bit-identically to a
155
- contiguous per-layer cache.
156
- """
153
+ contiguous per-layer cache."""
154
try:
155
from flashinfer.decode import trtllm_batch_decode_with_kv_cache_mla
156
except ImportError:
@@ -224,8 +221,7 @@ def test_flashinfer_mla_dense_decode_unified_slot_view():
221
def test_flashmla_fp8_sparse_decode_unified_slot_view(next_n: int):
222
"""FlashMLA fp8 sparse decode (DeepSeek V3.2/V4 DSA path) must read a
223
unified-slot block-major view bit-identically to a contiguous fp8_ds_mla
227
- cache, with finite nonzero output.
228
- """
224
+ cache, with finite nonzero output."""
225
import vllm.v1.attention.ops.flashmla as fm
226
227
ok, reason = fm.is_flashmla_sparse_supported()
@@ -314,8 +310,7 @@ def test_flashmla_fp8_sparse_decode_unified_slot_view(next_n: int):
310
def test_indexer_k_quant_and_cache_into_unified_slot_view():
311
"""indexer_k_quant_and_cache (DeepSeek V3.2/V4 DSA indexer K write) must
312
write correctly into a per-layer view whose block stride is the full
317
- unified slot, with zero bleed into the other layers' segments.
318
- """
313
+ unified slot, with zero bleed into the other layers' segments."""
314
from vllm import _custom_ops as ops
315
316
torch.manual_seed(0)
@@ -360,8 +355,7 @@ def test_indexer_k_quant_and_cache_into_unified_slot_view():
355
356
def test_flashattn_mla_dense_decode_unified_slot_view():
357
"""FA3 decode (FLASH_ATTN_MLA backend) must read a unified-slot
363
- block-major view bit-identically to a contiguous per-layer cache.
364
- """
358
+ block-major view bit-identically to a contiguous per-layer cache."""
359
try:
360
from vllm.vllm_flash_attn import flash_attn_varlen_func
361
except ImportError:
@@ -434,8 +428,7 @@ def test_flashattn_mla_dense_decode_unified_slot_view():
428
def test_flashmla_dense_fp8_decode_unified_slot_view():
429
"""FlashMLA dense fp8 decode (FLASHMLA backend with quantized KV cache)
430
must read a unified-slot block-major view bit-identically to a contiguous
437
- per-layer fp8 cache.
438
- """
431
+ per-layer fp8 cache."""
432
import vllm.v1.attention.ops.flashmla as fm
433
434
ok, reason = fm.is_flashmla_dense_supported()
@@ -506,8 +499,7 @@ def test_flashmla_dense_fp8_decode_unified_slot_view():
499
def test_flashinfer_mla_dense_fp8_decode_unified_slot_view():
500
"""FlashInfer MLA dense decode with an fp8 KV cache must read a
501
unified-slot block-major view bit-identically to a contiguous per-layer
509
- cache.
510
- """
502
+ cache."""
503
try:
504
from flashinfer.decode import trtllm_batch_decode_with_kv_cache_mla
505
except ImportError:
tests/kernels/attention/test_rocm_aiter_fa.py
+7
-14
@@ -283,8 +283,7 @@ def _run_direct_flash_attn_case(
283
# Backend contract tests --------------------------------------------------
284
def test_aiter_mha_backend_contract():
285
"""The ROCm backend advertises the dtypes, shapes, and attention types it
286
- is designed to handle.
287
- """
286
+ is designed to handle."""
287
from vllm.v1.attention.backend import AttentionType
288
from vllm.v1.attention.backends.rocm_aiter_fa import AiterFlashAttentionBackend
289
@@ -312,8 +311,7 @@ def test_aiter_mha_backend_contract():
311
312
def test_aiter_mha_backend_validates_kv_cache_block_size():
313
"""The backend should reject KV cache specs that cannot be gathered
315
- correctly by the ROCm kernel.
316
- """
314
+ correctly by the ROCm kernel."""
315
from vllm.v1.attention.backends.rocm_aiter_fa import AiterFlashAttentionBackend
316
from vllm.v1.kv_cache_interface import FullAttentionSpec
317
@@ -333,8 +331,7 @@ def test_aiter_mha_backend_validates_kv_cache_block_size():
331
332
def test_aiter_mha_backend_supports_compute_capability_matches_mi3xx_probe():
333
"""The backend should trust the ROCm MI3xx probe instead of the raw torch
336
- capability tuple.
337
- """
334
+ capability tuple."""
335
from vllm.platforms.interface import DeviceCapability
336
from vllm.v1.attention.backends.rocm_aiter_fa import AiterFlashAttentionBackend
337
@@ -359,8 +356,7 @@ def test_aiter_mha_env_flags_control_enablement(
356
use_aiter, use_mha, expected, monkeypatch
357
):
358
"""Both the global AITER flag and the MHA-specific flag must be enabled
362
- before the ROCm MHA path is considered active.
363
- """
359
+ before the ROCm MHA path is considered active."""
360
from vllm._aiter_ops import rocm_aiter_ops
361
362
_assert_aiter_supported()
@@ -378,8 +374,7 @@ def test_aiter_mha_env_flags_control_enablement(
374
375
def test_aiter_mha_platform_gate_matches_install_and_arch():
376
"""The global AITER availability check should only open on ROCm MI3xx when
381
- the aiter package is installed.
382
- """
377
+ the aiter package is installed."""
378
from vllm._aiter_ops import IS_AITER_FOUND, is_aiter_found_and_supported
379
380
assert is_aiter_found_and_supported() is (
@@ -650,8 +645,7 @@ def test_aiter_mha_multi_batch(num_heads, head_size, dtype):
645
@pytest.mark.parametrize("num_blocks", DIRECT_NUM_BLOCKS)
646
def test_aiter_fa_large_block_table_matches_reference(num_blocks):
647
"""The direct paged-KV path should stay stable for both normal and very
653
- large block tables.
654
- """
648
+ large block tables."""
649
atol = 2e-2
650
rtol = 2e-2
651
_assert_aiter_supported()
@@ -673,8 +667,7 @@ def test_aiter_fa_large_block_table_matches_reference(num_blocks):
667
@pytest.mark.skipif(not on_mi3xx(), reason="MI300/MI350 ROCm only")
668
def test_aiter_fa_sliding_window_matches_reference():
669
"""The direct kernel should respect the same sliding-window causal mask as
676
- the naive reference implementation.
677
- """
670
+ the naive reference implementation."""
671
atol = 2e-2
672
rtol = 2e-2
673
_assert_aiter_supported()
tests/kernels/attention/test_rocm_aiter_mla_sparse_metadata_sync.py
+2
-4
@@ -111,8 +111,7 @@ def _make_mixed_common_metadata():
111
112
def _patch_build_deps(monkeypatch, events=None):
113
"""Stub the aiter kernel, triton helper and CUDA sync so ``build()`` runs
114
- on CPU.
115
- """
114
+ on CPU."""
115
116
def fake_generate_sparse_seqlen_triton(
117
query_lens, seq_lens, cu_query_lens, topk_token, num_tokens, max_query_len
@@ -153,8 +152,7 @@ def test_build_populates_decode_only_split_fields(monkeypatch):
152
153
def test_build_populates_mixed_split_fields(monkeypatch):
154
"""Mixed decode+prefill batch: split is reported, prefill fields stay
156
- default because this impl always runs the MQA path.
157
- """
155
+ default because this impl always runs the MQA path."""
156
builder = _make_builder()
157
_patch_build_deps(monkeypatch)
158
tests/kernels/attention/test_triton_decode_attention.py
+2
-4
@@ -125,8 +125,7 @@ def _quantize_to_fp8(tensor: torch.Tensor):
125
@pytest.mark.parametrize("PAGE_SIZE", [1, 16])
126
def test_decode_attention_fp8(B, L, H_Q, H_KV, D_QK, D_V, CACHE_SIZE, PAGE_SIZE):
127
"""Test FP8 KV cache path: quantize K/V to FP8, run kernel with scales,
128
- and compare against BF16 reference output.
129
- """
128
+ and compare against BF16 reference output."""
129
assert CACHE_SIZE % PAGE_SIZE == 0
130
dtype = torch.bfloat16
131
seq_len = L
@@ -249,8 +248,7 @@ def test_decode_attention_cross_layer_view(H_Q, H_KV, D_QK, D_V, is_mla, PAGE_SI
248
"""The kernel must honor the cache's page-dim stride, not assume pages are
249
packed back-to-back. A per-layer view into a cross-layer (block-major)
250
cache has stride(0) inflated by num_layers; outputs must match a
252
- contiguous cache holding the same data exactly.
253
- """
251
+ contiguous cache holding the same data exactly."""
252
B = 3
253
seq_len = 1027
254
CACHE_SIZE = 16384
tests/kernels/core/test_fused_embed_norm.py
+2
-4
@@ -41,8 +41,7 @@ def _rmsnorm(x: torch.Tensor, w: torch.Tensor, eps: float) -> torch.Tensor:
41
def test_fused_embed_norm_matches_reference():
42
"""Main-model fusion: the residual is the exact gather and the second output
43
is a correct RMSNorm. The norm matches a full-precision reference to ~2 bf16
44
- ulp (rtol 1e-2) -- that gap is bf16 rounding, not the kernel.
45
- """
44
+ ulp (rtol 1e-2) -- that gap is bf16 rounding, not the kernel."""
45
set_random_seed(13)
46
table = torch.randn(VOCAB, HIDDEN, dtype=DTYPE, device="cuda")
47
ids = torch.randint(0, VOCAB, (NUM_TOKENS,), dtype=torch.int32, device="cuda")
@@ -61,8 +60,7 @@ def test_fused_embed_norm_matches_reference():
60
@torch.inference_mode()
61
def test_fused_embed_eh_norm_matches_reference():
62
"""MTP fusion (folded gather) is bit-exact vs gathering the embeds and
64
- feeding the untouched model-local ``fused_eh_norm``.
65
- """
63
+ feeding the untouched model-local ``fused_eh_norm``."""
64
set_random_seed(13)
65
table = torch.randn(VOCAB, HIDDEN, dtype=DTYPE, device="cuda")
66
ids = torch.randint(0, VOCAB, (NUM_TOKENS,), dtype=torch.int32, device="cuda")
tests/kernels/core/test_fused_q_kv_rmsnorm.py
+2
-4
@@ -62,8 +62,7 @@ def test_fused_q_kv_rmsnorm_outputs_are_packed(num_tokens: int):
62
a [1, q_size] slice of a [1, q_size + kv_size] buffer used to produce a
63
qr_out with row stride q_size + kv_size. Downstream dispatchers that
64
require packed row-major inputs then reject the tensor and silently fall
65
- back to a slower GEMM path on every decode step.
66
- """
65
+ back to a slower GEMM path on every decode step."""
66
device = "cuda"
67
dtype = torch.bfloat16
68
q_size, kv_size = 192, 576
@@ -89,8 +88,7 @@ def test_fused_q_kv_rmsnorm_outputs_are_packed(num_tokens: int):
88
def test_fused_q_kv_rmsnorm_launches_past_grid_y_cap(num_tokens: int):
89
"""Regression guard: grid used to be (2, num_tokens), hitting CUDA's
90
65535 grid-y cap at num_tokens >= 65536. The new grid (num_tokens, 2)
92
- lifts that bound to 2**31-1.
93
- """
91
+ lifts that bound to 2**31-1."""
92
device = "cuda"
93
dtype = torch.bfloat16
94
q_size, kv_size = 192, 576
tests/kernels/core/test_fused_rms_norm_gated.py
+1
-2
@@ -2,8 +2,7 @@
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
4
"""Tests that FusedRMSNormGated decomposes correctly under torch.compile,
5
-matching the eager triton kernel output.
6
-"""
5
+matching the eager triton kernel output."""
6
7
import pytest
8
import torch
tests/kernels/core/test_rocm_aiter_ops.py
+1
-2
@@ -579,8 +579,7 @@ def test_rocm_aiter_mla_dual_rmsnorm_group_quant_vs_sequential(m):
579
580
def test_rocm_aiter_mla_dual_rmsnorm_group_quant_strided_split_view():
581
"""Split-view inputs, as produced by the DeepSeek-V4 q/kv split, match
582
- contiguous inputs.
583
- """
582
+ contiguous inputs."""
583
require_aiter()
584
require_fp8()
585
from vllm._aiter_ops import rocm_aiter_ops
tests/kernels/core/test_vocab_parallel_embedding.py
+1
-2
@@ -87,8 +87,7 @@ def _shard(full_table, si, rows_per_rank, dtype):
87
@pytest.mark.parametrize("id_dtype", [torch.int32, torch.int64])
88
def test_matches_masked_gather(tp_size, vocab_size, org_vocab_size, hidden, id_dtype):
89
"""Every rank's partial output is bit-exact with the eager path, including
90
- the added-vocab (LoRA) rows and the ids owned by another rank.
91
- """
90
+ the added-vocab (LoRA) rows and the ids owned by another rank."""
91
set_random_seed(7)
92
dtype = torch.bfloat16
93
rows = pad_vocab_size(vocab_size, 64) // tp_size
tests/kernels/helion/test_autotune.py
+1
-2
@@ -59,8 +59,7 @@ class TestAutotuneDisabledKernel:
59
60
def test_autotune_disabled_kernel_produces_valid_config(self):
61
"""Register a kernel with no configs (disabled), run autotune,
62
- verify it produces a valid helion.Config.
63
- """
62
+ verify it produces a valid helion.Config."""
63
with dummy_kernel_registry(configs={}) as register:
64
wrapper = register(
65
"autotune_test_kernel",
tests/kernels/helion/test_register.py
+3
-6
@@ -598,8 +598,7 @@ class TestHelionKernelWrapper:
598
)
599
def test_init_eagerly_initializes_hop_path(self):
600
"""Test that register_kernel eagerly builds the configured kernel
601
- on the HOP path (no custom op registration needed).
602
- """
601
+ on the HOP path (no custom op registration needed)."""
602
from vllm.kernels.helion.utils import get_canonical_gpu_name
603
604
configs: dict[CaseKey, helion.Config] = {
@@ -634,8 +633,7 @@ class TestHelionKernelWrapper:
633
)
634
def test_init_eagerly_initializes(self):
635
"""Test that register_kernel eagerly loads configs and detects GPU
637
- during construction so __call__ needs no further initialization.
638
- """
636
+ during construction so __call__ needs no further initialization."""
637
from vllm.kernels.helion.utils import get_canonical_gpu_name
638
639
with (
@@ -963,8 +961,7 @@ class TestTorchCompileHOP:
961
962
def test_compiled_graph_contains_helion_hop(self):
963
"""Verify torch.compile on a HelionKernelWrapper emits a
966
- helion_kernel_wrapper_mutation HOP node in the FX graph.
967
- """
964
+ helion_kernel_wrapper_mutation HOP node in the FX graph."""
965
configs: dict[CaseKey, helion.Config] = {
966
CaseKey.default(): helion.Config(block_sizes=[4, 4])
967
}
tests/kernels/ir/test_layernorm.py
+1
-2
@@ -368,8 +368,7 @@ class TestFusedAddRMSNorm:
368
@pytest.mark.parametrize("provider", ["vllm_c"])
369
def test_inplace_semantics(self, dtype, n_tokens, hidden_size, epsilon, provider):
370
"""Test that inplace implementations reuse inputs,
371
- for maybe_inplace overload but not for default overload.
372
- """
371
+ for maybe_inplace overload but not for default overload."""
372
impl = ir.ops.fused_add_rms_norm.impls[provider]
373
if not impl.supported:
374
pytest.skip(f"{provider} impl not supported on this platform")
tests/kernels/mamba/cpu/test_cpu_gdn_ops.py
+3
-6
@@ -1055,8 +1055,7 @@ CONV_EQUIV_SEQ_LENS = [[1], [7], [64], [65], [1, 2, 3], [63, 64, 65], [128, 129]
1055
1056
def _conv_fp32_oracle(x, weight, bias, seq_lens, activation="silu"):
1057
"""High-precision conv reference: everything in float32, no bf16 rounding.
1058
- x: [total_tokens, dim] (no initial state). Returns [total_tokens, dim].
1059
- """
1058
+ x: [total_tokens, dim] (no initial state). Returns [total_tokens, dim]."""
1059
xf = x.float()
1060
wf = weight.float().unsqueeze(1)
1061
bf = bias.float()
@@ -1165,8 +1164,7 @@ def test_conv_cpp_no_worse_than_torch_vs_fp32(seq_lens):
1164
def test_conv_cpp_vnni_packed_matches_torch(seq_lens):
1165
"""The exact runtime prefill sequence (VNNI-packed weight + SD-layout
1166
conv_state view + is_vnni=True) must match the torch fallback. Validates
1168
- the packing + layout handoff on any AVX-512BF16 CPU.
1169
- """
1167
+ the packing + layout handoff on any AVX-512BF16 CPU."""
1168
x, weight, bias = _conv_inputs(sum(seq_lens))
1169
out_torch, _ = _run_prefill_torch(x, weight, bias, seq_lens)
1170
out_vnni, _ = _run_prefill_cpp(x, weight, bias, seq_lens, is_vnni=True)
@@ -1180,8 +1178,7 @@ def test_conv_cpp_vnni_packed_matches_torch(seq_lens):
1178
@torch.inference_mode()
1179
def test_conv_update_cpp_matches_torch(batch):
1180
"""Decode conv: causal_conv1d_update_cpu matches causal_conv1d_update_torch,
1183
- including the in-place conv_state update (the next-step handoff).
1184
- """
1181
+ including the in-place conv_state update (the next-step handoff)."""
1182
from vllm.model_executor.layers.mamba.ops.cpu.causal_conv1d import (
1183
causal_conv1d_update_torch,
1184
)
tests/kernels/mamba/test_mamba_ssm_configs.py
+3
-6
@@ -122,8 +122,7 @@ def test_fallback_when_no_config(monkeypatch, tmp_path):
122
123
def test_nearest_effective_batch_interpolation(monkeypatch, tmp_path):
124
"""When effective_batch = batch*nheads is not an exact key, the closest
125
- key should be selected.
126
- """
125
+ key should be selected."""
126
_write_config(
127
tmp_path,
128
dstate=32,
@@ -168,8 +167,7 @@ def test_nearest_effective_batch_interpolation(monkeypatch, tmp_path):
167
168
def test_non_dict_json_returns_none(monkeypatch, tmp_path):
169
"""A valid JSON file that is not a dict (e.g. a list) must be ignored
171
- and return None rather than raising AttributeError.
172
- """
170
+ and return None rather than raising AttributeError."""
171
device_name = get_ssm_device_name()
172
config_path = tmp_path / get_ssm_config_file_name(
173
_HEADDIM, 16, _CACHE_DTYPE, device_name
@@ -191,8 +189,7 @@ def test_non_dict_json_returns_none(monkeypatch, tmp_path):
189
190
def test_empty_config_falls_back_to_heuristic(monkeypatch, tmp_path):
191
"""An empty JSON object {} must not crash min() — should fall back
194
- to the hard-coded heuristic.
195
- """
192
+ to the hard-coded heuristic."""
193
_write_config(tmp_path, dstate=64, payload={})
194
195
monkeypatch.setenv("VLLM_TUNED_CONFIG_FOLDER", str(tmp_path))
tests/kernels/mamba/test_replayssm_prefill_decode_equivalence_mamba2.py
+1
-2
@@ -68,8 +68,7 @@ def _run_prefill_decode_equivalence(
68
the exact fp32 recurrence (and each other). All paths use the production dt
69
flow (raw dt + softplus + a per-head dt_bias), so this also checks prefill
70
and decode apply the softplus/bias preprocessing consistently. ``state_dtype``
71
- is the recurrent-state precision; ``act_dtype`` the activation/buffer one.
72
- """
71
+ is the recurrent-state precision; ``act_dtype`` the activation/buffer one."""
72
device = current_platform.device_type
73
rtol, atol = _prefill_tolerances(act_dtype)
74
set_random_seed(seed)
tests/kernels/mamba/test_replayssm_standard_decode_mamba2.py
+2
-4
@@ -95,8 +95,7 @@ def _run_standard_decode(
95
) -> None:
96
"""Drive ``num_steps`` decode steps and check every path against the
97
trusted recurrence. ``state_dtype`` is the recurrent-state precision;
98
- ``act_dtype`` is the activation/buffer precision.
99
- """
98
+ ``act_dtype`` is the activation/buffer precision."""
99
device = "cuda"
100
both_fp32 = state_dtype == torch.float32 and act_dtype == torch.float32
101
rtol, atol = _tolerances(torch.float32 if both_fp32 else torch.bfloat16)
@@ -540,8 +539,7 @@ def test_replayssm_standard_decode_tp_head_shard_equivalence(
539
separable: one run over all heads must equal concatenating ``tp`` independent
540
per-rank runs on ``nheads // tp`` heads and ``ngroups // tp`` groups. This
541
guards the per-rank divisors and group->head mapping the state-shape wiring
543
- relies on. The real TP1==TP2 engine check lives in the v1/e2e suite.
544
- """
542
+ relies on. The real TP1==TP2 engine check lives in the v1/e2e suite."""
543
state_dtype, act_dtype = precision
544
nheads, headdim, dstate, ngroups = geometry
545
assert nheads % tp == 0 and ngroups % tp == 0
tests/kernels/moe/modular_kernel_tools/common.py
+1
-2
@@ -167,8 +167,7 @@ class Config:
167
168
def fe_supports_quant_scheme(self) -> bool:
169
"""Check if the fused experts class supports this quant config.
170
- See https://github.com/ROCm/aiter/issues/2419 for AITER gaps.
171
- """
170
+ See https://github.com/ROCm/aiter/issues/2419 for AITER gaps."""
171
if self.quant_config is None or self.quant_dtype is None:
172
return True
173
if self.quant_dtype != torch.float8_e4m3fn:
tests/kernels/moe/test_b12x.py
+1
-2
@@ -468,8 +468,7 @@ def test_deepseek_v4_flashinfer_cutlass_falls_through_to_w4a8(
468
monkeypatch: pytest.MonkeyPatch,
469
) -> None:
470
"""Explicit flashinfer_cutlass must try the W4A8 variant when the BF16
471
- variant is unsupported (the BF16 variant is gated to SM90).
472
- """
471
+ variant is unsupported (the BF16 variant is gated to SM90)."""
472
from vllm.model_executor.layers.fused_moe.experts.flashinfer_cutlass_moe import (
473
FlashInferExperts,
474
)
tests/kernels/moe/test_batched_moe.py
+3
-6
@@ -129,8 +129,7 @@ def test_batched_mm(
129
per_act_token_quant: bool,
130
):
131
"""Note: float8_e4m3fn is not supported on CUDA architecture < 89,
132
- and those tests will be skipped on unsupported hardware.
133
- """
132
+ and those tests will be skipped on unsupported hardware."""
133
set_random_seed(7)
134
135
use_fp8_w8a8 = dtype == torch.float8_e4m3fn
@@ -269,8 +268,7 @@ def test_fused_moe_batched_experts(
268
workspace_init,
269
):
270
"""Note: float8_e4m3fn is not supported on CUDA architecture < 89,
272
- and those tests will be skipped on unsupported hardware.
273
- """
271
+ and those tests will be skipped on unsupported hardware."""
272
set_random_seed(7)
273
274
use_fp8_w8a8 = dtype == torch.float8_e4m3fn
@@ -651,8 +649,7 @@ def test_batched_experts_masked_activation_end_to_end(
649
def test_batched_experts_end_to_end(m, n, k, e, topk):
650
"""End-to-end BatchedTritonExperts via the reference (no-comms)
651
BatchedPrepareAndFinalize, validated against a torch reference. Exercises
654
- the device-enablement path.
655
- """
652
+ the device-enablement path."""
653
from vllm.v1.worker.workspace import init_workspace_manager
654
655
set_random_seed(7)
tests/kernels/moe/test_block_int8.py
+2
-4
@@ -54,8 +54,7 @@ SEEDS = [0]
54
# For test
55
def torch_w8a8_block_int8_moe(a, w1, w2, w1_s, w2_s, score, topk, block_shape):
56
"""This function performs fused moe with block-wise quantization using
57
- native torch.
58
- """
57
+ native torch."""
58
B, D = a.shape
59
a = a.view(B, -1, D).repeat(1, topk, 1).reshape(-1, D)
60
out = torch.zeros(B * topk, w2.shape[1], dtype=a.dtype, device=a.device)
@@ -98,8 +97,7 @@ def setup_cuda():
97
@torch.inference_mode()
98
def test_w8a8_block_int8_fused_moe(M, N, K, E, topk, block_size, dtype, seed):
99
"""Tests the fused_moe kernel with W8A8 INT8 block quantization against a
101
- native torch reference.
102
- """
100
+ native torch reference."""
101
torch.manual_seed(seed)
102
103
a = torch.randn((M, K), dtype=dtype) / 10
tests/kernels/moe/test_cpu_fused_moe.py
+2
-4
@@ -397,8 +397,7 @@ UNALIGNED_INTERMEDIATE_DIM = 176
397
class _StubMoELayer(torch.nn.Module):
398
"""Minimal stand-in for the real MoE layer module, exposing just what
399
the unquantized CPU experts read/replace (w13_weight, w2_weight, the
400
- router configuration, and optionally w13_bias/w2_bias).
401
- """
400
+ router configuration, and optionally w13_bias/w2_bias)."""
401
402
def __init__(
403
self,
@@ -501,8 +500,7 @@ def test_cpu_fused_moe_unaligned_intermediate_size(
500
act: MoEActivation,
501
):
502
"""CPU kernels handle unaligned intermediate sizes by zero-padding the
504
- weights before prepacking.
505
- """
503
+ weights before prepacking."""
504
set_random_seed(0)
505
batch_size = 64
506
intermediate_size = UNALIGNED_INTERMEDIATE_DIM
tests/kernels/moe/test_flashinfer.py
+1
-2
@@ -464,8 +464,7 @@ def test_trtllm_fp8_swiglu_clamp_support(
464
):
465
"""FlashInfer >= 0.6.18 applies the SwiGLU clamp for both block-scaled
466
kernels with a SwiGLU activation (DeepSeek-V4 sets swiglu_limit); the
467
- per-tensor kernel has no clamp, and Relu2 rejects the parameters.
468
- """
467
+ per-tensor kernel has no clamp, and Relu2 rejects the parameters."""
468
469
class _Experts(TrtLlmFp8ExpertsModular):
470
@staticmethod
tests/kernels/moe/test_gpt_oss_triton_kernels.py
+1
-2
@@ -377,8 +377,7 @@ def test_unit_shuffle():
377
@pytest.mark.parametrize("n_experts,topk", [(32, 4), (128, 4)])
378
def test_routing_data_from_sparse_topk_parity(n_tokens, n_experts, topk):
379
"""routing_data_from_sparse_topk must produce routing structures
380
- identical to make_routing_data for the same topk result.
381
- """
380
+ identical to make_routing_data for the same topk result."""
381
from vllm.model_executor.layers.fused_moe.experts import (
382
gpt_oss_triton_kernels_moe as gptoss_moe,
383
)
tests/kernels/moe/test_marlin_vs_trtllm_mxint4.py
+1
-2
@@ -289,8 +289,7 @@ def test_marlin_vs_trtllm_mxint4_moe_kimik2(monkeypatch, m, n, k, e, topk, group
289
@torch.inference_mode()
290
def test_flashinfer_trtllm_mxint4_moe_wrapper(m, n, k, e, topk):
291
"""Test that the flashinfer_trtllm_mxint4_moe wrapper matches the raw
292
- trtllm_mxint4_block_scale_moe kernel call.
293
- """
292
+ trtllm_mxint4_block_scale_moe kernel call."""
293
pytest.importorskip("flashinfer")
294
from flashinfer import RoutingMethodType
295
from flashinfer.fused_moe import trtllm_mxint4_block_scale_moe
tests/kernels/moe/test_modular_kernel_combinations.py
+1
-2
@@ -352,8 +352,7 @@ def test_modular_kernel_combinations_singlegpu(
352
workspace_init,
353
):
354
"""Note: float8_e4m3fn is not supported on CUDA architecture < 89,
355
- and those tests will be skipped on unsupported hardware.
356
- """
355
+ and those tests will be skipped on unsupported hardware."""
356
config = Config(
357
Ms=Ms,
358
K=k,
tests/kernels/moe/test_moe_kernel_oracle.py
+1
-2
@@ -21,8 +21,7 @@ from vllm.model_executor.layers.fused_moe.oracle.unquantized import (
21
22
class TestUnquantizedDelegation:
23
"""UnquantizedMoEKernelOracle methods must delegate to the existing
24
- module-level functions; behaviour is bit-identical.
25
- """
24
+ module-level functions; behaviour is bit-identical."""
25
26
def test_make_kernel_delegates(self) -> None:
27
quant_config = object()
tests/kernels/moe/test_moe_layer.py
+1
-2
@@ -315,8 +315,7 @@ def tp_chunk_gate_up(
315
device: torch.device | int | None = None,
316
) -> torch.Tensor:
317
"""TP-chunk a combined [gate; up] weight, splitting each half separately
318
- so every rank gets a portion of both gate and up.
319
- """
318
+ so every rank gets a portion of both gate and up."""
319
half = w.shape[dim] // 2
320
gate = chunk_by_rank(
321
w.narrow(dim, 0, half), tp_rank, tp_size, dim=dim, device=device
tests/kernels/moe/test_mxfp8_aiter_backend_selection.py
+2
-4
@@ -130,8 +130,7 @@ def test_is_supported_config(present, ep_size, supported, reason_substr):
130
131
def test_explicit_moe_backend_aiter():
132
"""--moe-backend aiter: returns FlyDSL when usable (TP or EP), else a clear
133
- ValueError when the flydsl package is missing.
134
- """
133
+ ValueError when the flydsl package is missing."""
134
with _gfx950(), _flydsl_installed(True):
135
assert (
136
_select_kernel_cls(Fp8MoeBackend.AITER_MXFP8, _config(1))
@@ -163,8 +162,7 @@ def test_gfx950_picks_aiter():
162
163
def test_gfx942_picks_emulation():
164
"""Flydsl unusable (e.g. gfx942, no FlyDSL support) -> native Triton
166
- dot_scaled backend wins instead.
167
- """
165
+ dot_scaled backend wins instead."""
166
with patch(f"{_AITER_MOD}.current_platform.supports_mx", return_value=False):
167
backend, experts_cls = select_mxfp8_moe_backend(_config())
168
assert backend is Fp8MoeBackend.EMULATION
tests/kernels/moe/test_rocm_aiter_moe.py
+11
-22
@@ -249,8 +249,7 @@ def _make_topk_ids(
249
device: str = "cuda",
250
) -> torch.Tensor:
251
"""Generate distinct expert IDs per token with the same top-k shape as
252
- production routing.
253
- """
252
+ production routing."""
253
router_logits = torch.randn(num_tokens, num_experts, device=device)
254
_, topk_ids = torch.topk(torch.softmax(router_logits, dim=-1), k=topk, dim=-1)
255
return topk_ids.to(torch.int32)
@@ -444,8 +443,7 @@ def test_aiter_fused_moe_custom_op_registered():
443
444
def test_aiter_asm_moe_tkw1_custom_op_registered():
445
"""The tkw1 custom op should stay registered for FP8 apply-router-weight
447
- paths.
448
- """
446
+ paths."""
447
_assert_aiter_supported()
448
import vllm._aiter_ops as aiter_ops # noqa: F401
449
@@ -455,8 +453,7 @@ def test_aiter_asm_moe_tkw1_custom_op_registered():
453
454
def test_aiter_fused_moe_fake_tensor_support():
455
"""The fused-MoE op should preserve fake-tensor compatibility for
458
- torch.compile-style tracing.
459
- """
456
+ torch.compile-style tracing."""
457
_assert_aiter_supported()
458
import vllm._aiter_ops # noqa: F401
459
@@ -519,8 +516,7 @@ def test_aiter_moe_enablement_follows_env(
516
monkeypatch: pytest.MonkeyPatch,
517
):
518
"""The fused-MoE gate should depend only on the main AITER toggle and the
522
- MoE-specific toggle.
523
- """
519
+ MoE-specific toggle."""
520
from vllm._aiter_ops import rocm_aiter_ops
521
522
_assert_aiter_supported()
@@ -551,8 +547,7 @@ def test_aiter_moe_shared_experts_enablement_follows_env(
547
monkeypatch: pytest.MonkeyPatch,
548
):
549
"""Shared-expert fusion should only be enabled when the fused-MoE path is
554
- enabled too.
555
- """
550
+ enabled too."""
551
from vllm._aiter_ops import rocm_aiter_ops
552
553
_assert_aiter_supported()
@@ -693,8 +688,7 @@ def test_aiter_mxfp4_quant_scheme_support_matches_gfx950():
688
@pytest.mark.skipif(not on_gfx950(), reason="gfx950 ROCm only")
689
def test_aiter_fused_moe_mi350_mxfp4_w4a16_accuracy():
690
"""The gfx950 AITER MXFP4 W4A16 MoE path should match the dequantized
696
- MXFP4 reference.
697
- """
691
+ MXFP4 reference."""
692
from vllm.model_executor.layers.fused_moe.activation import MoEActivation
693
from vllm.model_executor.layers.fused_moe.experts.rocm_aiter_moe import (
694
rocm_aiter_fused_experts,
@@ -743,8 +737,7 @@ def test_aiter_fused_moe_mi350_mxfp4_w4a16_accuracy():
737
@pytest.mark.skipif(not on_gfx950(), reason="gfx950 ROCm only")
738
def test_aiter_fused_moe_mi350_mxfp4_w4a16_determinism():
739
"""The gfx950 AITER MXFP4 W4A16 MoE path should stay bitwise
746
- deterministic.
747
- """
740
+ deterministic."""
741
from vllm.model_executor.layers.fused_moe.activation import MoEActivation
742
from vllm.model_executor.layers.fused_moe.experts.rocm_aiter_moe import (
743
rocm_aiter_fused_experts,
@@ -837,8 +830,7 @@ def test_aiter_fused_moe_bf16_accuracy(
830
intermediate_dim: int,
831
):
832
"""The ROCm AITER fused-MoE BF16 path should match the float32 reference
840
- on representative shapes.
841
- """
833
+ on representative shapes."""
834
from vllm.model_executor.layers.fused_moe.experts.rocm_aiter_moe import (
835
ActivationMethod,
836
QuantMethod,
@@ -883,8 +875,7 @@ def test_aiter_fused_moe_bf16_accuracy(
875
876
def test_aiter_fused_moe_gelu_accuracy():
877
"""The GELU activation variant should stay aligned with the float32
886
- reference.
887
- """
878
+ reference."""
879
from vllm.model_executor.layers.fused_moe.experts.rocm_aiter_moe import (
880
ActivationMethod,
881
QuantMethod,
@@ -929,8 +920,7 @@ def test_aiter_fused_moe_gelu_accuracy():
920
921
def test_aiter_fused_moe_determinism():
922
"""The BF16 fused-MoE kernel should stay bitwise deterministic for the
932
- same inputs.
933
- """
923
+ same inputs."""
924
from vllm.model_executor.layers.fused_moe.experts.rocm_aiter_moe import (
925
ActivationMethod,
926
QuantMethod,
@@ -1085,8 +1075,7 @@ def test_aiter_fused_moe_mi3xx_bf16_accuracy():
1075
)
1076
def test_aiter_fused_moe_mi3xx_fp8_accuracy():
1077
"""The MI3xx FP8 per-tensor MoE path should stay within the measured FP8
1088
- error budget.
1089
- """
1078
+ error budget."""
1079
from tests.kernels.moe.utils import make_test_weights
1080
from vllm._aiter_ops import rocm_aiter_ops
1081
from vllm.model_executor.layers.fused_moe.experts.rocm_aiter_moe import (
tests/kernels/moe/test_routed_experts_capture_monolithic.py
+8
-16
@@ -185,8 +185,7 @@ def test_trtllm_bf16_monolithic_routing_replay_records_valid_experts(
185
) -> None:
186
"""The capture callback should receive the int16 routed-expert IDs the
187
kernel actually used, the values should be valid expert indices, and
188
- each token should pick ``top_k`` distinct experts.
189
- """
188
+ each token should pick ``top_k`` distinct experts."""
189
if top_k > _DSV3_N_GROUP * _DSV3_TOPK_GROUP:
190
pytest.skip(
191
f"DSV3 requires top_k <= n_group * topk_group "
@@ -265,8 +264,7 @@ def test_trtllm_bf16_monolithic_routing_replay_non_dsv3(
264
routing_method: RoutingMethodType,
265
) -> None:
266
"""Routing replay works for non-DeepSeekV3 routing methods too.
268
- FlashInfer's ``routing_replay_out`` is routing-method-agnostic.
269
- """
267
+ FlashInfer's ``routing_replay_out`` is routing-method-agnostic."""
268
torch.manual_seed(0)
269
device = torch.device("cuda:0")
270
@@ -319,8 +317,7 @@ def test_trtllm_bf16_monolithic_routing_replay_non_dsv3(
317
318
def test_trtllm_bf16_monolithic_capture_disabled_skips_buffer_alloc() -> None:
319
"""With no callback installed the kernel should not see a
322
- ``routing_replay_out`` tensor — verify the helper short-circuits.
323
- """
320
+ ``routing_replay_out`` tensor — verify the helper short-circuits."""
321
torch.manual_seed(0)
322
device = torch.device("cuda:0")
323
experts, _, _ = _make_bf16_monolithic_experts(
@@ -342,8 +339,7 @@ def test_trtllm_bf16_monolithic_capture_disabled_skips_buffer_alloc() -> None:
339
def test_trtllm_bf16_monolithic_supports_capture_for_all_routing() -> None:
340
"""FlashInfer's ``routing_replay_out`` is supported by all routing
341
methods, so ``supports_routing_replay_capture`` should be True
345
- regardless of routing method.
346
- """
342
+ regardless of routing method."""
343
device = torch.device("cuda:0")
344
for routing_method in (
345
RoutingMethodType.DeepSeekV3,
@@ -365,8 +361,7 @@ def test_trtllm_bf16_monolithic_supports_capture_for_all_routing() -> None:
361
362
def test_trtllm_bf16_monolithic_capture_buffer_shape_and_dtype() -> None:
363
"""When capture is installed, the allocated buffer is int16 and shaped
368
- ``(num_tokens, experts_per_token)``.
369
- """
364
+ ``(num_tokens, experts_per_token)``."""
365
device = torch.device("cuda:0")
366
experts, _, _ = _make_bf16_monolithic_experts(
367
num_experts=_DSV3_NUM_EXPERTS,
@@ -597,8 +592,7 @@ def test_trtllm_fp8_block_scale_monolithic_routing_replay_records_valid_experts(
592
top_k: int,
593
) -> None:
594
"""End-to-end: ``TrtLlmFp8ExpertsMonolithic`` (DeepSeekFp8 block-scale
600
- path, DSV3 routing) captures valid expert IDs.
601
- """
595
+ path, DSV3 routing) captures valid expert IDs."""
596
if top_k > _DSV3_N_GROUP * _DSV3_TOPK_GROUP:
597
pytest.skip(
598
f"DSV3 requires top_k <= n_group * topk_group "
@@ -784,8 +778,7 @@ def _run_nvfp4_monolithic(
778
routing_bias: torch.Tensor,
779
) -> torch.Tensor:
780
"""The monolithic NVFP4 apply expects packed fp4 hidden states + the
787
- matching fp8 per-block scale stored in the ``a1q_scale`` slot.
788
- """
781
+ matching fp8 per-block scale stored in the ``a1q_scale`` slot."""
782
# Stash the weight tensors on the experts in the locations the apply()
783
# implementation reads from (it pulls them from quant_config / scales
784
# already; w1/w2 come in as args).
@@ -813,8 +806,7 @@ def test_trtllm_nvfp4_monolithic_routing_replay_records_valid_experts(
806
top_k: int,
807
) -> None:
808
"""End-to-end: ``TrtLlmNvFp4ExpertsMonolithic`` captures valid expert IDs
816
- on the DSV3 routing path.
817
- """
809
+ on the DSV3 routing path."""
810
if top_k > _DSV3_N_GROUP * _DSV3_TOPK_GROUP:
811
pytest.skip(
812
f"DSV3 requires top_k <= n_group * topk_group "
tests/kernels/moe/test_routing.py
+1
-2
@@ -250,8 +250,7 @@ def assert_aiter_routing_valid(
250
the Python baseline (different group selection, scoring internals),
251
so numerical comparison is not meaningful. Instead we verify the
252
outputs satisfy the routing contract: correct shapes, valid expert
253
- IDs, non-negative weights, and proper normalization.
254
- """
253
+ IDs, non-negative weights, and proper normalization."""
254
n_tokens = topk_weights.shape[0]
255
256
# Shape
tests/kernels/moe/test_routing_simulator.py
+2
-4
@@ -76,8 +76,7 @@ def test_basic_functionality(
76
77
def test_routing_strategy_integration(monkeypatch, device):
78
"""Test that the routing strategy environment variable works with
79
- FusedMoEFactory.
80
- """
79
+ FusedMoEFactory."""
80
pytest.importorskip("vllm.model_executor.layers.fused_moe.layer")
81
82
import vllm.envs as envs
@@ -158,8 +157,7 @@ def test_routing_strategy_integration(monkeypatch, device):
157
158
def test_distribution_based_routing_with_custom_strategy():
159
"""Test registering and using DistributionBasedRouting with custom
161
- parameters.
162
- """
160
+ parameters."""
161
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
162
163
# Register custom distribution-based strategy
tests/kernels/moe/test_silu_mul_per_token_group_quant_fp8_colmajor.py
+1
-2
@@ -70,8 +70,7 @@ def reference_with_clamp(
70
) -> tuple[torch.Tensor, torch.Tensor]:
71
"""Pre-clamp inputs (gate from above, up symmetric) at the input dtype to
72
match the C++ compute() template, then run the standard silu_and_mul +
73
- quant reference.
74
- """
73
+ quant reference."""
74
N_2 = x.size(1) // 2
75
dtype = x.dtype
76
gate = x[..., :N_2].to(torch.float32).clamp(max=clamp_limit).to(dtype)
tests/kernels/moe/test_triton_moe_ptpc_fp8.py
+2
-4
@@ -28,8 +28,7 @@ if current_platform.is_fp8_fnuz():
28
29
def native_w8a8_per_token_matmul(A, B, As, Bs, output_dtype=torch.float16):
30
"""Matrix multiplication function that supports per-token input
31
- quantization and per-column weight quantization
32
- """
31
+ quantization and per-column weight quantization"""
32
A = A.to(torch.float32)
33
B = B.to(torch.float32)
34
@@ -57,8 +56,7 @@ def fp8_mask(a, mask):
56
57
def torch_w8a8_per_column_moe(a, w1, w2, w1_s, w2_s, score, topk):
58
"""This function performs fused moe with per-column int8
60
- quantization using native torch.
61
- """
59
+ quantization using native torch."""
60
B, D = a.shape
61
# Perform per-token quantization
62
a_q, a_s = ops.scaled_fp8_quant(a, use_per_token_if_dynamic=True)
tests/kernels/moe/test_unquantized_backend_selection.py
+2
-4
@@ -150,8 +150,7 @@ def test_select_default_backend_by_platform(
150
expected_backend,
151
):
152
"""Test default backend selection per platform with all optional
153
- accelerators (FlashInfer, AITER) disabled.
154
- """
153
+ accelerators (FlashInfer, AITER) disabled."""
154
with patch(
155
"vllm.model_executor.layers.fused_moe.oracle.unquantized.current_platform"
156
) as mock_platform:
@@ -445,8 +444,7 @@ def test_select_cuda_flashinfer_cutlass_backend(
444
mock_has_flashinfer,
445
):
446
"""Test CUDA backend selection when FlashInfer TRTLLM is not available
448
- and FlashInfer CUTLASS is available.
449
- """
447
+ and FlashInfer CUTLASS is available."""
448
with (
449
patch.object(current_platform, "is_cuda", return_value=True),
450
patch.object(current_platform, "is_rocm", return_value=False),
tests/kernels/quant_utils.py
+1
-2
@@ -159,8 +159,7 @@ def native_per_token_group_quant_fp8(
159
x, group_size, eps=1e-10, dtype=torch.float8_e4m3fn
160
):
161
"""Function to perform per-token-group quantization on an input tensor
162
- `x` using native torch.
163
- """
162
+ `x` using native torch."""
163
assert x.shape[-1] % group_size == 0, (
164
"the last dimension of `x` must be divisible by `group_size`"
165
)
tests/kernels/quantization/test_aiter_hipb_mm_linear_kernel.py
+1
-2
@@ -304,8 +304,7 @@ def test_hipb_mm_kernel_forward_matches_raw_aiter_hipb_mm(enable_hipb_mm_kernel)
304
305
def test_hipb_mm_kernel_forward_accuracy(enable_hipb_mm_kernel):
306
"""Kernel output should match a dequantized fp32 reference within
307
- fp8 per-token / per-channel quantization noise.
308
- """
307
+ fp8 per-token / per-channel quantization noise."""
308
weight_shape = (512, 4096) # (N, K)
309
num_tokens = 32
310
_check_bpreshuffle_runtime_support(weight_shape, num_tokens=num_tokens)
tests/kernels/quantization/test_int8_kernel.py
+2
-4
@@ -30,8 +30,7 @@ if current_platform.is_cuda_alike() and not current_platform.has_device_capabili
30
31
def native_w8a8_per_token_matmul(A, B, As, Bs, output_dtype=torch.float16):
32
"""Matrix multiplication function that supports per-token input
33
- quantization and per-column weight quantization
34
- """
33
+ quantization and per-column weight quantization"""
34
A = A.to(torch.float32)
35
B = B.to(torch.float32)
36
@@ -54,8 +53,7 @@ def native_w8a8_per_token_matmul(A, B, As, Bs, output_dtype=torch.float16):
53
54
def torch_w8a8_per_column_moe(a, w1, w2, w1_s, w2_s, topk, topk_weight, topk_ids):
55
"""This function performs fused moe with per-column int8 quantization
57
- using native torch.
58
- """
56
+ using native torch."""
57
B, D = a.shape
58
# Perform per-token quantization
59
a_q, a_s = per_token_quant_int8(a)
tests/kernels/quantization/test_marlin_tile_padding.py
+5
-10
@@ -360,8 +360,7 @@ def test_gptq_marlin_padded_round_trip(shape, group_size):
360
def test_fp8_block_marlin_padded_round_trip(shape):
361
"""Block-quantized FP8 (e.g. Nemotron NVFP4 checkpoints' FP8 layers):
362
group_size=128 exercises the lcm K-alignment in marlin_padded_nk and the
363
- weight_scale_inv group-wise scale padding.
364
- """
363
+ weight_scale_inv group-wise scale padding."""
364
size_n, size_k = shape
365
block = 128
366
dtype = torch.float16
@@ -411,8 +410,7 @@ def test_fp8_block_marlin_padded_round_trip(shape):
410
@pytest.mark.parametrize("shape", [(200, 288), (4640, 512)])
411
def test_mxfp8_marlin_padded_round_trip(shape):
412
"""MXFP8 exercises the e8m0 scale path, where padded 0.0 scales clamp to
414
- 2^-127 instead of zero and must still contribute nothing.
415
- """
413
+ 2^-127 instead of zero and must still contribute nothing."""
414
size_n, size_k = shape
415
group_size = 32
416
# The e8m0-scale Marlin kernels are only instantiated for bf16 activations.
@@ -459,8 +457,7 @@ def test_mxfp8_marlin_padded_round_trip(shape):
457
@pytest.mark.parametrize("shape", [(200, 512), (4640, 512)])
458
def test_awq_zp_marlin_padded_round_trip(shape):
459
"""AWQ-style uint4 with runtime zero-points, padded the way
462
- MarlinLinearKernel does: padded columns rely on (q=0 - zp=0) * scale=0.
463
- """
460
+ MarlinLinearKernel does: padded columns rely on (q=0 - zp=0) * scale=0."""
461
size_n, size_k = shape
462
group_size = 128
463
dtype = torch.float16
@@ -695,8 +692,7 @@ def test_check_moe_marlin_supports_layer_padding():
692
@pytest.mark.parametrize("shape", [(96, 256, 8), (160, 512, 4)])
693
def test_fp8_marlin_moe_padded_round_trip(shape, quant):
694
"""FP8 weight-only MoE: pad a tile-misaligned intermediate and check the
698
- real prepare + fused_marlin_moe against the dequantized reference.
699
- """
695
+ real prepare + fused_marlin_moe against the dequantized reference."""
696
from tests.kernels.utils import torch_experts
697
from vllm.config import VllmConfig, set_current_vllm_config
698
from vllm.model_executor.layers.fused_moe import fused_topk
@@ -781,8 +777,7 @@ def test_fp8_marlin_moe_padded_round_trip(shape, quant):
777
@pytest.mark.parametrize("shape", [(96, 256, 8), (160, 512, 4)])
778
def test_mxfp8_marlin_moe_padded_round_trip(shape):
779
"""MXFP8 weight-only MoE round-trip at a tile-misaligned intermediate, with
784
- unit e8m0 scales so the reference is the exact fp8 dequant.
785
- """
780
+ unit e8m0 scales so the reference is the exact fp8 dequant."""
781
from tests.kernels.utils import torch_experts
782
from vllm.config import VllmConfig, set_current_vllm_config
783
from vllm.model_executor.layers.fused_moe import fused_topk
tests/kernels/quantization/test_mxfp4_kernel_selection.py
+6
-12
@@ -72,8 +72,7 @@ def test_true_w4a4_kernels_reject_unset_activation(kernel_cls):
72
@pytest.mark.parametrize("kernel_cls", _TRUE_W4A4_KERNELS)
73
def test_true_w4a4_kernels_reject_explicit_non_mxfp4_activation(kernel_cls):
74
"""FlashInfer/XPU/Aiter quantize activations to MXFP4 internally, so an
75
- explicit request for a different activation format must be rejected.
76
- """
75
+ explicit request for a different activation format must be rejected."""
76
config = MxFp4LinearLayerConfig(activation_quant_key=kMxfp6E3M2Dynamic)
77
can_implement, reason = kernel_cls.can_implement(config)
78
assert not can_implement
@@ -88,8 +87,7 @@ def test_weight_only_kernels_accept_unquantized_or_mxfp4_activation(
87
"""Marlin/Humming never quantize activations, so an unset activation key,
88
or one that already describes MXFP4-shaped data, is tolerated. When an
89
activation key is explicitly set, a warning must be logged noting that it
91
- is ignored, since these kernels are weight-only (A16).
92
- """
90
+ is ignored, since these kernels are weight-only (A16)."""
91
config = MxFp4LinearLayerConfig(activation_quant_key=activation_quant_key)
92
with patch(f"{kernel_cls.__module__}.logger.warning_once") as warning_once:
93
can_implement, reason = kernel_cls.can_implement(config)
@@ -118,8 +116,7 @@ def test_weight_only_kernels_reject_non_mxfp4_activation(kernel_cls):
116
)
117
def test_emulation_kernel_accepts_any_config(activation_quant_key, monkeypatch):
118
"""EmulationMxfp4LinearKernel is the universal fallback: it must accept
121
- every supported activation format.
122
- """
119
+ every supported activation format."""
120
# `EmulationMxfp4LinearKernel.can_implement` gates on `has_quark()`,
121
# which we are not testing here.
122
monkeypatch.setattr(
@@ -137,8 +134,7 @@ def test_emulation_kernel_accepts_any_config(activation_quant_key, monkeypatch):
134
135
def test_emulation_kernel_derives_quant_dequant_func_from_config(monkeypatch):
136
"""quant_dequant_func must be derived purely from the config's activation
140
- QuantKey, not set externally.
141
- """
137
+ QuantKey, not set externally."""
138
# `EmulationMxfp4LinearKernel.can_implement` gates on `has_quark()`,
139
# which we are not testing here.
140
monkeypatch.setattr(
@@ -162,8 +158,7 @@ def test_emulation_kernel_derives_quant_dequant_func_from_config(monkeypatch):
158
159
def test_aiter_kernel_is_supported_requires_native_mx_support():
160
"""AiterMxfp4LinearKernel must not be selected on platforms without
165
- native MX compute, even if AITER itself is importable.
166
- """
161
+ native MX compute, even if AITER itself is importable."""
162
with patch(
163
"vllm.model_executor.kernels.linear.mxfp4.aiter.current_platform.supports_mx",
164
return_value=False,
@@ -199,8 +194,7 @@ class OOTMxFp4LinearKernel(MxFp4LinearKernel):
194
@patch("vllm.model_executor.kernels.linear.current_platform")
195
def test_init_mxfp4_linear_kernel_dispatches_to_registered_kernel(platform_mock):
196
"""init_mxfp4_linear_kernel should select a registered kernel that
202
- reports itself as supported, and construct it with a fresh config.
203
- """
197
+ reports itself as supported, and construct it with a fresh config."""
198
platform_mock._enum = PlatformEnum.OOT
199
register_linear_kernel(OOTMxFp4LinearKernel, PlatformEnum.OOT, "mxfp4")
200
tests/kernels/quantization/test_mxfp4_triton_ep.py
+1
-2
@@ -16,8 +16,7 @@ import torch
16
17
class TestTritonMoeForwardExpertMap:
18
"""Test that triton_kernel_moe_forward applies expert_map remapping
19
- when expert_map is provided (EP active).
20
- """
19
+ when expert_map is provided (EP active)."""
20
21
def test_expert_map_remap(self):
22
device = "cuda" if torch.cuda.is_available() else "cpu"
tests/kernels/quantization/test_mxfp6_kernel_selection.py
+3
-6
@@ -41,8 +41,7 @@ def test_can_implement_is_abstract():
41
42
def test_emulation_kernel_rejects_non_mxfp6_weights():
43
"""EmulationMxfp6LinearKernel must not implement a non-MXFP6 weight
44
- format.
45
- """
44
+ format."""
45
config = MxFp6LinearLayerConfig(weight_quant_key=kMxfp4Static)
46
can_implement, reason = EmulationMxfp6LinearKernel.can_implement(config)
47
assert not can_implement
@@ -58,8 +57,7 @@ def test_emulation_kernel_accepts_any_supported_config(
57
weight_quant_key, activation_quant_key
58
):
59
"""EmulationMxfp6LinearKernel is the only backend today: it must accept
61
- every supported weight/activation format combination.
62
- """
60
+ every supported weight/activation format combination."""
61
config = MxFp6LinearLayerConfig(
62
weight_quant_key=weight_quant_key, activation_quant_key=activation_quant_key
63
)
@@ -104,8 +102,7 @@ class OOTMxFp6LinearKernel(MxFp6LinearKernel):
102
def test_init_mxfp6_linear_kernel_dispatches_to_registered_kernel(platform_mock):
103
"""init_mxfp6_linear_kernel should select a registered kernel that
104
reports itself as supported/able to implement the given config, and
107
- construct it with that exact config.
108
- """
105
+ construct it with that exact config."""
106
platform_mock._enum = PlatformEnum.OOT
107
register_linear_kernel(OOTMxFp6LinearKernel, PlatformEnum.OOT, "mxfp6")
108
tests/kernels/quantization/test_per_token_group_quant.py
+3
-6
@@ -118,8 +118,7 @@ def test_per_token_group_quant_fp8_packed(
118
num_tokens, hidden_dim, group_size, poisoned_scales
119
):
120
"""Test the packed DeepGEMM quantization kernel against the Triton
121
- reference (row-major, UE8M0 scales).
122
- """
121
+ reference (row-major, UE8M0 scales)."""
122
device = "cuda"
123
torch.manual_seed(42)
124
@@ -257,8 +256,7 @@ def test_per_token_group_quant_fp8_packed_all_zero():
256
def test_per_token_group_quant_fp8_packed_mantissa_rounds_up():
257
"""Inputs whose absmax/max_8bit produces a non-power-of-2 force the
258
mantissa-rounding-up branch (exp_byte += 1). Locks down this behavior
260
- before optimization.
261
- """
259
+ before optimization."""
260
device = "cuda"
261
num_tokens, hidden_dim, group_size = 4, 7168, 128
262
@@ -330,8 +328,7 @@ def test_per_token_group_quant_fp8_packed_zero_fills_padded_output_q(
328
):
329
"""When output_q is allocated with shape (tma_aligned_mn, k) instead of
330
(mn, k), the kernel must overwrite the padded mn rows with zeros so
333
- callers can use ``torch.empty`` instead of ``torch.zeros``.
334
- """
331
+ callers can use ``torch.empty`` instead of ``torch.zeros``."""
332
device = "cuda"
333
group_size = 128
334
torch.manual_seed(42)
tests/kernels/quantization/test_quantized_embedding.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Tests for the Triton dequant-gather kernel used by
4
-``CompressedTensorsEmbeddingWNA16Int`` (quantized embedding lookup).
5
-"""
4
+``CompressedTensorsEmbeddingWNA16Int`` (quantized embedding lookup)."""
5
6
import pytest
7
import torch
tests/kernels/quantization/test_rocm_aiter_grouped_quant.py
+2
-4
@@ -29,8 +29,7 @@ pytestmark = pytest.mark.skipif(
29
30
def test_rocm_aiter_group_fp8_quant_fake_implementation():
31
"""Test that the fake implementation is correctly
32
- defined for torch.ops.vllm.rocm_aiter_group_fp8_quant.
33
- """
32
+ defined for torch.ops.vllm.rocm_aiter_group_fp8_quant."""
33
# Create test tensors
34
M = 128
35
N = 4096
@@ -50,8 +49,7 @@ def test_rocm_aiter_group_fp8_quant_fake_implementation():
49
def test_rocm_aiter_group_fp8_quant_torch_compile_with_cudagraph():
50
"""Test that rocm_aiter_ops.group_fp8_quant
51
with group size 128 can be used with
53
- torch.compile in cudagraph mode.
54
- """
52
+ torch.compile in cudagraph mode."""
53
# Create test tensors
54
M = 128
55
N = 4096
tests/kernels/quantization/test_rocm_mxfp4.py
+1
-2
@@ -209,8 +209,7 @@ def test_rocm_aiter_fp4_enablement_follows_env_and_arch(
209
@pytest.mark.parametrize("shape", LLAMA_SHAPES)
210
def test_vllm_quant_dequant_mxfp4_matches_reference_on_large_shapes(shape, dtype):
211
"""The public vLLM MXFP4 QDQ helper should stay exact against the torch
212
- reference even on larger Llama-like shapes.
213
- """
212
+ reference even on larger Llama-like shapes."""
213
from vllm.model_executor.layers.quantization.utils.mxfp4_utils import (
214
quant_dequant_mxfp4,
215
)
tests/kernels/test_compressor_kv_cache.py
+3
-6
@@ -670,8 +670,7 @@ def test_v41_rope_insert_plain_row(compress_ratio: int, store_fp8: bool):
670
def test_v41_compressor_metadata_maps_tokens_to_their_ring():
671
"""The ring group's generic slot mapping is disabled (all PAD), so the
672
builder must map every real token to ``ring_block * capacity + pos %
673
- capacity`` and keep padding tokens at PAD.
674
- """
673
+ capacity`` and keep padding tokens at PAD."""
674
from unittest.mock import MagicMock
675
676
from vllm.models.deepseek_v41.compressor import CompressorMetadataBuilder
@@ -1096,8 +1095,7 @@ def test_get_c128_boundary(starts, query_start_loc, expected):
1095
@pytest.mark.parametrize("block_size", [16, 64])
1096
def test_deepseek_v4_attention_quant_cache_roundtrip(num_tokens: int, block_size: int):
1097
"""compressed_kv → quantize_and_insert_k_cache → dequantize_and_gather_k_cache
1099
- → compare against original.
1100
- """
1098
+ → compare against original."""
1099
HEAD_DIM = 512
1100
NOPE_DIM = 448
1101
HEAD_BYTES = 584 # 448 fp8 + 128 bf16 + 8 uint8 scale
@@ -1309,8 +1307,7 @@ def test_dequantize_and_gather_k_cache(
1307
@pytest.mark.parametrize("block_size", [16, 64])
1308
def test_indexer_quant_cache_roundtrip(num_tokens: int, block_size: int):
1309
"""K → indexer_k_quant_and_cache → cp_gather_indexer_k_quant_cache
1312
- → manual dequant → compare against original.
1313
- """
1310
+ → manual dequant → compare against original."""
1311
HEAD_DIM = 128
1312
QUANT_BLOCK_SIZE = 128
1313
# cache_stride = head_dim + (head_dim * 4 / quant_block_size) = 128 + 4 = 132
tests/kernels/test_cp_gather_fp8.py
+1
-2
@@ -432,8 +432,7 @@ def test_cp_gather_fp8_with_sequence_starts(gather_seq_lens, seq_starts):
432
)
433
def test_cp_gather_fp8_large_seqlens(seq_lens, block_size):
434
"""Correctness test with large sequence lengths matching benchmark
435
- scenarios (8K-128K prefill).
436
- """
435
+ scenarios (8K-128K prefill)."""
436
(
437
cache,
438
block_table,
tests/kernels/test_deepseek_v4_cpu_kernels.py
+19
-38
@@ -85,8 +85,7 @@ def _decode_token_regions(
85
cache: torch.Tensor, slot_mapping: torch.Tensor, block_size: int
86
):
87
"""Slice out, per valid token, the raw NoPE-fp8 / RoPE-bf16 / scale byte
88
- regions this layout defines.
89
- """
88
+ regions this layout defines."""
89
valid = slot_mapping >= 0
90
idx = valid.nonzero(as_tuple=True)[0]
91
slots = slot_mapping[idx]
@@ -111,8 +110,7 @@ def _assert_cache_parity(cache_fused, cache_ref, slot_mapping, block_size):
110
"""NoPE fp8 + the UE8M0 scale byte are a deterministic quant of an
111
un-rotated bf16 value, so they match tightly; the RoPE region is rotated
112
in fp32 before its bf16 store and eager/kernel can round a tie to
114
- opposite sides, so allow <=1 ULP there.
115
- """
113
+ opposite sides, so allow <=1 ULP there."""
114
nope_ref, rope_ref, scale_ref = _decode_token_regions(
115
cache_ref, slot_mapping, block_size
116
)
@@ -192,8 +190,7 @@ def _dup_padded_block_cache(
190
num_blocks: int, block_size: int, width: int, pad_elems: int
191
) -> tuple[torch.Tensor, torch.Tensor]:
192
"""Two independently-stored padded caches with identical values, for ops
195
- that mutate the cache in place.
196
- """
193
+ that mutate the cache in place."""
194
page_stride = block_size * width + pad_elems
195
template = torch.randn(num_blocks, page_stride, dtype=torch.float32)
196
@@ -210,8 +207,7 @@ def _run_save_partial_states_eager(
207
):
208
"""Reference: state_cache[block_idx, pos_in_block, :W] = kv;
209
state_cache[..., W:] = score + ape[position % compress_ratio]; skip
213
- slot < 0. Mutates state_cache in place, matching the op's contract.
214
- """
210
+ slot < 0. Mutates state_cache in place, matching the op's contract."""
211
state_width = kv.shape[-1]
212
block_size = state_cache.shape[1]
213
valid = slot_mapping >= 0
@@ -271,8 +267,7 @@ def _run_compress_eager(
267
):
268
"""Reference for the per-channel-softmax-pooling + RMSNorm + NoPE-UE8M0
269
quant + GPT-J RoPE math writing the main (head_dim=512) fp8_ds_mla
274
- layout.
275
- """
270
+ layout."""
271
num_tokens, window = gather_slots.shape
272
state_width = state_cache.shape[-1] // 2
273
state_block_size = state_cache.shape[1]
@@ -449,8 +444,7 @@ def test_compress_norm_rope_store_cpu_matches_eager(
444
445
def test_compress_norm_rope_store_cpu_non_contiguous_kv_cache_row_stride():
446
"""The main (output) kv_cache is a separate physical buffer from the
452
- state cache and can independently be a strided view.
453
- """
447
+ state cache and can independently be a strided view."""
448
eps = 1e-6
449
compress_ratio, overlap = 128, False
450
num_tokens = 5
@@ -526,8 +520,7 @@ def _run_compress_indexer_eager(
520
"""Same softmax-pool + RMSNorm + GPT-J RoPE prologue as the head=512
521
path, but the indexer's cache quantizes all 128 post-RoPE dims as one
522
FP8 block with a single raw fp32 scale per token (matching
529
- _indexer_k_quant_and_cache_cpu's layout), not 7 separate UE8M0 blocks.
530
- """
523
+ _indexer_k_quant_and_cache_cpu's layout), not 7 separate UE8M0 blocks."""
524
num_tokens, window = gather_slots.shape
525
state_width = state_cache.shape[-1] // 2
526
state_block_size = state_cache.shape[1]
@@ -655,8 +648,7 @@ def _pack_flash_mla_cache(kv_f32: torch.Tensor, block_size: int):
648
"""Quantize kv_f32 ([N, HEAD_DIM]) into the fp8_ds_mla byte layout and
649
return (cache, dequant_ref) -- the exact post-quantization value the
650
kernel's dequant should reproduce. Slot id == row index, packed
658
- contiguously from block 0.
659
- """
651
+ contiguously from block 0."""
652
n = kv_f32.shape[0]
653
num_blocks = max(1, -(-n // block_size))
654
cache = _make_cache(num_blocks, block_size)
@@ -714,8 +706,7 @@ def _flash_mla_eager(
706
"""MQA attention: gather the (already-dequantized) window+compressed KV
707
rows referenced by *_slots (-1 = invalid/masked), append a learned
708
per-head sink logit with zero value contribution, softmax, weighted
717
- sum.
718
- """
709
+ sum."""
710
num_tokens, num_heads, _ = q.shape
711
q_f32 = q.float()
712
@@ -814,8 +805,7 @@ def test_flash_mla_cpu_kernel_matches_eager(
805
806
def test_flash_mla_cpu_kernel_all_invalid_falls_back_to_sink():
807
"""When every KV slot is masked out, softmax degenerates to the sink
817
- logit alone and the output must be all-zero (no valid value rows).
818
- """
808
+ logit alone and the output must be all-zero (no valid value rows)."""
809
torch.manual_seed(2)
810
dtype = torch.bfloat16
811
num_tokens, num_heads, num_window = 3, 4, 5
@@ -855,8 +845,7 @@ def _qnorm_kv_insert_eager(
845
q, kv, positions, cache, slot_mapping, cos_sin_cache, q_head_padded, eps, bs
846
):
847
"""Reference: per-head weight-free RMSNorm + GPT-J RoPE on Q; GPT-J RoPE
858
- + UE8M0 FP8 quant + paged insert on KV.
859
- """
848
+ + UE8M0 FP8 quant + paged insert on KV."""
849
num_quant_blocks = NOPE_DIM // QUANT_BLOCK
850
851
num_tokens_full, num_heads_q, _ = q.shape
@@ -982,8 +971,7 @@ def test_qnorm_rope_kv_insert_cpu_kernel_matches_eager(
971
@pytest.mark.parametrize("pad", [1, 5])
972
def test_qnorm_rope_kv_insert_cpu_kernel_dp_padding(pad: int):
973
"""slot_mapping shorter than q/kv rows: the KV branch must only touch
985
- the first num_tokens rows while Q-norm+RoPE still runs on all rows.
986
- """
974
+ the first num_tokens rows while Q-norm+RoPE still runs on all rows."""
975
torch.manual_seed(1)
976
dtype = torch.bfloat16
977
eps = 1e-6
@@ -1044,8 +1032,7 @@ def _inverse_gptj_rope_o_proj_eager(
1032
rope_dim: int,
1033
) -> torch.Tensor:
1034
"""NoPE dims pass through as fp32; the RoPE segment is de-rotated by
1047
- R(-pos) in GPT-J (interleaved even/odd) convention.
1048
- """
1035
+ R(-pos) in GPT-J (interleaved even/odd) convention."""
1036
nope_dim = o.shape[-1] - rope_dim
1037
half_dim = rope_dim // 2
1038
@@ -1111,8 +1098,7 @@ def _write_page(
1098
) -> None:
1099
"""Write k_fp8 ([block_size, INDEXER_HEAD_DIM]) and scale ([block_size]
1100
fp32) into one page row: K-region then scale-region, matching
1114
- compress_norm_rope_store_indexer_cpu's layout.
1115
- """
1101
+ compress_norm_rope_store_indexer_cpu's layout."""
1102
k_region = page_row[: block_size * INDEXER_HEAD_DIM]
1103
k_region.copy_(k_fp8.view(torch.uint8).flatten())
1104
scale_region = page_row[block_size * INDEXER_HEAD_DIM :].view(torch.float32)
@@ -1148,8 +1134,7 @@ def _build_paged_mqa_logits_batch(
1134
):
1135
"""Fill pages (a pre-sized [n_pages, buf_width] uint8 tensor, possibly
1136
non-contiguous in dim 0) with deterministic-per-seed random K/scale
1151
- data.
1152
- """
1137
+ data."""
1138
torch.manual_seed(seed)
1139
batch_size = len(seq_lens)
1140
max_seq_len = max(seq_lens)
@@ -1215,8 +1200,7 @@ def test_fp8_paged_mqa_logits_cpu_non_contiguous_kv_cache_row_stride():
1200
"""The paged K-cache in production is a per-layer view into a shared
1201
multi-layer allocation, so its page stride generally exceeds the page
1202
byte width -- check the kernel reads a padded/strided buffer identically
1218
- to an equivalent tightly-packed one.
1219
- """
1203
+ to an equivalent tightly-packed one."""
1204
block_size = 64
1205
num_heads = 4
1206
seq_lens = [1, block_size + 7, 3 * block_size]
@@ -1342,8 +1326,7 @@ def test_fused_indexer_q_rope_quant_dispatches_to_cpu_kernel():
1326
CPU op on a CPU tensor, not silently fall through to the Triton kernel
1327
(which would also "work" under triton-cpu, masking a dispatch
1328
regression). The dispatcher does its CPU import inside the CPU branch,
1345
- so the patch target is the source module.
1346
- """
1329
+ so the patch target is the source module."""
1330
torch.manual_seed(0)
1331
num_tokens = 1
1332
@@ -1410,8 +1393,7 @@ def _hc_head_torch(
1393
) -> torch.Tensor:
1394
"""Eager reference for hc_head_fused_cpu: round-trips the RMSNorm
1395
output through bf16 before the linear, matching the kernel's bf16
1413
- arithmetic.
1414
- """
1396
+ arithmetic."""
1397
hc_mult, hidden_size = hidden_states.shape[-2:]
1398
outer_shape = hidden_states.shape[:-2]
1399
hs_flat = hidden_states.reshape(-1, hc_mult, hidden_size)
@@ -1493,8 +1475,7 @@ def test_mhc_post_cpu(num_tokens: int, hidden_size: int):
1475
@pytest.mark.parametrize("hidden_size", [4096, 7168])
1476
def test_hc_head_cpu(num_tokens: int, hidden_size: int):
1477
"""hc_head_fused_cpu vs. the _hc_head_torch eager reference it
1496
- replaces.
1497
- """
1478
+ replaces."""
1479
torch.set_default_device(DEVICE)
1480
set_random_seed(0)
1481
hc_mult = 4
tests/kernels/test_engram.py
+3
-6
@@ -383,8 +383,7 @@ def _hash_ids(requests, tables_meta, block_table, cache=None, capture=False):
383
"""Run the op on a batch of (token_ids, start, window) requests; `window`
384
is the runner's [depth] lookback for that request (None = all unknown).
385
Token IDs 14 and 22 stand in for image tokens that break n-grams.
386
- Returns one [len(token_ids), ...] hash tensor per request.
387
- """
386
+ Returns one [len(token_ids), ...] hash tensor per request."""
387
token_map, multipliers, primes, offsets, block_size = tables_meta
388
depth = multipliers.shape[1] - 1
389
@@ -443,8 +442,7 @@ def test_lookback_window_reproduces_single_instance(runner, capture):
442
V2 supplies every lookback from its device token history and needs no
443
slot cache. V1 supplies prompt positions only and reads generated
444
positions from the slot cache it fills itself. Without any window the
446
- first decode token hashes stale slots (negative control).
447
- """
445
+ first decode token hashes stale slots (negative control)."""
446
block_size = 4
447
block_table = torch.tensor(
448
[[3, 1, 5, 0], [2, 4, 6, 7]], dtype=torch.int32, device="cuda"
@@ -710,8 +708,7 @@ def test_engram_lookup_reuses_jit_across_token_shapes():
708
def test_engram_lookup_matches_torch(cpu_offload, background, num_tokens):
709
"""The fused gather must be bit-exact with the torch dequant path it
710
replaces, from HBM and from pinned host memory alike, and must contribute
713
- zeros for rows another TP rank owns.
714
- """
711
+ zeros for rows another TP rank owns."""
712
layer = _make_embedding(cpu_offload)
713
cols, rows = 24, layer.part_num_embeddings
714
ids = torch.randint(0, rows, (num_tokens, cols), dtype=torch.int32, device="cuda")
tests/kernels/test_fla_layernorm_guard.py
+1
-2
@@ -336,8 +336,7 @@ def test_layer_norm_rows_per_block(
336
@torch.inference_mode()
337
def test_strided_input(dtype: torch.dtype) -> None:
338
"""Test that the kernel handles non-contiguous (strided)
339
- inputs correctly.
340
- """
339
+ inputs correctly."""
340
set_random_seed(42)
341
device = torch.device(DEVICE)
342
num_tokens = 128
tests/kernels/test_fp32_router_gemm.py
+1
-2
@@ -97,8 +97,7 @@ def test_topk_routing_consistency(num_tokens: int, hidden_dim: int, num_experts:
97
"""The gate feeds top-k expert selection: the kernel's top-8 must match
98
an fp64 reference's top-8 per token (ties tolerated). This is the
99
business-level correctness of the router — numeric error only matters
100
- if it flips the argsort.
101
- """
100
+ if it flips the argsort."""
101
_requires_sm90()
102
top_k = 8
103
device = torch.device("cuda")
tests/kernels/test_fused_deepseek_v32_norm_rope.py
+1
-2
@@ -854,8 +854,7 @@ def test_fused_q_no_indexer(num_tokens: int):
854
@pytest.mark.parametrize("has_indexer", [True, False])
855
def test_fused_q_bf16_query(num_tokens: int, has_indexer: bool):
856
"""bf16-query path (FlashMLA sparse, SM90/SM100): only the RoPE'd q_pe is
857
- produced (bf16, unquantized); ql_nope is consumed directly by the caller.
858
- """
857
+ produced (bf16, unquantized); ql_nope is consumed directly by the caller."""
858
torch.manual_seed(6)
859
dev = "cuda"
860
max_pos = 8192
tests/kernels/test_fused_deepseek_v4_qnorm_rope_kv_insert.py
+2
-4
@@ -176,8 +176,7 @@ def _call_fused(
176
177
def _as_stored_fp8(t: torch.Tensor) -> torch.Tensor:
178
"""Reinterpret a float8_e4m3fn-typed kernel output under the real (FNUZ on
179
- gfx942) encoding the kernel actually wrote, without touching the bytes.
180
- """
179
+ gfx942) encoding the kernel actually wrote, without touching the bytes."""
180
return t.contiguous().view(torch.uint8).view(FP8_STORE_DTYPE)
181
182
@@ -713,8 +712,7 @@ def test_q_interleaved_is_orthogonal_to_norm_and_rope(
712
@pytest.mark.parametrize("block_size", [16, 64])
713
def test_kv_path_with_dp_padding(num_tokens: int, pad: int, block_size: int):
714
"""slot_mapping.size(0) < q.size(0): the kernel must skip padded
716
- tokens in the KV branch while still processing Q on all rows.
717
- """
715
+ tokens in the KV branch while still processing Q on all rows."""
716
torch.manual_seed(3)
717
device = "cuda"
718
dtype = torch.bfloat16
tests/kernels/test_fused_indexer_q_rope_quant.py
+1
-2
@@ -574,8 +574,7 @@ def test_indexer_k_store_roundtrips_through_rocm_gather(block_size, compress_rat
574
def test_fused_indexer_q_rope_quant_writes_bf16_weights(use_cutedsl):
575
"""The MXFP4 path can emit the per-head weights in bf16 (what DeepGEMM's
576
sparse MQA-logits kernels take) instead of fp32; the values are the fp32
577
- result rounded once, so the scoring kernel needs no cast.
578
- """
577
+ result rounded once, so the scoring kernel needs no cast."""
578
if use_cutedsl and not has_cutedsl():
579
pytest.skip("cutedsl (cutlass) not installed")
580
tests/kernels/test_fused_inv_rope_fp8_quant.py
+3
-6
@@ -446,8 +446,7 @@ def test_output_strides(num_tokens, num_heads, n_groups):
446
def test_per_group_contiguity(num_tokens):
447
"""FP8 per-group slices must be contiguous. Scale per-group slices
448
are column-major (T-stride=1) — not row-major contiguous, which is
449
- correct for TMA loads.
450
- """
449
+ correct for TMA loads."""
450
num_heads, n_groups = 64, 8
451
heads_per_group = num_heads // n_groups
452
max_pos = 4096
@@ -513,8 +512,7 @@ def test_scales_are_power_of_two():
512
def test_nope_dims_unchanged():
513
"""Nope dimensions (first 448 per head) should only be quantized,
514
not rotated. Verify by dequantizing and comparing against
516
- quantize-only reference (no RoPE).
517
- """
515
+ quantize-only reference (no RoPE)."""
516
num_tokens, num_heads, n_groups = 16, 64, 8
517
heads_per_group = num_heads // n_groups
518
max_pos = 4096
@@ -905,8 +903,7 @@ def test_einsum_end_to_end(num_tokens, num_heads, n_groups):
903
@torch.inference_mode()
904
def test_with_real_deepseek_v4_rope(num_tokens, default_vllm_config):
905
"""Test with real DeepseekV4ScalingRotaryEmbedding (GPT-J style,
908
- mscale=0, YaRN scaling) matching the production config.
909
- """
906
+ mscale=0, YaRN scaling) matching the production config."""
907
num_heads = 64
908
n_groups = 8
909
heads_per_group = num_heads // n_groups
tests/kernels/test_mhc_kernels.py
+2
-4
@@ -1372,8 +1372,7 @@ def _patch_first_rank_pp_group(monkeypatch):
1372
1373
def test_deepseek_v4_mhc_broadcast_finalize_sums_hc_streams(monkeypatch):
1374
"""First finalize (at the end of load_weights) allocates
1375
- hc_attn_fn_broadcast as hc_attn_fn summed over hc streams.
1376
- """
1375
+ hc_attn_fn_broadcast as hc_attn_fn summed over hc streams."""
1376
_patch_first_rank_pp_group(monkeypatch)
1377
layer = _make_mhc_decoder_layer(hc_mult=2, hidden_size=8)
1378
model = SimpleNamespace(start_layer=0, end_layer=1, layers=[layer])
@@ -1388,8 +1387,7 @@ def test_deepseek_v4_mhc_broadcast_finalize_sums_hc_streams(monkeypatch):
1387
def test_deepseek_v4_mhc_broadcast_refit_refreshes_in_place(monkeypatch):
1388
"""Re-finalizing after a weight refit must copy into the existing
1389
broadcast tensor so its address stays stable for captured CUDA graphs,
1391
- while picking up the new hc_attn_fn values.
1392
- """
1390
+ while picking up the new hc_attn_fn values."""
1391
_patch_first_rank_pp_group(monkeypatch)
1392
layer = _make_mhc_decoder_layer(hc_mult=2, hidden_size=8)
1393
model = SimpleNamespace(start_layer=0, end_layer=1, layers=[layer])
tests/kernels/test_minimax_m3_amd_ops.py
+4
-8
@@ -403,8 +403,7 @@ def test_mxfp8_linear_emulation_bf16_at_load(
403
):
404
"""EmulationMxfp8LinearKernel load-time BF16 dequant (default) and the
405
``VLLM_MXFP8_EMULATION_DEQUANT_AT_LOAD=0`` per-step fallback must produce the
406
- same result; the dtype-match (BF16/FP16 activations) must also hold.
407
- """
406
+ same result; the dtype-match (BF16/FP16 activations) must also hold."""
407
from vllm.model_executor.kernels.linear.mxfp8.emulation import (
408
EmulationMxfp8LinearKernel,
409
)
@@ -518,8 +517,7 @@ def test_mxfp8_rocm_native_unaligned_k_dequantizes_at_load(shape):
517
# produced EP garbage).
518
def _capture_expert_mask(expert_mask, *, global_num_experts):
519
"""Drive the real ``AiterMxfp8Experts.apply`` mask branch and capture the
521
- ``expert_mask`` it forwards to ``rocm_aiter_ops.fused_moe``.
522
- """
520
+ ``expert_mask`` it forwards to ``rocm_aiter_ops.fused_moe``."""
521
from types import SimpleNamespace
522
from unittest import mock
523
@@ -570,8 +568,7 @@ def _capture_expert_mask(expert_mask, *, global_num_experts):
568
@pytest.mark.skipif(not current_platform.is_rocm(), reason="ROCm only")
569
def test_aiter_mxfp8_apply_forwards_expert_mask_unchanged():
570
"""AiterMxfp8Experts.apply forwards the precomputed 0/1 mask to aiter as-is
573
- (no re-derivation that would collapse an already-0/1 mask to all-ones).
574
- """
571
+ (no re-derivation that would collapse an already-0/1 mask to all-ones)."""
572
# 0/1 local-expert mask over global ids + trailing sentinel (rank owns 0..3).
573
ep_mask = torch.tensor(
574
[1, 1, 1, 1, 0, 0, 0, 0, 0], dtype=torch.int32, device=DEVICE
@@ -585,8 +582,7 @@ def test_aiter_mxfp8_apply_forwards_expert_mask_unchanged():
582
def test_routed_experts_expert_map_delegates_to_kernel():
583
"""RoutedExperts.expert_map returns the 0/1 mask only for kernels that set
584
``consumes_expert_mask`` (AITER), and the canonical -1 map otherwise -- keyed
588
- on the resolved kernel, not the global aiter switch.
589
- """
585
+ on the resolved kernel, not the global aiter switch."""
586
from types import SimpleNamespace
587
588
from vllm.model_executor.layers.fused_moe.routed_experts import RoutedExperts
tests/kernels/test_shuffle_rows.py
+2
-4
@@ -17,8 +17,7 @@ from vllm.platforms import current_platform
17
@pytest.mark.parametrize("dtype", [torch.float16, torch.bfloat16, torch.float32])
18
def test_shuffle_rows_basic(num_tokens: int, hidden_size: int, dtype: torch.dtype):
19
"""Test basic functionality of shuffle_rows with various tensor sizes and
20
- dtypes.
21
- """
20
+ dtypes."""
21
if not current_platform.is_cuda():
22
pytest.skip("shuffle_rows requires CUDA")
23
@@ -73,8 +72,7 @@ def test_shuffle_rows_permutation(
72
@pytest.mark.parametrize("hidden_size", [256, 512])
73
def test_shuffle_rows_expansion(num_tokens: int, hidden_size: int):
74
"""Test shuffle_rows with expansion (more output tokens than input
76
- tokens).
77
- """
75
+ tokens)."""
76
if not current_platform.is_cuda():
77
pytest.skip("shuffle_rows requires CUDA")
78
tests/kernels/test_top_k_per_row.py
+2
-4
@@ -1740,8 +1740,7 @@ def test_sparse_indexer_decode_topk_explicit_backends(
1740
) -> None:
1741
"""Every explicit sparse-indexer decode top-k backend must restrict each
1742
row to its seq_len (dirty data past the end must never be selected) and
1743
- match torch.topk on the valid region.
1744
- """
1743
+ match torch.topk on the valid region."""
1744
from vllm.config import VllmConfig, set_current_vllm_config
1745
from vllm.model_executor.layers.indexer_topk import SparseIndexerTopk
1746
@@ -1812,8 +1811,7 @@ def test_sparse_indexer_decode_topk_short_seq_lens(
1811
backend: str, workspace_init
1812
) -> None:
1813
"""seq_len < next_n: derived per-row ends must clamp at 0 (the reference
1815
- kernels do max(0, ...)); negative ends are OOB for the ragged kernels.
1816
- """
1814
+ kernels do max(0, ...)); negative ends are OOB for the ragged kernels."""
1815
from vllm.config import VllmConfig, set_current_vllm_config
1816
from vllm.model_executor.layers.indexer_topk import SparseIndexerTopk
1817
tests/lora/test_default_mm_loras.py
+1
-2
@@ -132,8 +132,7 @@ def test_default_mm_lora_fails_with_overridden_lora_request(
132
monkeypatch: pytest.MonkeyPatch,
133
):
134
"""Ensure that if the lora_request conflicts with default_mm_loras,
135
- we use the lora_request.
136
- """
135
+ we use the lora_request."""
136
run_test(
137
vllm_runner,
138
audio_assets,
tests/lora/test_fused_moe_lora_kernel.py
+2
-4
@@ -1123,8 +1123,7 @@ def test_fused_moe_lora_kernel_one_shot_early_exit(trigger, device):
1123
@pytest.mark.parametrize("device", DEVICES)
1124
def test_fused_moe_lora_kernel_zero_grid_no_crash(device):
1125
"""num_active_loras=0 (or num_slices=0) would otherwise launch a grid
1126
- with a zero dimension. one-shot wrapper must short-circuit before launch.
1127
- """
1126
+ with a zero dimension. one-shot wrapper must short-circuit before launch."""
1127
torch.set_default_device(device)
1128
set_random_seed(0)
1129
num_tokens, top_k, E, max_loras, R, K, N = 8, 2, 8, 4, 16, 1024, 1024
@@ -1186,8 +1185,7 @@ def test_fused_moe_lora_kernel_zero_grid_no_crash(device):
1185
def test_fused_moe_lora_kernel_rejects_bad_block_size_m(device):
1186
"""one-shot must surface a clear assertion when shrink_block_size_m is not
1187
a power of 2 / less than 16, instead of the cryptic Triton compile
1189
- failure (`arange's range must be a power of 2`).
1190
- """
1188
+ failure (`arange's range must be a power of 2`)."""
1189
torch.set_default_device(device)
1190
set_random_seed(0)
1191
num_tokens, top_k, E, max_loras, R, K, N = 32, 2, 8, 4, 16, 1024, 1024
tests/lora/test_moe_lora_align_sum.py
+2
-4
@@ -249,8 +249,7 @@ def _build_and_run_align(
249
)
250
def test_moe_lora_align_block_size_mixed_base_and_lora(max_loras):
251
"""Regression test for issue #32235: real LoRA slot must not be skipped
252
- when ``active_lora_ids`` has -1 at position 0.
253
- """
252
+ when ``active_lora_ids`` has -1 at position 0."""
253
out = _build_and_run_align(
254
num_lora_tokens=8, num_base_tokens=8, max_loras=max_loras
255
)
@@ -289,8 +288,7 @@ def test_moe_lora_align_block_size_disabled_adapter_untouched():
288
kernels. Pins the invariant protected by the ``adapter_enabled`` guard
289
in ``lora_count_and_sort_expert_tokens_kernel``: without it the sort
290
kernel reads uninitialized ``token_mask`` values for disabled slots and
292
- pollutes ``sorted_token_ids`` / ``cumsum_buffer``.
293
- """
291
+ pollutes ``sorted_token_ids`` / ``cumsum_buffer``."""
292
max_loras = 1
293
out = _build_and_run_align(
294
num_lora_tokens=16,
tests/lora/test_moe_lora_ep_load.py
+2
-4
@@ -19,8 +19,7 @@ NON_EXPERT_MODULES = ("q_proj", "k_proj", "v_proj", "o_proj", "gate")
19
20
def _expected_lora_modules() -> set[str]:
21
"""Replicate the set ``WorkerLoRAManager._load_adapter`` would build
22
- from this model's ``packed_modules_mapping``.
23
- """
22
+ from this model's ``packed_modules_mapping``."""
23
expected: set[str] = set(NON_EXPERT_MODULES)
24
for expert in range(GLOBAL_NUM_EXPERTS):
25
for proj in EXPERT_PROJECTIONS:
@@ -43,8 +42,7 @@ def _load(lora_dir, peft_helper, *, moe_ep_spec, lora_id):
42
def test_moe_lora_ep2_real_qwen3moe(qwen3moe_lora_files, ep_rank):
43
"""ep_size=2 against the real Qwen3-MoE adapter: each rank's loaded
44
LoRA has the right size, the right expert membership, and the
46
- right tensor values.
47
- """
45
+ right tensor values."""
46
peft_helper = PEFTHelper.from_local_dir(
47
qwen3moe_lora_files, max_position_embeddings=4096
48
)
tests/lora/test_punica_ops.py
+2
-4
@@ -45,8 +45,7 @@ def _bgmv_shrink(
45
inputs, lora_weight, output, seq_len_tensor, lora_indices, scaling=1.0
46
):
47
"""Memory-efficient shrink reference: per-LoRA matmul loop.
48
- output[mask] = scaling * inputs[mask] @ weight.T
49
- """
48
+ output[mask] = scaling * inputs[mask] @ weight.T"""
49
exploded = torch.repeat_interleave(lora_indices, seq_len_tensor)
50
for lid in exploded.unique():
51
if lid < 0:
@@ -67,8 +66,7 @@ def _bgmv_expand(
66
add_inputs=False,
67
):
68
"""Memory-efficient expand reference: per-LoRA matmul loop.
70
- output[mask, offset:offset+n] (+)= inputs[mask] @ weight.T
71
- """
69
+ output[mask, offset:offset+n] (+)= inputs[mask] @ weight.T"""
70
exploded = torch.repeat_interleave(lora_indices, seq_len_tensor)
71
for lid in exploded.unique():
72
if lid < 0:
tests/lora/test_punica_ops_fp8.py
+2
-4
@@ -877,8 +877,7 @@ def test_lora_shrink_fp8(
877
quant_mode: str,
878
):
879
"""Test FP8 shrink kernel with per-tensor, per-channel, and block-wise
880
- quantization, comparing against the bf16 baseline.
881
- """
880
+ quantization, comparing against the bf16 baseline."""
881
torch.set_default_device(device)
882
set_random_seed(seed)
883
@@ -933,8 +932,7 @@ def test_lora_expand_fp8(
932
quant_mode: str,
933
):
934
"""Test FP8 expand kernel with per-tensor, per-channel, and block-wise
936
- quantization, comparing against the bf16 baseline.
937
- """
935
+ quantization, comparing against the bf16 baseline."""
936
torch.set_default_device(device)
937
set_random_seed(seed)
938
tests/model_executor/layers/test_fused_shared_expert.py
+2
-4
@@ -1319,8 +1319,7 @@ def test_fp8_shared_expert_fse_allows_symmetric_ignored_layers() -> None:
1319
1320
def test_fp8_shared_expert_fse_expands_packed_projections() -> None:
1321
"""Both shards of a fused projection ignored is symmetric within that
1322
- projection, so the mismatch reported is against the routed experts.
1323
- """
1322
+ projection, so the mismatch reported is against the routed experts."""
1323
quant_config = _fp8_config(
1324
ignored_layers=[
1325
"model.layers.0.mlp.shared_experts.gate_proj",
@@ -1344,8 +1343,7 @@ def test_fp8_shared_expert_fse_expands_packed_projections() -> None:
1343
1344
def test_fp8_shared_expert_fse_propagates_partial_shard_exclusion() -> None:
1345
"""Half a fused projection excluded is rejected by `is_layer_skipped`
1347
- itself, exactly as it is in `Fp8Config.get_quant_method`.
1348
- """
1346
+ itself, exactly as it is in `Fp8Config.get_quant_method`."""
1347
quant_config = _fp8_config(
1348
ignored_layers=["model.layers.0.mlp.shared_experts.gate_proj"]
1349
)
tests/model_executor/layers/test_mla_short_prefill_indexer.py
+12
-24
@@ -346,8 +346,7 @@ def test_deepseek_v32_dispatches_selected_mha(
346
def test_select_candidate_blocks_tolerates_empty_rows():
347
"""Full-cudagraph decode pads the batch with seq_len-0 rows. The newest
348
block pin must not index -1 for them (device-side assert); they select
349
- no candidate blocks and real rows still pin their newest block.
350
- """
349
+ no candidate blocks and real rows still pin their newest block."""
350
block_size, topk_blocks = 8, 3
351
logits = torch.zeros(3, 64, device="cuda")
352
logits[0, 3] = 5.0 # block 0 scores highest for row 0
@@ -458,8 +457,7 @@ def test_candidate_kernels_preserve_packed_bounds_and_padding(
457
458
def _make_candidates(lens: torch.Tensor, num_candidates: int, cbk: int):
459
"""Production-faithful candidates: top min(avail, K) blocks per row —
461
- full coverage for lens <= K*cbk, a fixed-size subset beyond that.
462
- """
460
+ full coverage for lens <= K*cbk, a fixed-size subset beyond that."""
461
avail = ((lens.cpu() + cbk - 1) // cbk).tolist()
462
rows = []
463
for a in avail:
@@ -495,8 +493,7 @@ def _candidate_token_mask(
493
494
def _reference_topk(masked: torch.Tensor, topk: int) -> torch.Tensor:
495
"""Plain ``torch.topk`` over -inf-masked logits; slots past a row's valid
498
- count are -1 (the indexer's "no token" sentinel).
499
- """
496
+ count are -1 (the indexer's "no token" sentinel)."""
497
values, indices = masked.topk(topk, dim=1)
498
return torch.where(values > float("-inf"), indices.int(), -1)
499
@@ -509,8 +506,7 @@ def _assert_same_selection(
506
) -> None:
507
"""Both top-k index sets must pick the same multiset of logit values per
508
row (-1 padding must match too). Indices themselves may differ: the
512
- top-k kernels break ties among equal values in nondeterministic order.
513
- """
509
+ top-k kernels break ties among equal values in nondeterministic order."""
510
for r in range(logits.shape[0]):
511
base = int(row_starts[r]) if row_starts is not None else 0
512
g, e = got[r][got[r] >= 0], expected[r][expected[r] >= 0]
@@ -522,8 +518,7 @@ def _assert_same_selection(
518
519
def _sparse_scratch(rows: int, num_sparse: int, topk: int) -> dict:
520
"""Caller-owned buffers the sparse path writes into (the metadata builder
525
- owns these in production).
526
- """
521
+ owns these in production)."""
522
i32 = dict(dtype=torch.int32, device="cuda")
523
return dict(
524
sparse_indices=torch.zeros(rows, num_sparse, **i32),
@@ -538,8 +533,7 @@ def _expand_candidates_reference(
533
"""PyTorch reference for `candidate_blocks_to_sparse_indices`: expand
534
each candidate block into ``cbk // sbk`` sparse blocks, keep those inside
535
``[0, ke - ks)``, sort ascending, anchor at ``ks // sbk``, pad by
541
- repeating the last valid block, and count the valid sparse columns.
542
- """
536
+ repeating the last valid block, and count the valid sparse columns."""
537
ratio = cbk // sbk
538
rows, num_candidates = candidates.shape
539
num_sparse = num_candidates * ratio
@@ -565,8 +559,7 @@ def _expand_candidates_reference(
559
@pytest.mark.skipif(not torch.cuda.is_available(), reason="Triton kernel")
560
def test_candidate_blocks_to_sparse_indices_math():
561
"""Candidate->sparse-block expansion: ks anchoring, range filtering,
568
- repeat-last padding, and the per-row valid column count (``end``).
569
- """
562
+ repeat-last padding, and the per-row valid column count (``end``)."""
563
from vllm.model_executor.kernels.attention.dsa.sparse_mqa_logits import (
564
candidate_blocks_to_sparse_indices,
565
)
@@ -618,8 +611,7 @@ def test_candidate_blocks_to_sparse_indices_math():
611
def test_candidate_blocks_to_sparse_indices_matches_reference(cbk: int, sbk: int):
612
"""The Triton expansion equals the PyTorch reference on production-shaped
613
random inputs, including strided (column-sliced) candidate rows and
621
- strided output buffers.
622
- """
614
+ strided output buffers."""
615
from vllm.model_executor.kernels.attention.dsa.sparse_mqa_logits import (
616
candidate_blocks_to_sparse_indices,
617
)
@@ -689,8 +681,7 @@ def test_sparse_mqa_logits_prefill_matches_dense_masked(capture: bool):
681
``torch.topk`` over dense bf16 logits masked to the candidates (the two
682
DeepGEMM kernels agree bitwise on candidate columns), incl. under CUDA
683
graph capture, and a later layer reusing the step's expansion/schedule
692
- selects the same values.
693
- """
684
+ selects the same values."""
685
deep_gemm = _skip_unless_sm100_sparse_kernels()
686
from vllm.model_executor.kernels.attention.dsa.sparse_mqa_logits import (
687
sparse_mqa_logits_prefill_chunk,
@@ -780,8 +771,7 @@ def test_sparse_mqa_logits_prefill_matches_dense_masked(capture: bool):
771
772
def _build_fp4_paged_cache(req_lens: torch.Tensor, page_kv: int, head_dim: int):
773
"""MXFP4 paged cache in DeepGEMM's fused layout: per page, all tokens'
783
- fp4 data first, then their packed UE8M0 scales.
784
- """
774
+ fp4 data first, then their packed UE8M0 scales."""
775
device = req_lens.device
776
pages_per = (req_lens + page_kv - 1) // page_kv
777
num_pages, max_pages = int(pages_per.sum()), int(pages_per.max())
@@ -817,8 +807,7 @@ def test_sparse_mqa_logits_paged_matches_dense_masked(next_n: int, capture: bool
807
"""Paged sparse-MQA decode selects exactly the values ``torch.topk`` picks
808
from the dense bf16 masked logits, incl. MTP rows (next_n > 1 flattened to
809
one query row each), CUDA graph capture/replay and schedule reuse by a
820
- later layer.
821
- """
810
+ later layer."""
811
deep_gemm = _skip_unless_sm100_sparse_kernels()
812
from vllm.model_executor.kernels.attention.dsa.sparse_mqa_logits import (
813
sparse_mqa_logits_paged_decode,
@@ -927,8 +916,7 @@ def test_sparse_mqa_logits_paged_matches_dense_masked(next_n: int, capture: bool
916
917
def test_sparse_mqa_logits_accuracy_vs_torch():
918
"""Sparse-kernel numerics vs a PyTorch fp32 reference on the dequantized
930
- MXFP4 inputs.
931
- """
919
+ MXFP4 inputs."""
920
_skip_unless_sm100_sparse_kernels()
921
from deep_gemm.utils import cast_back_from_fp4
922
tests/model_executor/model_loader/test_ep_weight_filter.py
+3
-6
@@ -232,8 +232,7 @@ class TestShouldSkipWeight:
232
233
class TestSafetensorsWeightsIteratorWithEpFilter:
234
"""Verify that EP filtering produces a strict subset of unfiltered loading
235
- and that all expected dense + local expert weights are present.
236
- """
235
+ and that all expected dense + local expert weights are present."""
236
237
@pytest.fixture(scope="class")
238
def gpt2_files(self):
@@ -263,8 +262,7 @@ class TestSafetensorsWeightsIteratorWithEpFilter:
262
263
def test_empty_filter_skips_experts_only(self, gpt2_files):
264
"""GPT-2 has no expert weights, so even an empty local_expert_ids
266
- set should return all weights (all are dense).
267
- """
265
+ set should return all weights (all are dense)."""
266
all_weights = dict(safetensors_weights_iterator(gpt2_files, False))
267
filtered_weights = dict(
268
safetensors_weights_iterator(gpt2_files, False, local_expert_ids=set())
@@ -275,8 +273,7 @@ class TestSafetensorsWeightsIteratorWithEpFilter:
273
274
class TestEpFilterOnSyntheticMoeWeights:
275
"""Create synthetic safetensors files with expert-like naming and verify
278
- that the filter correctly skips non-local experts.
279
- """
276
+ that the filter correctly skips non-local experts."""
277
278
@pytest.fixture
279
def synthetic_moe_files(self, tmp_path):
tests/model_executor/model_loader/test_reload.py
+3
-6
@@ -350,8 +350,7 @@ def test_marlin_post_load_preserves_runtime_tensor_addresses(monkeypatch, dist_i
350
@pytest.mark.parametrize("variant", ["fp8", "mxfp8", "nvfp4"])
351
def test_marlin_prepare_layer_preserves_workspace_address(monkeypatch, variant):
352
"""The Marlin fallback prepare_* functions rerun on weight reload and must
353
- reuse the workspace storage whose address captured CUDA graphs hold.
354
- """
353
+ reuse the workspace storage whose address captured CUDA graphs hold."""
354
from vllm import _custom_ops as ops
355
from vllm.model_executor.layers.quantization.utils import (
356
marlin_utils,
@@ -429,8 +428,7 @@ def test_marlin_prepare_layer_preserves_workspace_address(monkeypatch, variant):
428
429
def test_marlin_make_workspace_new_rejects_incompatible_existing(monkeypatch):
430
"""An incompatible existing workspace means the address captured by CUDA
432
- graphs is already unusable; allocating a replacement would hide that.
433
- """
431
+ graphs is already unusable; allocating a replacement would hide that."""
432
from vllm.model_executor.layers.quantization.utils import marlin_utils
433
434
monkeypatch.setattr(marlin_utils, "num_compute_units", lambda _: 4)
@@ -611,8 +609,7 @@ class _RecordingQuantMethod(QuantizeMethodBase):
609
class _LateBiasLayer(torch.nn.Module):
610
"""Mimics an online-quantized linear: `weight` is created on meta by
611
`create_weights()`, which wraps the loaders, and the linear base registers
614
- `bias` afterwards.
615
- """
612
+ `bias` afterwards."""
613
614
def __init__(self, quant_method):
615
super().__init__()
tests/model_executor/test_deep_gemm_warmup.py
+2
-4
@@ -42,8 +42,7 @@ def _run_warmup(monkeypatch, layers) -> list[dict]:
42
@pytest.mark.parametrize("scale_name", ["weight_scale", "weight_scale_inv"])
43
def test_registered_deep_gemm_layer_is_warmed_up(monkeypatch, scale_name) -> None:
44
"""Any layer stamped by the DeepGEMM kernel is warmed, regardless of the
45
- quantization method that owns it or the name of its scale parameter.
46
- """
45
+ quantization method that owns it or the name of its scale parameter."""
46
layer = _block_fp8_layer(256, 128, scale_name)
47
48
calls = _run_warmup(monkeypatch, [layer])
@@ -55,8 +54,7 @@ def test_registered_deep_gemm_layer_is_warmed_up(monkeypatch, scale_name) -> Non
54
55
def test_n_multiple_of_64_matches_kernel_selection(monkeypatch) -> None:
56
"""DeepGEMM accepts N % 64 == 0 (e.g. DeepSeek kv_a_proj_with_mqa, N=576),
58
- so warmup must not require N % 128 == 0.
59
- """
57
+ so warmup must not require N % 128 == 0."""
58
assert len(_run_warmup(monkeypatch, [_block_fp8_layer(576, 256)])) == 1
59
60
tests/model_executor/test_routed_experts_capture.py
+1
-2
@@ -326,8 +326,7 @@ def test_routed_experts_capturer_dp_unexpected_batch_raises():
326
327
def test_routed_experts_attention_group_is_shared_and_fail_closed():
328
"""Both sides key routing data by this gid, so it must skip non-full-attention
329
- groups rather than defaulting to 0, and fail closed when none exists.
330
- """
329
+ groups rather than defaulting to 0, and fail closed when none exists."""
330
common = dict(num_kv_heads=1, head_size=1, dtype=torch.float32)
331
config = SimpleNamespace(
332
kv_cache_groups=[
tests/model_executor/test_weight_utils.py
+8
-16
@@ -57,8 +57,7 @@ class TestMaybeRemapKvScaleName:
57
58
def test_qkv_proj_k_scale(self):
59
"""Qwen3-MoE / llm-compressor format: qkv_proj.k_scale -> attn.k_scale
60
- Regression test for https://github.com/vllm-project/vllm/issues/25047
61
- """
60
+ Regression test for https://github.com/vllm-project/vllm/issues/25047"""
61
result = maybe_remap_kv_scale_name(
62
"model.layers.0.self_attn.qkv_proj.k_scale", self.PARAMS_DICT
63
)
@@ -66,8 +65,7 @@ class TestMaybeRemapKvScaleName:
65
66
def test_qkv_proj_v_scale(self):
67
"""Qwen3-MoE / llm-compressor format: qkv_proj.v_scale -> attn.v_scale
69
- Regression test for https://github.com/vllm-project/vllm/issues/25047
70
- """
68
+ Regression test for https://github.com/vllm-project/vllm/issues/25047"""
69
result = maybe_remap_kv_scale_name(
70
"model.layers.0.self_attn.qkv_proj.v_scale", self.PARAMS_DICT
71
)
@@ -110,8 +108,7 @@ class TestMaybeRemapKvScaleName:
108
def test_nvfp4_modelopt_k_proj_k_scale(self):
109
"""ModelOpt NVFP4 format (e.g. nvidia/Qwen3-30B-A3B-NVFP4):
110
k_proj.k_scale -> attn.k_scale.
113
- Validates that NVFP4 checkpoints are not broken by this change.
114
- """
111
+ Validates that NVFP4 checkpoints are not broken by this change."""
112
result = maybe_remap_kv_scale_name(
113
"model.layers.0.self_attn.k_proj.k_scale", self.PARAMS_DICT
114
)
@@ -120,8 +117,7 @@ class TestMaybeRemapKvScaleName:
117
def test_nvfp4_modelopt_v_proj_v_scale(self):
118
"""ModelOpt NVFP4 format (e.g. nvidia/Qwen3-30B-A3B-NVFP4):
119
v_proj.v_scale -> attn.v_scale.
123
- Validates that NVFP4 checkpoints are not broken by this change.
124
- """
120
+ Validates that NVFP4 checkpoints are not broken by this change."""
121
result = maybe_remap_kv_scale_name(
122
"model.layers.0.self_attn.v_proj.v_scale", self.PARAMS_DICT
123
)
@@ -129,8 +125,7 @@ class TestMaybeRemapKvScaleName:
125
126
def test_qwen3_vl_moe_qkv_proj_k_scale(self):
127
"""Qwen3-VL-MoE uses the same fused qkv_proj naming as Qwen3-MoE.
132
- Regression test for qwen3_vl_moe.py fix (same bug as #25047).
133
- """
128
+ Regression test for qwen3_vl_moe.py fix (same bug as #25047)."""
129
result = maybe_remap_kv_scale_name(
130
"model.layers.0.self_attn.qkv_proj.k_scale", self.PARAMS_DICT
131
)
@@ -138,8 +133,7 @@ class TestMaybeRemapKvScaleName:
133
134
def test_qwen3_vl_moe_qkv_proj_v_scale(self):
135
"""Qwen3-VL-MoE uses the same fused qkv_proj naming as Qwen3-MoE.
141
- Regression test for qwen3_vl_moe.py fix (same bug as #25047).
142
- """
136
+ Regression test for qwen3_vl_moe.py fix (same bug as #25047)."""
137
result = maybe_remap_kv_scale_name(
138
"model.layers.0.self_attn.qkv_proj.v_scale", self.PARAMS_DICT
139
)
@@ -181,8 +175,7 @@ class TestKvCacheScaleMapper:
175
"""The `WeightsMapper` returned by `get_cache_scale_mapper` replaces the
176
per-model `maybe_remap_kv_scale_name` calls. It must remap the same set of
177
checkpoint formats (the non-`params_dict`-dependent ones) and be idempotent
184
- so it composes safely with a model's own qkv/gate_up `hf_to_vllm_mapper`.
185
- """
178
+ so it composes safely with a model's own qkv/gate_up `hf_to_vllm_mapper`."""
179
180
def _mapper(self):
181
# `get_cache_scale_mapper` does not use `self`; call it on the base
@@ -272,8 +265,7 @@ class TestKvCacheScaleMapper:
265
def test_composes_with_qkv_mapper(self):
266
"""Applied together with a model's qkv/gate_up mapper, the regex scale
267
rules run before the substr rename, so scales are normalized to `.attn.`
275
- and regular projections are still fused correctly.
276
- """
268
+ and regular projections are still fused correctly."""
269
from vllm.model_executor.models.utils import WeightsMapper
270
271
model_mapper = WeightsMapper(
tests/models/inkling/test_mm_towers.py
+1
-2
@@ -42,8 +42,7 @@ def _assert_close_ulps(
42
compare against the reference's local ulp spacing. ``pre_act`` (the
43
reference pre-activation) adds derivative-propagated slack: near
44
``gelu(x) ~ 0`` an ulp-level input flip legitimately moves the output by
45
- many of ITS (tiny) ulps, bounded by |gelu'| <= 1.13 times the input ulps.
46
- """
45
+ many of ITS (tiny) ulps, bounded by |gelu'| <= 1.13 times the input ulps."""
46
g, r = got.float(), ref.float()
47
tol = torch.clamp(max_ulps * _bf16_spacing(ref), min=atol)
48
if pre_act is not None:
tests/models/kimi_k3/test_amd_latent_moe_runner.py
+1
-2
@@ -123,8 +123,7 @@ def _check_writes_only_its_own_shard(
123
device: torch.device, tp_size: int, rank: int
124
) -> None:
125
"""Two ranks that swapped both weight rows and write offsets still sum to
126
- the right total, so inspect each slice before the final collective.
127
- """
126
+ the right total, so inspect each slice before the final collective."""
127
transform = _build_transform(device)
128
runner = _tail_runner(transform, tp_size)
129
group = get_tp_group().device_group
tests/models/kimi_k3/test_aux_attn_res_stream.py
+2
-4
@@ -130,8 +130,7 @@ def test_disabled_reproduces_the_plain_residual_sum(
130
131
def test_taps_the_consumer_layer_when_one_follows(recorder, monkeypatch):
132
"""The value the next layer reads is the mixture against *its* weights,
133
- so the tap has to reach forward rather than use the current layer's.
134
- """
133
+ so the tap has to reach forward rather than use the current layer's."""
134
_set_last_rank(monkeypatch, True)
135
136
_call(_stub_model(enabled=True), 1, torch.zeros(2), None, torch.zeros(2))
@@ -182,8 +181,7 @@ def test_pending_mlp_output_is_folded_in_rather_than_passed_as_delta(
181
):
182
"""The kernel writes an applied delta back into the prefix in place, which
183
would double-add it into the live residual stream, so the pending output
185
- has to arrive already summed into the prefix with `delta` left None.
186
- """
184
+ has to arrive already summed into the prefix with `delta` left None."""
185
_set_last_rank(monkeypatch, True)
186
prefix_sum = torch.tensor([1.0, 2.0])
187
pending = torch.tensor([0.5, 0.25])
tests/models/kimi_k3/test_kda_metadata.py
+1
-2
@@ -727,8 +727,7 @@ def test_cudagraph_capture_metadata_avoids_device_to_host_copy(
727
"""`build_for_cudagraph_capture` is not capture-only: a DP rank with nothing
728
scheduled re-stages its FULL-graph metadata through it on every dummy step,
729
so it must not synchronize the device. The host-side draft counts have to
730
- come from `query_start_loc_cpu` and match the device-derived values.
731
- """
730
+ come from `query_start_loc_cpu` and match the device-derived values."""
731
num_speculative_tokens = 2
732
batch = BatchSpec(seq_lens=[50, 30], query_lens=[3, 3])
733
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
tests/models/language/generation/test_gemma.py
+2
-4
@@ -60,8 +60,7 @@ def test_checkpoint_lm_head_can_override_tied_config(monkeypatch) -> None:
60
def test_gemma4_kv_shared_layer_loads_plain_q_proj() -> None:
61
"""KV-shared layers have q_proj instead of a packed qkv_proj; their
62
redundant K/V tensors in original checkpoints have no parameter and are
63
- skipped rather than failing the load.
64
- """
63
+ skipped rather than failing the load."""
64
model = torch.nn.Module()
65
model.config = SimpleNamespace(num_experts=0)
66
model.start_layer, model.end_layer = 0, 2
@@ -93,8 +92,7 @@ def test_gemma4_kv_shared_layer_loads_plain_q_proj() -> None:
92
@pytest.mark.cpu_test
93
def test_gemma3n_kv_shared_layer_mapper() -> None:
94
"""Only non-shared layers pack q/k/v into qkv_proj; KV-shared layers keep
96
- q_proj and drop the redundant K/V tensors original checkpoints ship.
97
- """
95
+ q_proj and drop the redundant K/V tensors original checkpoints ship."""
96
config = SimpleNamespace(num_hidden_layers=4, num_kv_shared_layers=2)
97
mapper = Gemma3nTextModel.hf_to_vllm_mapper | _kv_sharing_weights_mapper(config)
98
weights = [
tests/models/language/generation/test_mistral.py
+1
-2
@@ -274,8 +274,7 @@ def test_mistral_function_calling(vllm_runner, model: str, dtype: str) -> None:
274
275
def test_mistral_function_call_nested_json():
276
"""Ensure that the function-name regex captures the entire outermost
277
- JSON block, including nested braces.
278
- """
277
+ JSON block, including nested braces."""
278
279
# Create a minimal stub tokenizer that provides the few attributes the
280
# parser accesses (`version` and `get_vocab`).
tests/models/language/pooling/test_splade_sparse_pooler.py
+1
-2
@@ -29,8 +29,7 @@ from vllm.v1.worker.gpu.states import RequestState
29
@torch.inference_mode
30
def test_splade_pooler_matches_reference_formula(B, T, H, V):
31
"""Ensure SPLADESparsePooler forward() matches the mathematical formula:
32
- log1p(relu(logits)) -> max over sequence length (after masking).
33
- """
32
+ log1p(relu(logits)) -> max over sequence length (after masking)."""
33
torch.manual_seed(0)
34
35
# Prepare [B] sequences of shape [T, H]
tests/models/multimodal/generation/test_moondream3_moe.py
+1
-2
@@ -33,8 +33,7 @@ NUM_TOKENS = 3
33
34
class _StubGate(torch.nn.Module):
35
"""Router stand-in, so the test does not depend on platform-specific
36
- ``ReplicatedLinear`` weight post-processing.
37
- """
36
+ ``ReplicatedLinear`` weight post-processing."""
37
38
def __init__(self, hidden_size: int, num_experts: int):
39
super().__init__()
tests/models/multimodal/generation/test_transformers_audio.py
+1
-2
@@ -81,8 +81,7 @@ def test_transformers_audio_generation(
81
under pytest can cause (possibly flaky) hangs, so they are grouped under
82
the same config. Using VLLM_WORKER_MULTIPROC_METHOD=spawn avoids the
83
deadlock and allows worker processes to terminate cleanly, and release
84
- GPU memory between test runs until the issue is fixed.
85
- """
84
+ GPU memory between test runs until the issue is fixed."""
85
# TODO: Remove monkeypatch once
86
# https://github.com/vllm-project/vllm/issues/17676 is fixed.
87
disable_envs_cache()
tests/models/multimodal/generation/vlm_utils/builders.py
+1
-2
@@ -294,8 +294,7 @@ def sample_frames_with_video_metadata(
294
295
def apply_image_size_scaling(image, size: float | tuple[int, int], size_type: SizeType):
296
"""Applies a size scaler to one image; this can be an image size factor,
297
- which scales the image while maintaining the aspect ratio
298
- """
297
+ which scales the image while maintaining the aspect ratio"""
298
# Special case for embeddings; if it's a tensor, it's only valid if we
299
# are considering size factors at constant scale, i.e., we just clone
300
# the tensor
tests/models/multimodal/processing/test_deepseek_ocr.py
+2
-4
@@ -108,8 +108,7 @@ class TestDeepseekOCREmptyImagesCrop:
108
109
def test_mismatched_image_size_raises(self, processor):
110
"""Deliberately wrong image_size binding should still be caught
111
- by TensorSchema validation.
112
- """
111
+ by TensorSchema validation."""
112
small_image = Image.new("RGB", (100, 100), color="green")
113
114
result = processor(
@@ -143,8 +142,7 @@ class TestDeepseekOCRInputValidation:
142
def test_mismatched_image_count_raises_value_error(self, processor):
143
"""Two ``<image>`` tokens with one image must raise ValueError, not
144
AssertionError (which would yield HTTP 500 and, under ``-O``, silently
146
- drop the middle text segment).
147
- """
145
+ drop the middle text segment)."""
146
image = Image.new("RGB", (100, 100), color="red")
147
with pytest.raises(ValueError, match="does not match number of images"):
148
processor(prompt="<image> and <image>", images=[image])
tests/models/multimodal/processing/test_llava_next_video.py
+2
-4
@@ -16,8 +16,7 @@ from ...utils import build_model_context
16
class _StubModel:
17
"""Carries only the attributes the token-count method reads from
18
`self`, so the real methods can be exercised without constructing
19
- the full `nn.Module` (vision tower, language model, etc.).
20
- """
19
+ the full `nn.Module` (vision tower, language model, etc.)."""
20
21
patch_grid_length: int
22
pooled_grid_length: int
@@ -32,8 +31,7 @@ get_mm_lora_token_counts = (
31
def test_num_mm_tokens_match_real_config(model_id):
32
"""The stored grid lengths must match what `__init__` derives from
33
the real HF config, and the LoRA token counts must preserve the
35
- frame-level scaling exactly.
36
- """
34
+ frame-level scaling exactly."""
35
ctx = build_model_context(model_id, limit_mm_per_prompt={"video": 1})
36
config = ctx.model_config.hf_config
37
tests/models/multimodal/processing/test_molmo2.py
+1
-2
@@ -70,8 +70,7 @@ def test_dummy_video_num_frames_override_honors_min_of_two(
70
):
71
"""A ``num_frames`` override below 2 must be ignored (the model needs at
72
least 2 frames), matching the "cannot be less than 2, will be ignored"
73
- warning.
74
- """
73
+ warning."""
74
builder = object.__new__(Molmo2DummyInputsBuilder)
75
builder.info = SimpleNamespace(
76
get_hf_processor=lambda: SimpleNamespace(
tests/models/multimodal/processing/test_qwen3_vl.py
+4
-8
@@ -31,8 +31,7 @@ def _build_video_mm_data(
31
32
``total_num_frames`` is set equal to the ndarray frame count so
33
that HF's ``sample_frames`` indices stay within bounds of the
34
- actual tensor that is passed.
35
- """
34
+ actual tensor that is passed."""
35
video = np.zeros((num_frames, height, width, 3), dtype=np.uint8)
36
metadata = {
37
"fps": original_fps,
@@ -238,8 +237,7 @@ def _build_video_embeds_mm_data(
237
grid_thw: tuple[int, int, int] = (2, 4, 4),
238
) -> dict[str, Any]:
239
"""Create an embeds-only video item as an EPD consumer receives it:
241
- pre-computed embeddings plus the metadata published by the encoder.
242
- """
240
+ pre-computed embeddings plus the metadata published by the encoder."""
241
import torch
242
243
t, h, w = grid_thw
@@ -258,8 +256,7 @@ def test_processor_video_embeds_with_timestamps(model_id: str) -> None:
256
"""Embeds-only video input must size the placeholder range from the
257
grid and the real timestamps published by the encoder (EC consumer
258
path); synthesized or missing timestamps would change the token count
261
- and break embedding merging downstream.
262
- """
259
+ and break embedding merging downstream."""
260
# `build_model_context` forces enable_mm_embeds off, so build the
261
# config directly; keep the same online-availability skip behavior.
262
HF_EXAMPLE_MODELS.find_hf_info(model_id).check_available_online(on_fail="skip")
@@ -304,8 +301,7 @@ def test_processor_video_embeds_with_timestamps(model_id: str) -> None:
301
def test_processor_video_embeds_missing_timestamps(model_id: str) -> None:
302
"""Timestamps are required metadata for video embeds: they size the
303
placeholder range, so omitting them must fail loudly at parse time
307
- instead of silently producing a wrong prompt.
308
- """
304
+ instead of silently producing a wrong prompt."""
305
ctx = build_model_context(
306
model_id,
307
limit_mm_per_prompt={"image": 0, "video": 1},
tests/models/multimodal/processing/test_transformers_audio.py
+1
-2
@@ -116,8 +116,7 @@ def test_audio_multimodal_processor(model_id, processor_cls):
116
@pytest.mark.parametrize("separator", [" and ", ""])
117
def test_audio_multiple_inputs(separator, processor_cls):
118
"""Multiple audios per prompt are each detected as a separate placeholder
119
- and multi-modal item by the Transformers modelling backend.
120
- """
119
+ and multi-modal item by the Transformers modelling backend."""
120
model_id = "ibm-granite/granite-speech-3.3-2b"
121
mm_processor = create_processor(model_id, processor_cls)
122
tests/models/multimodal/processing/test_transformers_image.py
+8
-16
@@ -83,8 +83,7 @@ def _process_two_images(processor_cls, separator: str):
83
@pytest.mark.parametrize("processor_cls", PROCESSOR_CLASSES)
84
def test_image_multiple_inputs(processor_cls):
85
"""Multiple images per prompt are each detected as a separate placeholder
86
- and multi-modal item by the Transformers modelling backend.
87
- """
86
+ and multi-modal item by the Transformers modelling backend."""
87
result = _process_two_images(processor_cls, separator="\n and ")
88
89
assert len(result["mm_placeholders"]["image"]) == 2
@@ -103,8 +102,7 @@ def test_image_adjacent_inputs(processor_cls):
102
@pytest.mark.parametrize("processor_cls", PROCESSOR_CLASSES)
103
def test_batch_padding_removed_from_image_items(processor_cls):
104
"""Emu3 pads every image up to the largest in the batch, which would leave an
106
- item's data dependent on what it was processed with and so uncacheable.
107
- """
105
+ item's data dependent on what it was processed with and so uncacheable."""
106
mm_processor = create_processor("BAAI/Emu3-Chat-hf", processor_cls)
107
image_token = mm_processor.info.get_hf_processor().image_token
108
@@ -146,8 +144,7 @@ def _process_one_gemma3_image(processor_cls):
144
@offsets_only
145
def test_non_embedding_tokens_excluded_from_placeholders():
146
"""Gemma3 wraps each image in text that carries no embeddings, which must be
149
- inside the placeholder range but masked out of it.
150
- """
147
+ inside the placeholder range but masked out of it."""
148
_, result = _process_one_gemma3_image(OffsetsMultiModalProcessor)
149
150
(placeholder,) = result["mm_placeholders"]["image"]
@@ -159,8 +156,7 @@ def test_legacy_placeholders_hold_only_image_tokens():
156
"""The legacy path spans whatever `mm_token_type_ids` attributes to the image,
157
which for Gemma3 excludes the text wrapping it, unlike the replacement the offsets
158
path spans. Gemma3 is also the sharp case for the mask: its `image_token_id` is the
162
- marker in the unexpanded prompt, not the token the expansion repeats.
163
- """
159
+ marker in the unexpanded prompt, not the token the expansion repeats."""
160
hf_processor, result = _process_one_gemma3_image(LegacyMultiModalProcessor)
161
162
(placeholder,) = result["mm_placeholders"]["image"]
@@ -176,8 +172,7 @@ def test_tokens_structuring_an_image_are_masked_not_dropped(processor_cls):
172
embeddings. Those belong inside the placeholder and masked out, because the token
173
count the processor reports is over the whole span. Idefics3 also refuses a prompt
174
holding `<image>` when no images are passed, which is how the offsets path has to
179
- tokenize it before splicing in the expansion.
180
- """
175
+ tokenize it before splicing in the expansion."""
176
mm_processor = create_processor(
177
"HuggingFaceTB/SmolVLM-256M-Instruct", processor_cls
178
)
@@ -197,8 +192,7 @@ def test_tokens_structuring_an_image_are_masked_not_dropped(processor_cls):
192
@offsets_only
193
def test_missing_replacement_offsets_names_the_processor():
194
"""A processor that reports no replacement offsets cannot be served, which must
200
- be said plainly rather than surfacing later as a field config mismatch.
201
- """
195
+ be said plainly rather than surfacing later as a field config mismatch."""
196
model_id = "llava-hf/llava-onevision-qwen2-0.5b-ov-hf"
197
mm_processor = create_processor(model_id, OffsetsMultiModalProcessor)
198
hf_processor_cls = type(mm_processor.info.get_hf_processor())
@@ -282,8 +276,7 @@ def test_repeated_image_hits_the_processor_cache():
276
def test_spliced_prompt_matches_hf_expansion(model_id, prompt):
277
"""The offsets path splices the expansion into a prompt tokenized without any
278
multi-modal data, so its token ids have to come out the same as the ones the HF
285
- processor produces itself, which is what the legacy path returns.
286
- """
279
+ processor produces itself, which is what the legacy path returns."""
280
prompt_ids = []
281
for processor_cls in (LegacyMultiModalProcessor, OffsetsMultiModalProcessor):
282
mm_processor = create_processor(model_id, processor_cls)
@@ -305,8 +298,7 @@ def test_spliced_prompt_matches_hf_expansion(model_id, prompt):
298
def test_nested_image_fields_split_per_image(processor_cls):
299
"""Idefics3 returns image fields with a leading batch dimension, putting the rows
300
belonging to each image one dimension further in. Slicing the batch dimension
308
- instead handed the first image every row and the second an empty tensor.
309
- """
301
+ instead handed the first image every row and the second an empty tensor."""
302
mm_processor = create_processor(
303
"HuggingFaceTB/SmolVLM-256M-Instruct", processor_cls
304
)
tests/models/multimodal/processing/transformers_backend.py
+2
-4
@@ -29,8 +29,7 @@ PROCESSOR_CLASSES = [
29
30
def create_processor(model_id: str, processor_cls):
31
"""Build a processor directly, because the registry only ever builds the one the
32
- installed transformers version selects, leaving the other path untested.
33
- """
32
+ installed transformers version selects, leaving the other path untested."""
33
model_config = ModelConfig(model=model_id, model_impl="transformers")
34
ctx = InputProcessingContext(
35
model_config, cached_tokenizer_from_config(model_config)
@@ -41,8 +40,7 @@ def create_processor(model_id: str, processor_cls):
40
41
def create_cached_processor(model_id: str, processor_cls):
42
"""Build a processor backed by a real multi-modal processor cache, and hand the
44
- cache back so a test can check it was actually used.
45
- """
43
+ cache back so a test can check it was actually used."""
44
model_config = ModelConfig(model=model_id, model_impl="transformers")
45
model_config.multimodal_config.mm_processor_cache_gb = 4
46
ctx = InputProcessingContext(
tests/models/multimodal/test_cohere_asr.py
+1
-2
@@ -18,8 +18,7 @@ from vllm.model_executor.models.cohere_asr import CohereAsrForConditionalGenerat
18
def test_get_num_audio_tokens_streaming_estimate(audio_duration_s, expected_tokens):
19
"""The duration-based estimate must convert ``window_stride`` (seconds) to a
20
sample hop and divide by the encoder subsampling factor. Values are pinned to
21
- concrete numbers so a rounding regression is actually caught.
22
- """
21
+ concrete numbers so a rounding regression is actually caught."""
22
model_config = SimpleNamespace(
23
hf_config=SimpleNamespace(
24
preprocessor={"window_stride": 0.01, "sample_rate": 16000},
tests/models/multimodal/test_mapping.py
+1
-2
@@ -78,8 +78,7 @@ def test_cosmos3_modelopt_quantizer_weights_mapper():
78
"""ModelOpt/Diffusers FP8 checkpoints ship native fake-quant buffers
79
(``*_quantizer._amax`` / ``._scale``) alongside the vLLM-consumable
80
``weight_scale`` / ``input_scale`` sidecars. vLLM must drop the former
81
- (it has no parameter for them) while keeping the latter.
82
- """
81
+ (it has no parameter for them) while keeping the latter."""
82
from vllm.model_executor.models.cosmos3 import Cosmos3ForConditionalGeneration
83
84
mapper = Cosmos3ForConditionalGeneration.hf_to_vllm_mapper
tests/models/multimodal/test_nano_nemotron_vl.py
+3
-6
@@ -81,8 +81,7 @@ class _FakeTensor:
81
"""Sentinel stand-in for torch.Tensor in load_weights tests. Supports the
82
.detach().clone() chain used by load_weights for buffered mm weights;
83
both methods return self so identity (and the existing equality
84
- assertions) are preserved through cloning.
85
- """
84
+ assertions) are preserved through cloning."""
85
86
def detach(self):
87
return self
@@ -166,8 +165,7 @@ def _make_mm_items_with_video_bytes(
165
166
def test_extract_audio_from_videos_passes_max_duration():
167
"""_extract_audio_from_videos must forward VLLM_MAX_AUDIO_DECODE_DURATION_S
169
- to load_audio_pyav so decompression-bomb audio is rejected.
170
- """
168
+ to load_audio_pyav so decompression-bomb audio is rejected."""
169
dummy_audio = (np.zeros(16000, dtype=np.float32), 16000.0)
170
mm_items = _make_mm_items_with_video_bytes(b"\x00" * 64)
171
@@ -187,8 +185,7 @@ def test_extract_audio_from_videos_passes_max_duration():
185
186
def test_extract_audio_from_videos_rejects_oversized_audio():
187
"""When load_audio_pyav raises due to duration limit the video is
190
- marked as having no audio instead of crashing the server.
191
- """
188
+ marked as having no audio instead of crashing the server."""
189
mm_items = _make_mm_items_with_video_bytes(b"\x00" * 64)
190
191
processor = object.__new__(NanoNemotronVLMultiModalProcessor)
tests/models/qwen4_exp/test_config.py
+1
-2
@@ -144,8 +144,7 @@ def test_qwen4_exp_mtp_override_sets_draft_config(
144
def test_qwen4_exp_rejects_pipeline_parallel_only_with_ple(ple_layer_ids) -> None:
145
"""PLE needs raw input_ids, which non-first pipeline ranks never see. The
146
rest of the architecture is PP-capable, so the refusal must be conditional
147
- -- and must land before the engine spends time loading weights.
148
- """
147
+ -- and must land before the engine spends time loading weights."""
148
vllm_config = SimpleNamespace(
149
model_config=SimpleNamespace(
150
hf_text_config=_text_config(ple_layer_ids=ple_layer_ids),
tests/models/test_deepseek_v4_fi_moe_ep.py
+5
-10
@@ -103,8 +103,7 @@ def test_fi_backend_strings_are_registered_mega_moe_backends():
103
@pytest.mark.parametrize("moe_backend", sorted(FLASHINFER_MOE_EP_BACKENDS))
104
def test_fi_moe_ep_backend_rejected_for_non_dsv4(moe_backend):
105
"""An FI moe_ep backend with a non-DSv4 model must fail at config time
106
- instead of silently falling through to the generic FusedMoE path.
107
- """
106
+ instead of silently falling through to the generic FusedMoE path."""
107
with pytest.raises(ValueError, match="only supported for DeepSeek-V4"):
108
validate_flashinfer_moe_ep_model(moe_backend, ["MixtralForCausalLM"])
109
@@ -120,8 +119,7 @@ def test_fi_moe_ep_backend_accepted_for_dsv4(moe_backend):
119
)
120
def test_native_deep_gemm_mega_moe_not_arch_gated(architectures):
121
"""VLLM's own deep_gemm mega path is not DSv4-only (Kimi K3 uses it);
123
- models validate their own constraints at construction time.
124
- """
122
+ models validate their own constraints at construction time."""
123
validate_flashinfer_moe_ep_model("deep_gemm_mega_moe", architectures)
124
125
@@ -134,8 +132,7 @@ def test_all_mega_backends_get_sequence_parallel_moe(moe_backend):
132
"""Every mega backend must qualify for sequence-parallel MoE at
133
TP>1/EP: the predicate once matched only the native backend string,
134
which silently ran the fi backends full-batch with an all-reduce on
137
- every rank — 0.42-0.65x native e2e at TP8.
138
- """
135
+ every rank — 0.42-0.65x native e2e at TP8."""
136
from vllm.models.deepseek_v4.nvidia.model import _use_sequence_parallel
137
138
vllm_config = SimpleNamespace(
@@ -179,8 +176,7 @@ def test_bootstrap_pins_the_device_vllm_bound(fake_flashinfer, monkeypatch):
176
"""The runtime must not rederive the device from LOCAL_RANK/rank: under a
177
remapped CUDA_VISIBLE_DEVICES that ordinal points at the wrong GPU
178
(CUDA_ERROR_ILLEGAL_ADDRESS in the weight transforms). vLLM passes the
182
- device it already bound via BootstrapConfig.device.
183
- """
179
+ device it already bound via BootstrapConfig.device."""
180
import vllm.utils.flashinfer_moe_ep as mod
181
182
pg = object()
@@ -245,8 +241,7 @@ def test_ckpt_uses_nvfp4_experts_reads_moe_quant_algo():
241
242
def test_dequant_fp4_ue8m0_gran32_decodes_lut_and_scales():
243
"""One 32-element scale group per row: low nibble is the even element,
248
- high nibble the odd one, ue8m0 scale applies to the whole group.
249
- """
244
+ high nibble the odd one, ue8m0 scale applies to the whole group."""
245
packed = torch.arange(32, dtype=torch.uint8).reshape(2, 16)
246
sf = torch.tensor([[127], [128]], dtype=torch.uint8) # 2**0, 2**1
247
tests/models/test_deepseek_v4_mega_moe.py
+2
-4
@@ -783,8 +783,7 @@ def test_deepseek_v4_mega_moe_stages_shared_scale_tma_layout(shared_block_m):
783
def test_deepseek_v4_pwal_hook_finalizes_mega_moe_and_mhc_broadcast():
784
"""The loader invokes the model-level PWAL hook for every load format,
785
so it must finalize megamoe + mhc broadcast weights to cover dummy
786
- load, which skips load_weights().
787
- """
786
+ load, which skips load_weights()."""
787
calls = []
788
stub = SimpleNamespace(
789
model=SimpleNamespace(
@@ -801,8 +800,7 @@ def test_deepseek_v4_pwal_hook_finalizes_mega_moe_and_mhc_broadcast():
800
def test_deepseek_v4_drafter_pwal_hooks_finalize_mega_moe():
801
"""MTP/DSpark drafters load as their own top-level models, so each needs
802
its own PWAL hook now that the megamoe forward no longer finalizes
804
- weights lazily on first use.
805
- """
803
+ weights lazily on first use."""
804
calls = []
805
mtp = SimpleNamespace(finalize_mega_moe_weights=lambda: calls.append("mtp"))
806
DeepSeekV4MTP.process_weights_after_loading(mtp)
tests/models/test_dspark_mla.py
+1
-2
@@ -215,8 +215,7 @@ def test_v41_dspark_loads_linear_scales(
215
):
216
"""Checkpoint ``.scale`` maps to the quant method's scale parameter and
217
loads untouched. MXFP8 block-scale expansion lives in the KMxfp8Static
218
- loader (see tests/quantization/test_modelopt.py), not in load_weights.
219
- """
218
+ loader (see tests/quantization/test_modelopt.py), not in load_weights."""
219
from vllm.models.deepseek_v41.nvidia import dspark
220
221
mxfp8 = scale_dtype != torch.float32
tests/models/test_qwen3_5_mtp_config.py
+3
-6
@@ -73,8 +73,7 @@ def test_mtp_override_extracts_n_predict_from_multimodal_wrapper(
73
model_type: str, expected_arch: str
74
) -> None:
75
"""Verify that multimodal wrapper checkpoints with mtp_num_hidden_layers
76
- in text_config resolve n_predict and architecture correctly.
77
- """
76
+ in text_config resolve n_predict and architecture correctly."""
77
cfg = SpeculativeConfig.hf_config_override(
78
_multimodal_wrapper_mtp_config(model_type, mtp_layers=2)
79
)
@@ -94,8 +93,7 @@ def test_mtp_override_top_level_precedence_over_nested_text_config(
93
model_type: str, expected_arch: str
94
) -> None:
95
"""Verify that an explicit top-level mtp_num_hidden_layers takes precedence
97
- over a nested text_config value.
98
- """
96
+ over a nested text_config value."""
97
cfg = _multimodal_wrapper_mtp_config(model_type, mtp_layers=2)
98
cfg.mtp_num_hidden_layers = 3
99
overridden = SpeculativeConfig.hf_config_override(cfg)
@@ -115,8 +113,7 @@ def test_mtp_override_downloads_real_hf_hub_configs(
113
model_id: str, expected_arch: str
114
) -> None:
115
"""Verify that unmodified real-world checkpoints downloaded via
118
- AutoConfig.from_pretrained resolve n_predict=1 from text_config.
119
- """
116
+ AutoConfig.from_pretrained resolve n_predict=1 from text_config."""
117
hf_config = AutoConfig.from_pretrained(model_id)
118
cfg = SpeculativeConfig.hf_config_override(hf_config)
119
assert cfg.model_type == "qwen3_5_mtp"
tests/models/test_utils.py
+1
-2
@@ -197,8 +197,7 @@ def test_merge_multimodal_embeddings_no_sync():
197
def test_get_rename_mapper_keeps_only_renames():
198
"""`None` means "do not load", which is meaningless to the consumers of
199
this mapper (LoRA name parsing, quantization config layer lists), and
200
- applying it would silently shrink their lists.
201
- """
200
+ applying it would silently shrink their lists."""
201
mapper = WeightsMapper(
202
orig_to_new_regex={re.compile(r"^drop_regex\."): None},
203
orig_to_new_substr={"drop_substr": None, "keep_substr": "kept"},
tests/models/test_vision.py
+1
-2
@@ -512,8 +512,7 @@ def _reference_input_norm(
512
def test_fused_input_norm_matches_reference(num_patches: int):
513
"""FusedInputNorm must equal the plain affine, including for num_patches
514
above the cuDNN batch-norm grid limit (~65535) that previously raised
515
- CUDNN_STATUS_INTERNAL_ERROR (issue #51717).
516
- """
515
+ CUDNN_STATUS_INTERNAL_ERROR (issue #51717)."""
516
channel = 3
517
patch_size = 14 * 14
518
image_mean = [0.48145466, 0.4578275, 0.40821073]
tests/models/transformers/fusers/test_linear.py
+23
-46
@@ -251,8 +251,7 @@ class UnderscoreInplaceParallelLinears(FourParallelLinears):
251
252
class PlainQKV(nn.Module):
253
"""q/k/v returned as a bare tuple: no reshape stands between the calls and
254
- the return, so both QKVFuser and MergedColumnParallelFuser can rewrite it.
255
- """
254
+ the return, so both QKVFuser and MergedColumnParallelFuser can rewrite it."""
255
256
def __init__(self, hidden: int = 32, heads: int = 4, head_dim: int = 8):
257
super().__init__()
@@ -339,8 +338,7 @@ class GuardedVAttention(FakeAttention):
338
"""Gemma 4-style: `v_proj` is called once but also read in a `None` guard.
339
340
The guard is a fusion invariant (the fuser only binds instances where the
342
- projection exists), so it folds to `True` and the call still fuses.
343
- """
341
+ projection exists), so it folds to `True` and the call still fuses."""
342
343
def forward(
344
self, hidden_states, attention_mask=None, past_key_values=None, **kwargs
@@ -370,8 +368,7 @@ class TruthyGuardAttention(FakeAttention):
368
369
An `nn.Linear` is always truthy, so the guard folds to `True` and the call
370
still fuses (the projection is a proven invariant, exactly as for a `None`
373
- guard).
374
- """
371
+ guard)."""
372
373
def forward(
374
self, hidden_states, attention_mask=None, past_key_values=None, **kwargs
@@ -402,8 +399,7 @@ class StatementGuardVAttention(FakeAttention):
399
The `if`'s test is not an `ast.Compare`, so the identity-check scan skips it;
400
`_in_boolean_context` folds the test to `True` (an `nn.Linear` is always
401
truthy) and the call inside the now-`if True:` body still fuses, with the
405
- live `else` surviving the rewrite.
406
- """
402
+ live `else` surviving the rewrite."""
403
404
def forward(
405
self, hidden_states, attention_mask=None, past_key_values=None, **kwargs
@@ -432,8 +428,7 @@ class BranchedKVAttention(FakeAttention):
428
429
The three calls do not share a block, so the fused GEMM must be hoisted to
430
the innermost block that dominates all of them (the function body). The
435
- live `if`/`else` must survive the rewrite.
436
- """
431
+ live `if`/`else` must survive the rewrite."""
432
433
is_kv_shared_layer = False
434
@@ -464,8 +459,7 @@ class RebindArgAttention(FakeAttention):
459
460
The branch is dead at trace time so the match succeeds, but the source
461
rewrite must refuse: hoisting the GEMM above the rebind would feed k/v a
467
- different input. Result: no fusion.
468
- """
462
+ different input. Result: no fusion."""
463
464
recompute = False
465
@@ -496,8 +490,7 @@ class InPlaceMutatedArgAttention(FakeAttention):
490
Like `RebindArgAttention`, but the mutation keeps the name in a `Load`
491
context (`hidden_states.mul_(2)`), so a bare `Name`-store check would miss it.
492
The rewrite must still refuse: hoisting the GEMM above the mutation changes
499
- the value k/v see. Result: no fusion.
500
- """
493
+ the value k/v see. Result: no fusion."""
494
495
recompute = False
496
@@ -527,8 +520,7 @@ class AliasMutatedArgAttention(FakeAttention):
520
521
`hidden_states.view(-1)` shares storage with its base, so `alias.mul_(2)`
522
changes what k/v read without ever naming `hidden_states` as a target. Only
530
- tracking names that may alias the input catches it. Result: no fusion.
531
- """
523
+ tracking names that may alias the input catches it. Result: no fusion."""
524
525
recompute = False
526
@@ -559,8 +551,7 @@ class FunctionalInplaceArgAttention(FakeAttention):
551
552
`F.relu(hidden_states, inplace=True)` writes through an argument, so the
553
name appears only in a `Load` context inside a call that is not a method on
562
- it -- invisible to a trailing-underscore method check. Result: no fusion.
563
- """
554
+ it -- invisible to a trailing-underscore method check. Result: no fusion."""
555
556
recompute = False
557
@@ -590,8 +581,7 @@ class SubscriptMutatedArgAttention(FakeAttention):
581
582
`hidden_states[..., 0] = 0` leaves the name in a `Load` context on the
583
subscript's value, so it too evades a bare `Name`-store check. The rewrite
593
- must refuse for the same reason. Result: no fusion.
594
- """
584
+ must refuse for the same reason. Result: no fusion."""
585
586
recompute = False
587
@@ -621,8 +611,7 @@ class NonFoldableRefAttention(FakeAttention):
611
612
Deleting `v_proj` would break `isinstance(self.v_proj, nn.Linear)`: it reads
613
the projection's type, not just whether it exists, so the fuser cannot fold
624
- it and must refuse rather than rewrite it.
625
- """
614
+ it and must refuse rather than rewrite it."""
615
616
def forward(
617
self, hidden_states, attention_mask=None, past_key_values=None, **kwargs
@@ -847,8 +836,7 @@ def test_glu_identifies_down_projection():
836
837
It is forced to `RowParallelLinear` in `update_attrs` so its sharded input
838
matches the column-parallel merged gate/up; `None` when there is no such
850
- projection to force (fusion of gate/up still applies).
851
- """
839
+ projection to force (fusion of gate/up still applies)."""
840
with torch.device("meta"):
841
assert get_fuser(GLUMLP(), GLUFuser).down_name == "down_proj"
842
assert get_fuser(ReversedGLUMLP(), GLUFuser).down_name == "down_proj"
@@ -1009,8 +997,7 @@ def test_bypass_existence_guard_folds_identity_none_check(expr, expected):
997
The projection is a proven invariant (it exists as an `nn.Linear`), so an
998
`is (not) None` guard has a constant truth value; folding it lets the call be
999
rewritten away without changing the guard's outcome. `==`/`!=` are excluded
1012
- (see the refusal test) because a subclass may override `__eq__`/`__ne__`.
1013
- """
1000
+ (see the refusal test) because a subclass may override `__eq__`/`__ne__`."""
1001
funcdef, ref = _guard_funcdef(expr)
1002
bypass_existence_guard(funcdef, ref, "v_proj")
1003
test = next(node for node in ast.walk(funcdef) if isinstance(node, ast.IfExp)).test
@@ -1029,8 +1016,7 @@ def test_bypass_existence_guard_folds_bare_truthiness(expr):
1016
1017
An `nn.Linear` has no `__bool__`/`__len__`, so it is always truthy; in a pure
1018
boolean position (a test, or a `not` operand) the reference can be replaced by
1032
- `True`, letting the projection be deleted.
1033
- """
1019
+ `True`, letting the projection be deleted."""
1020
funcdef, ref = _guard_funcdef(expr)
1021
bypass_existence_guard(funcdef, ref, "v_proj")
1022
# No `self.v_proj` reference survives; a literal `True` took its place.
@@ -1045,8 +1031,7 @@ def test_bypass_existence_guard_folds_bare_if_statement():
1031
1032
The `len(node.ops) == 1` `Compare` scan skips it (it is not a comparison at
1033
all); `_in_boolean_context` then matches the `if`'s test and folds it, so the
1048
- bare-truthiness statement form is handled, not silently dropped.
1049
- """
1034
+ bare-truthiness statement form is handled, not silently dropped."""
1035
funcdef = ast.parse(
1036
"def f(self, a, b):\n if self.v_proj:\n return a\n return b"
1037
).body[0]
@@ -1078,8 +1063,7 @@ def test_bypass_existence_guard_refuses_non_guard_reference(expr):
1063
Rewriting it is unsafe (its value depends on more than the projection's
1064
existence), so the fuser refuses rather than change semantics. `==`/`!=` are
1065
refused too: `is_linear` accepts `nn.Linear` subclasses that could override
1081
- `__eq__`/`__ne__`, so equality need not agree with `is (not) None`.
1082
- """
1066
+ `__eq__`/`__ne__`, so equality need not agree with `is (not) None`."""
1067
funcdef, ref = _guard_funcdef(expr)
1068
with pytest.raises(ValueError, match="outside an existence guard"):
1069
bypass_existence_guard(funcdef, ref, "v_proj")
@@ -1119,8 +1103,7 @@ def test_merged_column_fuser_folds_existence_guard():
1103
1104
Guard folding lives on `StackedFuser`, not just `QKVFuser`, because every
1105
stacked fuser deletes the projections it merges -- a surviving reference to
1122
- one would fail at runtime.
1123
- """
1106
+ one would fail at runtime."""
1107
with torch.device("meta"):
1108
module = GuardedParallelLinears()
1109
fuser = MergedColumnParallelFuser.match(trace(module), module)
@@ -1146,8 +1129,7 @@ def test_merged_column_fuser_rejects_input_mutation(cls):
1129
The mutation may be direct (`x.add_(1)`), through a view that shares the
1130
input's storage, or through a call that writes an argument in place
1131
(`F.relu(x, inplace=True)`, `torch.relu_(x)`). Each one silently changes the
1149
- fused result, so the rewrite must refuse rather than fuse.
1150
- """
1132
+ fused result, so the rewrite must refuse rather than fuse."""
1133
with torch.device("meta"):
1134
module = cls()
1135
fuser = MergedColumnParallelFuser.match(trace(module), module)
@@ -1205,8 +1187,7 @@ def test_merged_column_fuser_supports_any_number_of_linears(
1187
1188
def test_merged_name_is_unique_per_linear_names():
1189
"""The computed name must not collide across different projections, so
1208
- stacking two unrelated fusions can never clobber packed_modules_mapping.
1209
- """
1190
+ stacking two unrelated fusions can never clobber packed_modules_mapping."""
1191
ab_c = MergedColumnParallelFuser(source_cls="M", linear_names=("a_b", "c"))
1192
a_bc = MergedColumnParallelFuser(source_cls="M", linear_names=("a", "b_c"))
1193
assert ab_c.merged_name != a_bc.merged_name
@@ -1222,8 +1203,7 @@ def test_heterogeneous_instances_fall_back_to_merged_column_fuser(
1203
layer whose out_features aren't a multiple of its own head_dim (as a
1204
misconfigured or heterogeneous checkpoint might have) fails QKVFuser's
1205
validation and must still fuse via the generic fallback, while a
1225
- well-formed sibling of the same class keeps using QKVFuser.
1226
- """
1206
+ well-formed sibling of the same class keeps using QKVFuser."""
1207
with torch.device("meta"):
1208
container = nn.Module()
1209
container.compatible = PlainQKV(head_dim=8)
@@ -1244,8 +1224,7 @@ def test_detects_and_rewrites_packed_qkv(kv_heads):
1224
"""A single projection split into q/k/v must be re-sharded, not merged.
1225
1226
Only the split sizes change: `QKVParallelLinear` loads the packed
1247
- checkpoint weight as-is, and shards q by heads while replicating k/v.
1248
- """
1227
+ checkpoint weight as-is, and shards q by heads while replicating k/v."""
1228
with torch.device("meta"):
1229
meta = PackedQKVAttention(kv_heads=kv_heads)
1230
fuser = get_fuser(meta, PackedQKVFuser)
@@ -1276,8 +1255,7 @@ def test_detects_and_rewrites_packed_qkv(kv_heads):
1255
1256
def test_per_head_split_is_not_packed_qkv():
1257
"""The split must consume the whole projection, else its sizes are head
1279
- widths and re-sharding by them would be wrong.
1280
- """
1258
+ widths and re-sharding by them would be wrong."""
1259
with torch.device("meta"):
1260
assert get_fuser(PerHeadSplitAttention(), PackedQKVFuser) is None
1261
@@ -1397,8 +1375,7 @@ def test_act_and_mul_derived_from_module(default_vllm_config):
1375
1376
def _wider_model_config(head_dim: int) -> SimpleNamespace:
1377
"""A model whose global head size is twice `head_dim`, as a wider layer
1400
- elsewhere in a heterogeneous checkpoint would make it.
1401
- """
1378
+ elsewhere in a heterogeneous checkpoint would make it."""
1379
return SimpleNamespace(
1380
model_config=SimpleNamespace(get_head_size=lambda: 2 * head_dim),
1381
quant_config=None,
tests/models/transformers/fusers/test_mla.py
+5
-10
@@ -45,8 +45,7 @@ def _attention(q_lora_rank: int | None):
45
46
def _match(q_lora_rank: int | None) -> MLAFuser | None:
47
"""Match a meta `DeepseekV2Attention` directly (bypassing the per-class
48
- `get_fuser` cache, so both q_lora variants of the same class are seen).
49
- """
48
+ `get_fuser` cache, so both q_lora variants of the same class are seen)."""
49
attn = _attention(q_lora_rank)
50
return MLAFuser.match(trace(attn), attn)
51
@@ -82,8 +81,7 @@ def test_discovers_modules_with_q_lora():
81
82
def test_q_lora_stacks_qkv_a_proj():
83
"""The MLA layer reads `q_a_proj` and `kv_a_proj_with_mqa` fused into one
85
- down-projection, so both checkpoint weights must remap into it.
86
- """
84
+ down-projection, so both checkpoint weights must remap into it."""
85
fuser = _match(q_lora_rank=64)
86
assert isinstance(fuser, MLAFuser)
87
prefix = "model.layers.0.self_attn"
@@ -104,8 +102,7 @@ def test_update_forward_rewrites_real_attention(q_lora_rank):
102
The q-LoRA path hoists the merged down-projection to a top-level statement
103
while its calls sit inside the `q_lora_rank` branches, so the region it
104
spans is wide; a check that over-approximates aliasing would silently refuse
107
- here and cost the fusion rather than fail loudly.
108
- """
105
+ here and cost the fusion rather than fail loudly."""
106
fuser = _match(q_lora_rank)
107
assert isinstance(fuser, MLAFuser)
108
fuser.update_forward(_attention(q_lora_rank))
@@ -129,8 +126,7 @@ class _Norm(nn.Module):
126
127
class RenamedMLA(nn.Module):
128
"""An MLA-shaped attention whose children have non-standard names, proving
132
- discovery is by structure and not attribute name.
133
- """
129
+ discovery is by structure and not attribute name."""
130
131
def __init__(self):
132
super().__init__()
@@ -157,8 +153,7 @@ class RenamedMLA(nn.Module):
153
154
def test_discovers_modules_under_arbitrary_names():
155
"""Discovery is purely structural: `RenamedMLA` gives its children non-standard
160
- names, and `match` still locates each projection by dataflow.
161
- """
156
+ names, and `match` still locates each projection by dataflow."""
157
with torch.device("meta"):
158
module = RenamedMLA()
159
fuser = MLAFuser.match(trace(module), module)
tests/models/transformers/fusers/test_moe.py
+6
-12
@@ -277,8 +277,7 @@ def test_moe_fuser_matches_scaled_router():
277
278
def test_moe_fuser_matches_grouped_router():
279
"""Group masking between the score and the routing top-k still matches: the
280
- scorer is anchored on the routing (last) top-k, not the group one.
281
- """
280
+ scorer is anchored on the routing (last) top-k, not the group one."""
281
with torch.device("meta"):
282
block = MoEBlock(GroupedRouter)
283
fuser = MoEBlockFuser.match(block, "experts")
@@ -288,8 +287,7 @@ def test_moe_fuser_matches_grouped_router():
287
288
def test_moe_fuser_matches_correction_router():
289
"""A score-correction bias buffer (DeepSeek-V3 noaux) is allowed; the
291
- rebuilt gate carries it in fp32 for FusedMoE's biased routers.
292
- """
290
+ rebuilt gate carries it in fp32 for FusedMoE's biased routers."""
291
with torch.device("meta"):
292
block = MoEBlock(CorrectionRouter)
293
fuser = MoEBlockFuser.match(block, "experts")
@@ -300,8 +298,7 @@ def test_moe_fuser_matches_correction_router():
298
def test_moe_fuser_reads_router_dtype_from_the_gate():
299
"""A router that computes its logits in fp32 must keep routing in fp32 when
300
rebuilt, even though no config field names the dtype. The cast back to the
303
- activation dtype after the top-k must not be mistaken for the routing dtype.
304
- """
301
+ activation dtype after the top-k must not be mistaken for the routing dtype."""
302
with torch.device("meta"):
303
fp32 = MoEBlockFuser.match(MoEBlock(Fp32Router), "experts")
304
default = MoEBlockFuser.match(MoEBlock(TopKRouter), "experts")
@@ -320,8 +317,7 @@ def test_moe_fuser_detects_shared_experts():
317
318
def test_moe_fuser_skips_shared_detection_without_extra_children():
319
"""With only experts and gate, shared-expert detection (and its block trace)
323
- is skipped, so a gate-derived add is not misread as a shared expert.
324
- """
320
+ is skipped, so a gate-derived add is not misread as a shared expert."""
321
with torch.device("meta"):
322
block = MoEBlockNoShared()
323
fuser = MoEBlockFuser.match(block, "experts")
@@ -366,8 +362,7 @@ def test_moe_fuser_declines_unsupported(block_cls):
362
363
def test_moe_fuser_ignores_nested_returns():
364
"""A tuple `return` inside a nested helper must not decline a block whose own
369
- forward returns a single tensor.
370
- """
365
+ forward returns a single tensor."""
366
with torch.device("meta"):
367
block = MoEBlockNestedTupleReturn()
368
assert isinstance(MoEBlockFuser.match(block, "experts"), MoEBlockFuser)
@@ -375,8 +370,7 @@ def test_moe_fuser_ignores_nested_returns():
370
371
def test_moe_fuser_router_requires_connected_dataflow():
372
"""A gate with linear + softmax + top-k present but not wired as a router
378
- (top-k selects over the input, not the scored logits) is not detected.
379
- """
373
+ (top-k selects over the input, not the scored logits) is not detected."""
374
with torch.device("meta"):
375
block = MoEBlock(DisconnectedRouter)
376
assert MoEBlockFuser.match(block, "experts") is None
tests/models/transformers/fusers/test_rms_norm.py
+9
-18
@@ -83,8 +83,7 @@ class ToleranceRMSNorm(NamedEpsRMSNorm):
83
84
class LiteralEpsRMSNorm(RMSNorm):
85
"""eps is a literal in the source, and an unrelated attribute happens to
86
- hold the same value: matching on the value alone would bind to it.
87
- """
86
+ hold the same value: matching on the value alone would bind to it."""
87
88
def __init__(self, hidden: int = 16, eps: float = 1e-5):
89
super().__init__(hidden, eps)
@@ -96,8 +95,7 @@ class LiteralEpsRMSNorm(RMSNorm):
95
96
class AmbiguousEpsRMSNorm(nn.Module):
97
"""Two attributes hold the eps value, and the forward reads the second, so
99
- their order cannot pick it.
100
- """
98
+ their order cannot pick it."""
99
100
def __init__(self, hidden: int = 16, eps: float = 1e-6):
101
super().__init__()
@@ -233,8 +231,7 @@ def test_weightless_norm_has_no_hidden_size(default_vllm_config):
231
232
def test_fused_rms_norm_op_default_eps(default_vllm_config):
233
"""`torch.nn.RMSNorm` (a single `F.rms_norm` call) matches via the fast path;
236
- its default `eps=None` resolves to `finfo(dtype).eps` in `fuse`.
237
- """
234
+ its default `eps=None` resolves to `finfo(dtype).eps` in `fuse`."""
235
from vllm.model_executor.layers.layernorm import RMSNorm as VLLMRMSNorm
236
237
with torch.device("meta"):
@@ -250,8 +247,7 @@ def test_fused_rms_norm_op_default_eps(default_vllm_config):
247
248
def test_eps_is_derived_per_instance(default_vllm_config):
249
"""Two instances of the same norm class with different eps must fuse to their
253
- own eps: the type-cached fuser holds only structure, not this value.
254
- """
250
+ own eps: the type-cached fuser holds only structure, not this value."""
251
with torch.device("meta"):
252
for eps in (1e-5, 1e-6):
253
module = RMSNorm(16, eps=eps)
@@ -263,8 +259,7 @@ def test_eps_is_derived_per_instance(default_vllm_config):
259
@pytest.mark.parametrize("cls", [NamedEpsRMSNorm, ToleranceRMSNorm])
260
def test_eps_attr_is_found_by_value_not_name(cls, default_vllm_config):
261
"""The eps attribute is identified by holding the traced value, so a norm
266
- stays per-instance correct whatever it names it.
267
- """
262
+ stays per-instance correct whatever it names it."""
263
with torch.device("meta"):
264
for eps in (1e-5, 1e-6):
265
module = cls(16, eps=eps)
@@ -276,8 +271,7 @@ def test_eps_attr_is_found_by_value_not_name(cls, default_vllm_config):
271
272
def test_literal_eps_is_not_mistaken_for_an_attribute(default_vllm_config, caplog):
273
"""A literal eps is recognised as coming from no attribute, even when one
279
- holds the same value, and is taken from the traced source instead.
280
- """
274
+ holds the same value, and is taken from the traced source instead."""
275
logger = "vllm.model_executor.models.transformers.fusers.rms_norm"
276
with caplog.at_level("DEBUG", logger=logger), torch.device("meta"):
277
module = LiteralEpsRMSNorm()
@@ -290,8 +284,7 @@ def test_literal_eps_is_not_mistaken_for_an_attribute(default_vllm_config, caplo
284
285
def test_ambiguous_eps_attrs_are_disambiguated(default_vllm_config):
286
"""When several attributes hold the eps value, the one the forward actually
293
- reads is identified, and they are all left as they were found.
294
- """
287
+ reads is identified, and they are all left as they were found."""
288
with torch.device("meta"):
289
module = AmbiguousEpsRMSNorm(16, eps=1e-6)
290
before = dict(vars(module))
@@ -308,8 +301,7 @@ def test_ambiguous_eps_attrs_are_disambiguated(default_vllm_config):
301
def test_fused_norm_is_gather_capable(default_vllm_config):
302
"""Every weighted fused norm is emitted gather-capable, so a norm on a head-sharded
303
projection (OLMoE-style) self-corrects at runtime with no QKV-specific
311
- plumbing. A full-width input skips the gather and equals a plain norm.
312
- """
304
+ plumbing. A full-width input skips the gather and equals a plain norm."""
305
from vllm.model_executor.layers.layernorm import GemmaRMSNorm, RMSNorm
306
from vllm.model_executor.models.transformers.fusers import rms_norm
307
@@ -331,8 +323,7 @@ def test_fused_norm_is_gather_capable(default_vllm_config):
323
324
def test_gathered_norm_rejects_uneven_sharding(default_vllm_config):
325
"""A sharded input (narrower than the full-width weight) that does not tile
334
- the weight evenly across ranks is rejected before any collective.
335
- """
326
+ the weight evenly across ranks is rejected before any collective."""
327
from vllm.model_executor.models.transformers.fusers import rms_norm
328
329
norm = rms_norm.TPAwareRMSNorm(hidden_size=8, eps=1e-6)
tests/models/transformers/test_layer_registry.py
+2
-4
@@ -28,8 +28,7 @@ def fake_hw_layernorm(monkeypatch):
28
A `SimpleNamespace` stands in for the module: `importlib.import_module`
29
returns it from `sys.modules` and `getattr` resolves `RMSNorm`, while its
30
attributes are set at construction (no `ModuleType` attribute-set that mypy
31
- rejects, no constant `setattr` that ruff rejects).
32
- """
31
+ rejects, no constant `setattr` that ruff rejects)."""
32
module = types.SimpleNamespace(RMSNorm=type("HwRMSNorm", (), {}))
33
monkeypatch.setitem(sys.modules, HW_MODULE, module)
34
return module
@@ -82,8 +81,7 @@ def test_act_and_mul_falls_back_for_unknown_activation(
81
@pytest.fixture(scope="module")
82
def tiny_llama_path(tmp_path_factory):
83
"""A randomly-initialized microscopic Llama saved to disk (with an ungated
85
- tokenizer) so vLLM can load it like any local checkpoint.
86
- """
84
+ tokenizer) so vLLM can load it like any local checkpoint."""
85
from transformers import AutoTokenizer, LlamaConfig, LlamaForCausalLM
86
87
tokenizer = AutoTokenizer.from_pretrained("hf-internal-testing/llama-tokenizer")
tests/multimodal/media/test_audio.py
+6
-12
@@ -54,8 +54,7 @@ def test_audio_media_io_load_base64(dummy_audio_bytes):
54
def test_audio_media_io_load_base64_rejects_malformed(dummy_audio_bytes):
55
"""Malformed base64 must surface as a ValueError so the server answers 400.
56
Without strict decoding the bad characters are dropped, the garbage reaches
57
- libsndfile, and the client gets a 500 instead.
58
- """
57
+ libsndfile, and the client gets a 500 instead."""
58
encoded = base64.b64encode(dummy_audio_bytes).decode("utf-8")
59
malformed = encoded[:8] + "!!!@@@###" + encoded[8:]
60
@@ -134,8 +133,7 @@ def test_small_file_passes_memory_guard():
133
134
def test_memory_guard_rejects_large_allocation():
135
"""A file whose frames*channels*4 exceeds the byte limit must be
137
- rejected before allocating the buffer.
138
- """
136
+ rejected before allocating the buffer."""
137
# 100_000 frames * 8 channels * 4 bytes = 3.2 MB
138
payload = _make_flac_bytes(frames=100_000, channels=8, samplerate=48000)
139
# Set limit to 1 MiB — should reject
@@ -150,8 +148,7 @@ def test_memory_guard_rejects_large_allocation():
148
149
def test_forged_samplerate_rejected_by_memory_guard():
150
"""The PoC scenario: high sample rate fools the duration guard but
153
- the memory guard catches the large frame*channel allocation.
154
- """
151
+ the memory guard catches the large frame*channel allocation."""
152
# Forged high sample rate: 655350 Hz, 8 channels, 1M frames
153
# Duration guard sees: 1_000_000 / 655_350 = 1.5s → passes
154
# Memory: 1_000_000 * 8 * 4 = 32 MB
@@ -212,8 +209,7 @@ def test_load_audio_unknown_backend_rejected(dummy_audio_bytes):
209
210
def test_load_audio_auto_falls_back_without_torchcodec(dummy_audio_bytes):
211
"""`auto` must fall back to the soundfile → PyAV chain when torchcodec
215
- is not importable.
216
- """
212
+ is not importable."""
213
ref_audio, ref_sr = load_audio_soundfile(BytesIO(dummy_audio_bytes), sr=None)
214
with patch.object(audio_module, "load_audio_torchcodec", side_effect=ImportError):
215
audio, sr = load_audio(BytesIO(dummy_audio_bytes), sr=None, backend="auto")
@@ -223,8 +219,7 @@ def test_load_audio_auto_falls_back_without_torchcodec(dummy_audio_bytes):
219
220
def test_load_audio_auto_falls_back_without_ffmpeg(dummy_audio_bytes):
221
"""Torchcodec installed but system ffmpeg missing (`AudioDecoder is None`)
226
- must surface as ImportError so `auto` falls back to soundfile → PyAV.
227
- """
222
+ must surface as ImportError so `auto` falls back to soundfile → PyAV."""
223
ref_audio, ref_sr = load_audio_soundfile(BytesIO(dummy_audio_bytes), sr=None)
224
with patch.object(audio_module, "AudioDecoder", None):
225
with pytest.raises(ImportError, match="torchcodec audio backend"):
@@ -239,8 +234,7 @@ def test_load_audio_auto_falls_back_when_libtorchcodec_unloadable(
234
):
235
"""Torchcodec loads its ffmpeg-backed core lazily at decoder construction;
236
a "Could not load libtorchcodec" RuntimeError there (no system ffmpeg)
242
- must also surface as ImportError so `auto` falls back.
243
- """
237
+ must also surface as ImportError so `auto` falls back."""
238
239
class _UnloadableDecoder:
240
def __init__(self, *args, **kwargs):
tests/multimodal/media/test_connector.py
+1
-2
@@ -228,8 +228,7 @@ async def test_fetch_image_local_files_with_space_in_name(image_url: str):
228
@pytest.mark.asyncio
229
async def test_fetch_image_data_url_with_params():
230
"""RFC 2397 allows parameters between the mediatype and the base64
231
- marker; they must not be rejected or leak into the media type.
232
- """
231
+ marker; they must not be rejected or leak into the media type."""
232
connector = MediaConnector()
233
234
image = Image.new("RGB", (4, 4), color=(255, 0, 0))
tests/multimodal/media/test_video.py
+5
-10
@@ -398,8 +398,7 @@ def test_pynvvideocodec_unrelated_error_propagates(
398
399
class TestMergeKwargsGpuBackendPolicy:
400
"""Verify that merge_kwargs blocks request-level GPU backend selection
401
- when the static (engine-level) config did not configure that backend.
402
- """
401
+ when the static (engine-level) config did not configure that backend."""
402
403
def test_pynvvideocodec_requires_gpu(self):
404
assert VIDEO_LOADER_REGISTRY.backend_requires_gpu(PYNVVIDEOCODEC_VIDEO_BACKEND)
@@ -492,8 +491,7 @@ class TestMergeKwargsGpuBackendPolicy:
491
492
def test_static_pynv_with_different_runtime_gpu_backend(self):
493
"""If static sets pynv via video_backend but runtime tries to set it
495
- via the codec-level 'backend' key (without a static match), strip it.
496
- """
494
+ via the codec-level 'backend' key (without a static match), strip it."""
495
result = VideoMediaIO.merge_kwargs(
496
default_kwargs={"video_backend": "pynvvideocodec"},
497
runtime_kwargs={"backend": "pynvvideocodec"},
@@ -532,8 +530,7 @@ class TestMergeKwargsGpuBackendPolicy:
530
def test_strips_request_level_device(self):
531
"""The decode device is a startup-only knob: a request must not move
532
decoding onto the GPU when the startup config did not opt in, nor off
535
- it when it did.
536
- """
533
+ it when it did."""
534
result = VideoMediaIO.merge_kwargs(
535
default_kwargs={"backend": "torchcodec"},
536
runtime_kwargs={"device": "cuda"},
@@ -558,8 +555,7 @@ class TestMergeKwargsGpuBackendPolicy:
555
def test_switching_backend_drops_stale_codec_options(default_kwargs):
556
"""Codec-specific options from the static config must not leak into a
557
different codec backend selected per-request, where they would fail the
561
- new backend's option validation.
562
- """
558
+ new backend's option validation."""
559
result = VideoMediaIO.merge_kwargs(
560
default_kwargs={**default_kwargs, "num_frames": 8},
561
runtime_kwargs={"backend": "opencv"},
@@ -581,8 +577,7 @@ def test_pynvvc_frames_normalized_to_nhwc(layout: str):
577
"""PyNvVideoCodec frame batches are normalized to NHWC regardless of the
578
per-frame layout the decoder emits (it has varied across versions), so the
579
HF video processors (which materialize a PIL image per frame) receive the
584
- same NHWC shape as every other video backend.
585
- """
580
+ same NHWC shape as every other video backend."""
581
torch = pytest.importorskip("torch")
582
583
n, h, w, c = 4, 5, 6, 3
tests/multimodal/test_hasher.py
+1
-2
@@ -141,8 +141,7 @@ def test_hash_collision_video_num_frames():
141
142
def test_hash_video_tensor_frames():
143
"""Videos holding tensor frames (e.g. NVDEC-decoded) hash like
144
- array-framed ones, from the original bytes without a D2H copy.
145
- """
144
+ array-framed ones, from the original bytes without a D2H copy."""
145
source = b"x" * 100
146
147
def item_for_hash(frames):
tests/multimodal/test_image.py
+1
-2
@@ -80,8 +80,7 @@ def test_l_mode_no_trns_to_rgb():
80
81
def test_exif_transpose_normalizes_orientation():
82
"""Image with EXIF orientation 3 (180-degree rotation) should be
83
- normalized so pixel data matches visual display.
84
- """
83
+ normalized so pixel data matches visual display."""
84
# Built synthetically because the existing assets are PNGs which
85
# don't carry EXIF orientation metadata; we need a JPEG with an
86
# injected EXIF orientation=3 tag.
tests/multimodal/test_parse.py
+2
-4
@@ -59,8 +59,7 @@ def test_frame_size_hwc_chw(frame):
59
def test_video_with_metadata_tensor_passthrough():
60
"""Tensor frames pass through unchanged regardless of device: HF video
61
processors accept tensors, and device-resident frames (e.g. NVDEC-decoded)
62
- must not be copied back to host.
63
- """
62
+ must not be copied back to host."""
63
frames = torch.zeros((4, H, W, 3), dtype=torch.uint8)
64
video, metadata = MultiModalDataParser()._get_video_with_metadata(frames)
65
@@ -71,8 +70,7 @@ def test_video_with_metadata_tensor_passthrough():
70
@pytest.mark.skipif(not torch.cuda.is_available(), reason="Requires CUDA")
71
def test_video_with_metadata_keeps_device_tensor():
72
"""Device-resident frames (e.g. NVDEC-decoded) pass through as tensors,
74
- so a device-side HF processor can consume them without a D2H copy.
75
- """
73
+ so a device-side HF processor can consume them without a D2H copy."""
74
frames = torch.zeros((4, H, W, 3), dtype=torch.uint8, device="cuda")
75
video, metadata = MultiModalDataParser()._get_video_with_metadata(frames)
76
tests/multimodal/test_registry.py
+1
-2
@@ -57,8 +57,7 @@ def test_dummy_inputs_scheduler_budget(
57
@pytest.mark.core_model
58
def test_supports_multimodal_inputs(model_id, limit_mm_per_prompt, expected):
59
"""Test supports_multimodal_inputs returns correct boolean for various
60
- configs.
61
- """
60
+ configs."""
61
ctx = build_model_context(
62
model_id,
63
limit_mm_per_prompt=limit_mm_per_prompt,
tests/multimodal/test_utils.py
+1
-2
@@ -231,8 +231,7 @@ def test_group_and_batch_mm_items_splits_shared_data_by_dtype():
231
232
def test_encode_image_url_uncommon_format_has_valid_mimetype():
233
"""A format missing from mimetypes.types_map must still produce a
234
- well-formed type/subtype media type, not a bare 'image'.
235
- """
234
+ well-formed type/subtype media type, not a bare 'image'."""
235
# ".tga" is not registered in mimetypes.types_map, so it exercises the
236
# fallback path; Pillow can still encode it.
237
url = encode_image_url(Image.new("RGB", (2, 2)), format="TGA")
tests/multimodal/test_video.py
+10
-20
@@ -1214,8 +1214,7 @@ def test_torchcodec_backend_rejects_frame_recovery(dummy_video_path):
1214
@pytest.mark.skipif(not current_platform.is_cuda(), reason="Requires CUDA")
1215
def test_torchcodec_backend_cuda_decodes_on_gpu(dummy_video_path):
1216
"""With device="cuda", torchcodec decodes via NVDEC and keeps the frames
1217
- on the GPU instead of returning a host-side numpy array.
1218
- """
1217
+ on the GPU instead of returning a host-side numpy array."""
1218
pytest.importorskip("torchcodec")
1219
1220
with open(dummy_video_path, "rb") as f:
@@ -1508,8 +1507,7 @@ def test_glm46v_duration_estimation_from_fps():
1507
class TestGLMGASamplingCaps:
1508
"""Regression tests for GHSA-58v5-2m8f-94pr: request-controlled fps
1509
and max_frames must not create intermediate allocations larger than
1511
- the actual frame count.
1512
- """
1510
+ the actual frame count."""
1511
1512
@staticmethod
1513
def _source(
@@ -1563,8 +1561,7 @@ def test_glm5next_backend_selected_for_processor():
1561
"""Glm5NextVideoProcessor maps to the glm5next loader so only the
1562
sampled frames are decoded instead of the whole container. Both the
1563
borrowed-config spelling and the dedicated Glm5next class name (landing
1566
- with the new checkpoint) must resolve.
1567
- """
1564
+ with the new checkpoint) must resolve."""
1565
for name in ("Glm5NextVideoProcessor", "Glm5nextVideoProcessor"):
1566
assert VIDEO_LOADER_REGISTRY.get_backend_for_video_processor(name) == "glm5next"
1567
@@ -1586,8 +1583,7 @@ def test_glm5next_backend_indices_match_sampler(
1583
total_frames, original_fps, duration, fps, max_frames
1584
):
1585
"""The loader must select exactly the frames the processor's sampler
1589
- would, with target.fps mapping onto the raw-fps override.
1590
- """
1586
+ would, with target.fps mapping onto the raw-fps override."""
1587
from vllm.transformers_utils.processors.glm5next import (
1588
glm_sample_frame_indices,
1589
)
@@ -1615,8 +1611,7 @@ def test_glm5next_backend_indices_match_sampler(
1611
1612
def test_glm5next_backend_metadata_contract():
1613
"""create_hf_metadata reports the subset so the processor skips
1618
- re-sampling (do_sample_frames=False) and keeps the original totals.
1619
- """
1614
+ re-sampling (do_sample_frames=False) and keeps the original totals."""
1615
source = VideoSourceMetadata(total_frames_num=900, original_fps=30.0, duration=30.0)
1616
target = VideoTargetMetadata(num_frames=-1, fps=-1, max_duration=-1)
1617
indices = Glm5NextVideoBackend.compute_frames_index_to_sample(source, target)
@@ -1645,8 +1640,7 @@ def test_glm5next_backend_metadata_contract():
1640
1641
def _write_gray_video(tmp_path, total_frames, fps, size=(32, 32)):
1642
"""Synthetic clip whose frame i is flat gray level i (near-lossless under
1648
- mp4v), so a decoded frame's level maps back to its source index.
1649
- """
1643
+ mp4v), so a decoded frame's level maps back to its source index."""
1644
cv2 = pytest.importorskip("cv2")
1645
1646
path = tmp_path / f"gray_{total_frames}_{fps}.mp4"
@@ -1687,8 +1681,7 @@ class _CountingCap:
1681
def test_glm5next_backend_codec_parity(tmp_path, backend):
1682
"""Every codec samples the same GLM indices and decodes the same
1683
frames; the OpenCV seek reader and torchcodec batched index-exact decode
1690
- must agree.
1691
- """
1684
+ must agree."""
1685
if backend == "torchcodec":
1686
pytest.importorskip("torchcodec")
1687
@@ -1718,8 +1711,7 @@ def test_glm5next_backend_codec_parity(tmp_path, backend):
1711
1712
def test_glm5next_backend_decodes_only_sampled_frames(tmp_path):
1713
"""End to end over a synthetic clip: load_bytes returns exactly the
1721
- sampler's frame count, with the right frame content at each index.
1722
- """
1714
+ sampler's frame count, with the right frame content at each index."""
1715
pytest.importorskip("cv2")
1716
1717
total_frames, fps = 60, 10
@@ -1745,8 +1737,7 @@ def test_glm5next_backend_decodes_only_sampled_frames(tmp_path):
1737
1738
def test_glm5next_read_frames_seeks_past_large_gaps(tmp_path):
1739
"""Sparse targets must not walk the container: the stock reader grabs
1748
- every frame up to the last index; the GLM reader seeks instead.
1749
- """
1740
+ every frame up to the last index; the GLM reader seeks instead."""
1741
cv2 = pytest.importorskip("cv2")
1742
1743
total_frames, fps = 200, 10
@@ -1773,8 +1764,7 @@ def test_glm5next_read_frames_seeks_past_large_gaps(tmp_path):
1764
1765
def test_glm5next_read_frames_dense_walk_matches_stock(tmp_path):
1766
"""Dense targets keep the sequential walk (seeking would be slower) and
1776
- return the same frames as the stock reader.
1777
- """
1767
+ return the same frames as the stock reader."""
1768
cv2 = pytest.importorskip("cv2")
1769
1770
total_frames, fps = 120, 10
tests/parser/cohere/test_reasoning.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Reasoning extraction, reasoning-end gating and parser selection for the
4
-unified Cohere Command parser.
5
-"""
4
+unified Cohere Command parser."""
5
6
from __future__ import annotations
7
tests/parser/cohere/utils.py
+3
-6
@@ -76,8 +76,7 @@ def token_deltas(
76
) -> list[tuple[str, list[int]]]:
77
"""Split ``text`` into ``(delta_text, delta_token_ids)`` steps of
78
``chunk_size`` tokens, buffering incomplete multi-byte sequences (trailing
79
- U+FFFD) into the next step as real streaming does.
80
- """
79
+ U+FFFD) into the next step as real streaming does."""
80
ids = tokenizer.encode(text)
81
deltas: list[tuple[str, list[int]]] = []
82
prev = ""
@@ -101,8 +100,7 @@ def make_parser(
100
model_config=None,
101
) -> Parser:
102
"""Resolve the unified Cohere parser through ``ParserManager`` by registry
104
- name (``cohere_command3`` / ``cohere_command4``).
105
- """
103
+ name (``cohere_command3`` / ``cohere_command4``)."""
104
cls = ParserManager.get_parser(name, name, enable_auto_tools=True)
105
assert cls is not None
106
return cls(
@@ -119,8 +117,7 @@ def drive_parser(
117
deltas: list[tuple[str, list[int]]],
118
) -> list[DeltaMessage]:
119
"""Feed ``deltas`` through ``parse_delta`` (flushing on the last one) and
122
- return the non-``None`` messages in order.
123
- """
120
+ return the non-``None`` messages in order."""
121
out: list[DeltaMessage] = []
122
for i, (text, ids) in enumerate(deltas):
123
delta = parser.parse_delta(text, ids, request, finished=i == len(deltas) - 1)
tests/parser/engine/test_deepseek_v32.py
+1
-2
@@ -289,8 +289,7 @@ class TestStreaming:
289
290
class TestMissingFunctionCallsWrapper:
291
"""An invoke without the ``<|DSML|function_calls>`` wrapper is still a
292
- tool call (V3.2 counterpart of #48931).
293
- """
292
+ tool call (V3.2 counterpart of #48931)."""
293
294
def test_non_streaming(self, mock_tokenizer, mock_request):
295
text = _invoke("fn", _param("k", "true", "v"))
tests/parser/engine/test_deepseek_v4.py
+6
-12
@@ -334,8 +334,7 @@ class TestMissingToolCallsWrapper:
334
):
335
"""Text after a tool block is dropped whether or not the closing
336
wrapper is present, so a missing ``</|DSML|tool_calls>`` does not
337
- change what the client sees.
338
- """
337
+ change what the client sees."""
338
text = "pre\n" + self._ORPHAN
339
if trailing_end:
340
text += DSML_TOOL_END
@@ -916,8 +915,7 @@ class TestParallelUnwrapping:
915
916
class TestStreamingWrapperConsistency:
917
"""Streamed arg deltas must stay consistent with final extraction
919
- when wrapper params like 'arguments' are unwrapped.
920
- """
918
+ when wrapper params like 'arguments' are unwrapped."""
919
920
def test_streaming_wrapper_unwrap_consistency(self, mock_tokenizer, mock_request):
921
tool = _make_tool("get_weather", {"location": {"type": "string"}})
@@ -1198,8 +1196,7 @@ class TestDelegatingParserLargeDelta:
1196
)
1197
def test_eos_not_leaked_when_reasoning_never_ends(self, chunk_size):
1198
"""EOS must not leak into reasoning_content when the model never
1201
- emits </think> (generation ends while still in REASONING state).
1202
- """
1199
+ emits </think> (generation ends while still in REASONING state)."""
1200
eos_text = "<|end▁of▁sentence|>"
1201
eos_id = 128801
1202
vocab = {
@@ -1288,8 +1285,7 @@ class TestMalformedDsmlNoise:
1285
self, mock_tokenizer, mock_request, wrapper
1286
):
1287
"""Like the real wrapper, a corrupted one inside ``<think>`` closes
1291
- the reasoning block and starts the tool call.
1292
- """
1288
+ the reasoning block and starts the tool call."""
1289
text = f"thinking{wrapper}\n{self._INNER}"
1290
parser = self._parser(mock_tokenizer, thinking=True)
1291
reasoning, content = parser.extract_reasoning(text, mock_request)
@@ -1333,8 +1329,7 @@ class TestMalformedDsmlNoise:
1329
prose mention of the real wrapper: the opener starts a tool block and
1330
the rest of the message is dropped. That is pre-existing behavior of
1331
``<|DSML|tool_calls>``; the variants must not differ from it either
1336
- way.
1337
- """
1332
+ way."""
1333
template = "The opener looks like {} and then params follow. Done."
1334
text = template.format(wrapper)
1335
reference = template.format(DSML_TOOL_START)
@@ -1358,8 +1353,7 @@ class TestMalformedDsmlNoise:
1353
@pytest.mark.parametrize("chunk_size", [1, 3, None], ids=lambda c: f"chunk={c}")
1354
def test_delegating_parser_corrupted_wrapper(self, wrapper, chunk_size):
1355
"""The serving-layer shape: reasoning and tool adapters on separate
1361
- engines, with the corrupted opener arriving as plain text.
1362
- """
1356
+ engines, with the corrupted opener arriving as plain text."""
1357
tokens = _dsv4_tokens(
1358
reasoning="Checking the weather.",
1359
tool_name="get_weather",
tests/parser/engine/test_delegating_replay.py
+1
-2
@@ -174,8 +174,7 @@ _TOOL_CALL_SAMPLES = [
174
)
175
def test_delegating_parse_tool_choice_none(parser_cls, parser_name, sample):
176
"""Non-streaming parse() with tool_choice='none' via DelegatingParser
177
- must not leak special tokens into content.
178
- """
177
+ must not leak special tokens into content."""
178
tokenizer = make_mock_tokenizer(sample)
179
validated_tools = (
180
_TOOLS_VALIDATOR.validate_python(sample.tools) if sample.tools else None
tests/parser/engine/test_engine.py
+19
-38
@@ -275,8 +275,7 @@ class TestStreaming:
275
276
def test_unmatched_close_brace_does_not_poison_depth(self):
277
"""A stray } in malformed JSON must not kill streaming for
278
- all subsequent content.
279
- """
278
+ all subsequent content."""
279
engine = StreamingParserEngine(_hermes_config(), tokenizer=None)
280
engine.feed("<tool_call>", [])
281
@@ -292,8 +291,7 @@ class TestStreaming:
291
292
def test_json_args_no_premature_close_brace(self):
293
"""Closing braces of the top-level JSON shouldn't be streamed
295
- until confirmed by the end tag.
296
- """
294
+ until confirmed by the end tag."""
295
engine = StreamingParserEngine(_hermes_config(), tokenizer=None)
296
297
engine.feed("<tool_call>", [])
@@ -348,8 +346,7 @@ class TestLexerBufferFlush:
346
347
def test_buffered_prefix_emitted_in_current_state(self):
348
"""Text buffered by the lexer (e.g. '<') must be emitted as
351
- REASONING_CHUNK before THINK_END transitions to CONTENT.
352
- """
349
+ REASONING_CHUNK before THINK_END transitions to CONTENT."""
350
engine = StreamingParserEngine(_think_config(), _make_think_tokenizer())
351
352
events = engine.feed("<think>", [_START_ID])
@@ -387,13 +384,11 @@ class TestLexerBufferFlush:
384
385
class TestTokenIdFiltering:
386
"""When token IDs are available, lex-matched terminals that also
390
- have token_id_terminal entries should be demoted to content.
391
- """
387
+ have token_id_terminal entries should be demoted to content."""
388
389
def test_lex_matched_terminal_demoted_after_token_ids_seen(self):
390
"""After receiving token IDs, text that matches a token-ID
395
- terminal should be treated as content, not trigger a transition.
396
- """
391
+ terminal should be treated as content, not trigger a transition."""
392
engine = StreamingParserEngine(_hermes_config(), _make_hermes_tokenizer())
393
394
# First feed with a non-special token ID to set _ever_had_token_ids
@@ -414,8 +409,7 @@ class TestTokenIdFiltering:
409
410
def test_scanner_matched_terminal_bypasses_filter(self):
411
"""PreLexedTerminals from the scanner bypass the filter and
417
- still trigger state transitions.
418
- """
412
+ still trigger state transitions."""
413
engine = StreamingParserEngine(_hermes_config(), _make_hermes_tokenizer())
414
415
events = engine.feed("<tool_call>", [_TOOL_START_ID])
@@ -428,8 +422,7 @@ class TestTokenIdFiltering:
422
423
def test_no_filtering_without_token_ids(self):
424
"""When no token IDs are ever provided (non-streaming),
431
- text matching still triggers transitions.
432
- """
425
+ text matching still triggers transitions."""
426
engine = StreamingParserEngine(_hermes_config(), _make_hermes_tokenizer())
427
428
events = engine.feed('<tool_call>{"name": "f"}</tool_call>', [])
@@ -441,8 +434,7 @@ class TestTokenIdFiltering:
434
435
def test_mixed_text_then_real_tool_call(self):
436
"""Text mentioning tool syntax followed by a real special-token
444
- tool call.
445
- """
437
+ tool call."""
438
engine = StreamingParserEngine(_hermes_config(), _make_hermes_tokenizer())
439
440
events1 = engine.feed("Mention <tool_call> in text. ", [1, 2, 3, 4])
@@ -502,8 +494,7 @@ class TestReasoningTokenCounts:
494
495
def _func_prefix_config() -> ParserEngineConfig:
496
"""Config mixing token-ID terminals (TOOL_START/END) with
505
- text-only terminals (FUNC_PREFIX) and fallback transitions.
506
- """
497
+ text-only terminals (FUNC_PREFIX) and fallback transitions."""
498
return ParserEngineConfig(
499
name="func_prefix_test",
500
terminals={
@@ -572,13 +563,11 @@ def _make_func_prefix_tokenizer():
563
564
class TestTextOnlyFallbackFiltering:
565
"""When token IDs are available, transitions marked
575
- skip_in_token_id_mode should be skipped.
576
- """
566
+ skip_in_token_id_mode should be skipped."""
567
568
def test_func_prefix_in_prose_demoted_in_strict_mode(self):
569
"""<function=get_time> in prose should NOT trigger a tool call
580
- when strict mode is active.
581
- """
570
+ when strict mode is active."""
571
engine = StreamingParserEngine(
572
_func_prefix_config(), _make_func_prefix_tokenizer()
573
)
@@ -595,8 +584,7 @@ class TestTextOnlyFallbackFiltering:
584
585
def test_normal_flow_after_tool_start_still_works(self):
586
"""TOOL_START (special token) -> FUNC_PREFIX (text) should
598
- still parse a tool call normally in strict mode.
599
- """
587
+ still parse a tool call normally in strict mode."""
588
engine = StreamingParserEngine(
589
_func_prefix_config(), _make_func_prefix_tokenizer()
590
)
@@ -616,8 +604,7 @@ class TestTextOnlyFallbackFiltering:
604
605
def test_fallback_fires_without_token_ids(self):
606
"""When no token IDs are provided, fallback transitions should
619
- still fire normally.
620
- """
607
+ still fire normally."""
608
engine = StreamingParserEngine(
609
_func_prefix_config(), _make_func_prefix_tokenizer()
610
)
@@ -631,8 +618,7 @@ class TestTextOnlyFallbackFiltering:
618
619
def test_tool_between_fallback_blocked_in_strict_mode(self):
620
"""The (TOOL_BETWEEN, FUNC_PREFIX) fallback should also be
634
- blocked in strict mode.
635
- """
621
+ blocked in strict mode."""
622
engine = StreamingParserEngine(
623
_func_prefix_config(), _make_func_prefix_tokenizer()
624
)
@@ -662,8 +648,7 @@ class TestNoUnusedTokenizerAttr:
648
class TestArgsResetOnReentry:
649
"""When leaving TOOL_ARGS and later re-entering (e.g. two tool
650
calls), the entering-TOOL_ARGS block resets args tracking. The
665
- redundant reset on exit was removed.
666
- """
651
+ redundant reset on exit was removed."""
652
653
@staticmethod
654
def _multi_tool_config() -> ParserEngineConfig:
@@ -738,8 +723,7 @@ class TestArgsResetOnReentry:
723
724
class TestToolPreambleFinish:
725
"""finish() in TOOL_PREAMBLE state emits TOOL_CALL_END when a tool
741
- call was started (tool_index >= 0), but not when tool_index is -1.
742
- """
726
+ call was started (tool_index >= 0), but not when tool_index is -1."""
727
728
@staticmethod
729
def _preamble_with_tool_call_start_config() -> ParserEngineConfig:
@@ -798,8 +782,7 @@ class TestToolPreambleFinish:
782
783
class TestRegexTerminalInfraRemoved:
784
"""TerminalDef.priority, LexerShape.regex_terminals, and the regex
801
- matching loop were removed.
802
- """
785
+ matching loop were removed."""
786
787
def test_terminal_def_no_priority(self):
788
import regex as re
@@ -824,8 +807,7 @@ class TestRegexTerminalInfraRemoved:
807
808
class TestMultiCharTerminalInArgs:
809
"""Regression: multi-char terminals falling through in TOOL_ARGS
827
- must be fed char-by-char via _feed_args_text, not _feed_args_char.
828
- """
810
+ must be fed char-by-char via _feed_args_text, not _feed_args_char."""
811
812
@staticmethod
813
def _newline_config() -> ParserEngineConfig:
@@ -917,8 +899,7 @@ class TestSkipToolParsing:
899
900
def _message_header_config(reasoning_end: bool) -> ParserEngineConfig:
901
"""MESSAGE_HEADER-based grammar whose tool opener optionally carries
920
- REASONING_END, mirroring the two shapes a transition table can take.
921
- """
902
+ REASONING_END, mirroring the two shapes a transition table can take."""
903
return ParserEngineConfig(
904
name=f"message_header_test_{reasoning_end}",
905
initial_state=ParserState.MESSAGE_HEADER,
tests/parser/engine/test_gemma4_streaming_reasoning.py
+9
-18
@@ -1097,8 +1097,7 @@ class TestNonStreamingReasoningPlusToolCalls:
1097
1098
def test_both_extractions_independent(self, parser, request_obj):
1099
"""Calling extract_reasoning then extract_tool_calls on the same
1100
- parser instance should both work (each resets the engine).
1101
- """
1100
+ parser instance should both work (each resets the engine)."""
1101
model_output = FULL_MODEL_OUTPUT
1102
1103
reasoning, _ = parser.extract_reasoning(model_output, request_obj)
@@ -1112,8 +1111,7 @@ class TestNonStreamingReasoningPlusToolCalls:
1111
1112
class TestAdapterExtractReasoning:
1113
"""The reasoning adapter's extract_reasoning uses skip_tool_parsing
1115
- so tool call text is preserved as content for the tool adapter.
1116
- """
1114
+ so tool call text is preserved as content for the tool adapter."""
1115
1116
@pytest.fixture
1117
def adapter(self, mock_tokenizer):
@@ -1154,8 +1152,7 @@ class TestAdapterExtractReasoning:
1152
class TestGemma4SchemaAwareTypeCoercion:
1153
"""Verify that streaming and non-streaming produce identical
1154
type-fixed arguments when tool schemas declare string parameters
1157
- but the model outputs bare numbers/booleans.
1158
- """
1155
+ but the model outputs bare numbers/booleans."""
1156
1157
@pytest.fixture
1158
def tools(self):
@@ -1185,8 +1182,7 @@ class TestGemma4SchemaAwareTypeCoercion:
1182
1183
def test_streaming_string_param_not_coerced(self, parser_with_tools, mock_request):
1184
"""A numeric value for a string-typed param must remain a string
1188
- in the streamed output, matching the non-streaming result.
1189
- """
1185
+ in the streamed output, matching the non-streaming result."""
1186
chunks = [
1187
"<|tool_call>",
1188
"call:update_record{",
@@ -1217,8 +1213,7 @@ class TestGemma4SchemaAwareTypeCoercion:
1213
1214
def test_streaming_matches_non_streaming(self, parser_with_tools, mock_request):
1215
"""Concatenated streaming deltas must produce the same arguments
1220
- as non-streaming extraction.
1221
- """
1216
+ as non-streaming extraction."""
1217
text = "<|tool_call>call:update_record{zipcode:12345}<tool_call|>"
1218
1219
non_streaming = parser_with_tools.extract_tool_calls(text, mock_request)
@@ -1239,8 +1234,7 @@ class TestGemma4SchemaAwareTypeCoercion:
1234
1235
class TestGemma4SchemaCoercionBoolNumberNull:
1236
"""Verify that _fix_arg_types coerces string values to non-string
1242
- schema types for the Gemma4 parser.
1243
- """
1237
+ schema types for the Gemma4 parser."""
1238
1239
@pytest.fixture
1240
def tools(self):
@@ -1301,8 +1295,7 @@ class TestGemma4SchemaCoercionBoolNumberNull:
1295
1296
def test_streaming_type_stability(self, parser_with_tools, mock_request):
1297
"""Values streamed incrementally must not cause prefix
1304
- incompatibility when types are coerced.
1305
- """
1298
+ incompatibility when types are coerced."""
1299
text = (
1300
"<|tool_call>call:configure{"
1301
"enabled:true,"
@@ -1402,8 +1395,7 @@ BARE_THOUGHT_SEQUENCE.append((TOOL_CALL_END_ID, "<tool_call|>"))
1395
class TestBareThoughtWithoutChannelOpener:
1396
"""When the model omits <|channel> and starts with bare ``thought``,
1397
the parser should auto-inject the channel opener so reasoning is
1405
- captured correctly.
1406
- """
1398
+ captured correctly."""
1399
1400
@pytest.fixture
1401
def bare_thought_tokenizer(self):
@@ -1474,8 +1466,7 @@ class TestBareThoughtWithoutChannelOpener:
1466
1467
def test_bare_thought_token_at_end_of_stream(self, request_obj):
1468
"""When the stream ends with just "thought" (no \\n), the parser
1477
- should treat it as the thought prefix token, not real reasoning.
1478
- """
1469
+ should treat it as the thought prefix token, not real reasoning."""
1470
seq: list[tuple[int, str]] = [
1471
(CHANNEL_START_ID, "<|channel>"),
1472
(3000, "thought"),
tests/parser/engine/test_glm47_moe.py
+2
-4
@@ -61,8 +61,7 @@ class TestIsReasoningEnd:
61
62
def test_previous_turn_tool_call_ignored(self, parser):
63
"""A finished tool call from an earlier turn says nothing about the
64
- turn currently being generated.
65
- """
64
+ turn currently being generated."""
65
prompt = [THINK_S, TEXT, TOOL_S, TEXT, TOOL_E, OBSERVATION, TEXT, ASSISTANT]
66
assert not parser.is_reasoning_end(prompt)
67
@@ -89,8 +88,7 @@ class TestExtractContentIds:
88
89
def test_falls_back_to_tool_call(self, parser):
90
"""Without ``</think>``, content starts at the opener itself so the
92
- tool parser still receives a well-formed call.
93
- """
91
+ tool parser still receives a well-formed call."""
92
ids = [THINK_S, TEXT, TOOL_S, 30, TOOL_E]
93
assert parser.extract_content_ids(ids) == [TOOL_S, 30, TOOL_E]
94
tests/parser/engine/test_inkling.py
+10
-20
@@ -70,8 +70,7 @@ _MARKERS = sorted(_TML_VOCAB, key=len, reverse=True)
70
def _tokenize(text: str) -> list[tuple[int, str]]:
71
"""Tokenize like the real stream: markers are atomic special tokens,
72
plain text becomes one token per character (matching the mock
73
- tokenizer's ``chr``-based decode).
74
- """
73
+ tokenizer's ``chr``-based decode)."""
74
tokens: list[tuple[int, str]] = []
75
i = 0
76
while i < len(text):
@@ -88,8 +87,7 @@ def _tokenize(text: str) -> list[tuple[int, str]]:
87
88
def _stream(parser, request, text: str, chunk_size: int):
89
"""Stream production-shaped deltas: ``chunk_size`` tokens per delta,
91
- with delta_token_ids covering every token (specials and text).
92
- """
90
+ with delta_token_ids covering every token (specials and text)."""
91
tokens = _tokenize(text)
92
results = []
93
previous_text = ""
@@ -121,8 +119,7 @@ def _stream(parser, request, text: str, chunk_size: int):
119
def _stream_text_only(parser, request, text: str, chunk_size: int):
120
"""Stream text-only deltas (no token ids), chunked at arbitrary
121
character boundaries — exercises the text-lexing fallback path,
124
- including markers split across chunks.
125
- """
122
+ including markers split across chunks."""
123
results = []
124
previous_text = ""
125
for start in range(0, len(text), chunk_size):
@@ -173,8 +170,7 @@ def _stream_delegating(parser, request, text, chunk_size, prompt_token_ids):
170
"""Stream ``text`` through ``DelegatingParser.parse_delta``, ``chunk_size``
171
tokens per delta; return ``(content, reasoning, ordered tool names,
172
ordered tool arguments)``. Arguments arrive in fragments, so they are
176
- concatenated per tool index.
177
- """
173
+ concatenated per tool index."""
174
tokens = _tokenize(text)
175
content, reasoning = "", ""
176
tools: dict[int, str] = {}
@@ -526,8 +522,7 @@ class TestToolCallFiltering:
522
"""Inkling equivalents of the generic tool-call-filtering replay tests
523
(Inkling is excluded from those in test_replay.py: its structural
524
role/kind tokens and shared block-end token don't fit the generic
529
- reasoning/tool split model).
530
- """
525
+ reasoning/tool split model)."""
526
527
def test_skip_tool_parsing_round_trip(self, mock_tokenizer, mock_request):
528
# First pass (reasoning adapter, skip_tool_parsing): reasoning is
@@ -825,8 +820,7 @@ class TestDelegatingTwoPass:
820
):
821
"""The optional function name between ``<|message_model|>`` and the
822
content-kind marker is metadata: the buffered header must be
828
- discarded on the way out, not flushed into content.
829
- """
823
+ discarded on the way out, not flushed into content."""
824
tools = [_function_tool()]
825
mock_request.tools = tools
826
content, _, names, args = _stream_delegating(
@@ -843,8 +837,7 @@ class TestDelegatingTwoPass:
837
def test_content_state_tool_start_streaming(self, mock_tokenizer, mock_request):
838
"""Same opener reached from CONTENT rather than MESSAGE_HEADER: a
839
text block closed with no ``<|message_model|>`` before the tool
846
- block. Preceding text must reach content exactly once, unmarked.
847
- """
840
+ block. Preceding text must reach content exactly once, unmarked."""
841
tools = [_function_tool()]
842
mock_request.tools = tools
843
content, _, names, args = _stream_delegating(
@@ -866,8 +859,7 @@ def test_content_tool_start_emits_reasoning_end_in_reasoning_pass():
859
boundary (#49876), but the header-flush path
860
(MESSAGE_HEADER --END_MESSAGE--> CONTENT) reaches CONTENT without
861
one, so a tool block opening from there relies on this transition
869
- alone to hand off to the tool pass.
870
- """
862
+ alone to hand off to the tool pass."""
863
engine = StreamingParserEngine(inkling_config(), tokenizer=None)
864
engine.skip_tool_parsing = True
865
engine.reset(initial_state=ParserState.CONTENT)
@@ -884,8 +876,7 @@ def test_skip_reasoning_parsing_inert_for_shared_markers():
876
markers. Inkling has none — ``<|end_message|>`` is labelled THINK_END
877
yet also closes text, header, and tool blocks — so the flag must be
878
inert: a tool block still closes through its transition and following
887
- text returns to CONTENT instead of leaking into the argument stream.
888
- """
879
+ text returns to CONTENT instead of leaking into the argument stream."""
880
engine = StreamingParserEngine(inkling_config(), tokenizer=None)
881
engine.skip_reasoning_parsing = True
882
engine.reset(initial_state=ParserState.CONTENT)
@@ -905,8 +896,7 @@ class TestToolParserWithoutReasoningParser:
896
labels ``<|end_message|>`` as THINK_END; a bypass keyed on the label
897
would neutralize the closer of every block kind, leaking markers into
898
content and leaving tool calls unterminated. Structure must keep
908
- parsing exactly as with the reasoning parser attached.
909
- """
899
+ parsing exactly as with the reasoning parser attached."""
900
901
GEN_PROMPT = [_TML_VOCAB[MSG_MODEL]]
902
tests/parser/engine/test_nemotron_v3.py
+6
-12
@@ -56,8 +56,7 @@ def parser():
56
class TestNemotronSwap:
57
def test_enable_thinking_false_swaps(self, parser):
58
"""When enable_thinking=False, model output without think tags
59
- should have reasoning swapped to content.
60
- """
59
+ should have reasoning swapped to content."""
60
text = "The answer is 42."
61
request = _make_request(enable_thinking=False)
62
reasoning, content = parser.extract_reasoning(text, request)
@@ -74,8 +73,7 @@ class TestNemotronSwap:
73
74
def test_no_swap_when_content_exists(self, parser):
75
"""With enable_thinking=False but real </think> giving content,
77
- no swap occurs.
78
- """
76
+ no swap occurs."""
77
text = "Some reasoning.</think>Actual content here."
78
request = _make_request(enable_thinking=False)
79
reasoning, content = parser.extract_reasoning(text, request)
@@ -182,13 +180,11 @@ class TestStreaming:
180
181
class TestParseDeltaTokenIdFiltering:
182
"""parse_delta must not trigger tool call parsing when <tool_call>
185
- appears as regular text rather than as a special token ID.
186
- """
183
+ appears as regular text rather than as a special token ID."""
184
185
def test_tool_call_text_in_reasoning_is_not_parsed(self, parser):
186
"""Literal <tool_call> in model reasoning should be content,
190
- not a tool call.
191
- """
187
+ not a tool call."""
188
request = _make_request()
189
190
text = (
@@ -214,8 +210,7 @@ class TestParseDeltaTokenIdFiltering:
210
211
def test_special_token_id_still_triggers_tool_call(self, parser):
212
"""When the scanner matches a special token ID, the tool call
217
- must still be parsed correctly.
218
- """
213
+ must still be parsed correctly."""
214
request = _make_request()
215
216
parser.parse_delta(
@@ -255,8 +250,7 @@ class TestParseDeltaTokenIdFiltering:
250
251
def test_text_discussion_then_real_tool_call(self, parser):
252
"""Model discusses tool syntax in reasoning, then makes a real
258
- tool call via special tokens.
259
- """
253
+ tool call via special tokens."""
254
request = _make_request()
255
256
r1 = parser.parse_delta(
tests/parser/engine/test_parser_engine.py
+23
-46
@@ -323,8 +323,7 @@ class TestEventsToDelta:
323
324
def test_multiple_arg_chunks_same_batch_coalesced(self):
325
"""Multiple events for the same tool in one batch must produce
326
- at most one DeltaToolCall per index.
327
- """
326
+ at most one DeltaToolCall per index."""
327
engine = _make_engine()
328
events = [
329
SemanticEvent(EventType.TOOL_CALL_START, tool_index=0),
@@ -552,8 +551,7 @@ class TestPostToolContentDeferral:
551
"""Regression: content after TOOL_CALL_END in the same batch must not
552
produce a mixed DeltaMessage(content=..., tool_calls=...) — that causes
553
split_delta to reorder content before tool_calls, breaking the Responses
555
- API state machine.
556
- """
554
+ API state machine."""
555
556
def test_text_after_tool_end_deferred(self):
557
engine = _make_engine()
@@ -607,8 +605,7 @@ class TestPostToolContentDeferral:
605
"""Deferred content from batch N must not mix with arg-continuation
606
tool events in batch N+1 — that creates a DeltaMessage with both
607
content and nameless tool_calls, which crashes the Responses API
610
- state machine (name=None → Pydantic ValidationError).
611
- """
608
+ state machine (name=None → Pydantic ValidationError)."""
609
engine = _make_engine()
610
engine._content_has_nonws = True
611
@@ -837,8 +834,7 @@ class TestBuildExtractedResult:
834
835
class TestEngineBasedPath:
836
"""Tests for the _engine_based accumulation behavior in
840
- DelegatingParser.parse_delta.
841
- """
837
+ DelegatingParser.parse_delta."""
838
839
def test_engine_based_true_when_both_parsers_engine(self):
840
r = SimpleNamespace(engine_based_streaming=True)
@@ -884,8 +880,7 @@ class TestEngineBasedPath:
880
881
class TestParseTokenIdPassthrough:
882
"""parse() must forward model_output_token_ids to _single_pass_parse
887
- so that token-ID-based strict terminal matching is active.
888
- """
883
+ so that token-ID-based strict terminal matching is active."""
884
885
def test_literal_tool_tag_in_content_preserved_with_token_ids(self, mock_request):
886
engine = _make_engine(_hermes_config())
@@ -1109,8 +1104,7 @@ class TestAdapterFinishOnStreamEnd:
1104
1105
def test_lexer_buffer_flushed_on_finished(self):
1106
"""Text buffered as a potential terminal prefix must be emitted
1112
- as content when the stream ends.
1113
- """
1107
+ as content when the stream ends."""
1108
tokenizer = make_mock_tokenizer(_VOCAB)
1109
parser = _CombinedDelegating(tokenizer)
1110
request = _make_delegating_request()
@@ -1128,8 +1122,7 @@ class TestAdapterFinishOnStreamEnd:
1122
1123
def test_args_buffer_flushed_on_finished(self):
1124
"""Pending arg buffer text must be emitted when stream ends
1131
- mid-tool-call (closing brace held back in buffer).
1132
- """
1125
+ mid-tool-call (closing brace held back in buffer)."""
1126
tokenizer = make_mock_tokenizer(_VOCAB)
1127
parser = _CombinedDelegating(tokenizer)
1128
request = _make_delegating_request()
@@ -1365,8 +1358,7 @@ class TestSkipToolSpanForwarding:
1358
1359
class TestToolAdapterForwardsKwargs:
1360
"""ParserEngineToolAdapter.__init__ must forward **kwargs to the
1368
- parser engine class so chat_template_kwargs reach model parsers.
1369
- """
1361
+ parser engine class so chat_template_kwargs reach model parsers."""
1362
1363
@pytest.mark.parametrize(
1364
"enable_thinking,expected_state",
@@ -1396,8 +1388,7 @@ class TestToolAdapterForwardsKwargs:
1388
1389
class TestExtractContentIdsNoEmptyReturn:
1390
"""extract_content_ids must return input_ids (not []) when there is
1399
- no THINK_END token ID and _reasoning_ended is True.
1400
- """
1391
+ no THINK_END token ID and _reasoning_ended is True."""
1392
1393
_NO_THINK_CONFIG = ParserEngineConfig(name="no_think_end", token_id_terminals={})
1394
@@ -1795,8 +1786,7 @@ class TestDropSpecialTokens:
1786
1787
def test_drops_special_token_by_id_from_content(self):
1788
"""A special token (not a configured terminal) is dropped when
1798
- it arrives as its actual token ID.
1799
- """
1789
+ it arrives as its actual token ID."""
1790
config = ParserEngineConfig(
1791
name="drop_content_test",
1792
terminals={},
@@ -1831,8 +1821,7 @@ class TestDropSpecialTokens:
1821
1822
def test_drops_via_text_fallback_when_no_token_ids(self):
1823
"""When no token IDs are provided, text-based lexer catches
1834
- drop tokens as a fallback.
1835
- """
1824
+ drop tokens as a fallback."""
1825
engine = _make_engine(
1826
vocab=_DROP_VOCAB,
1827
special_tokens=list(_DROP_VOCAB.keys()),
@@ -1845,8 +1834,7 @@ class TestDropSpecialTokens:
1834
1835
def test_regular_tokens_spelling_special_survive(self):
1836
"""Regular tokens that spell out a drop-token string survive
1848
- when token IDs prove they are not the special token.
1849
- """
1837
+ when token IDs prove they are not the special token."""
1838
vocab = {**_DROP_VOCAB, "h": 72, "<": 73, "bos": 74, ">": 75, "w": 76}
1839
engine = _make_engine(
1840
vocab=vocab,
@@ -1862,8 +1850,7 @@ class TestDropSpecialTokens:
1850
1851
def test_configured_terminal_not_treated_as_drop(self):
1852
"""Tokens already in config.terminals (like <think>) are handled
1865
- by the state machine, not the drop mechanism.
1866
- """
1853
+ by the state machine, not the drop mechanism."""
1854
engine = _make_engine(
1855
vocab=_DROP_VOCAB,
1856
special_tokens=list(_DROP_VOCAB.keys()),
@@ -1918,8 +1905,7 @@ class TestDropSpecialTokens:
1905
def test_drops_applied_with_skip_tool_parsing(self):
1906
"""Drop tokens are always dropped, even with skip_tool_parsing.
1907
DROP_TERMINALs have no transitions by construction, so no parser
1921
- pass can use them.
1922
- """
1908
+ pass can use them."""
1909
for initial_state in (ParserState.REASONING, ParserState.CONTENT):
1910
engine = _make_engine(
1911
vocab=_DROP_VOCAB,
@@ -1935,8 +1921,7 @@ class TestDropSpecialTokens:
1921
1922
def test_transitions_unaffected_by_drop_in_reasoning_with_skip_tool_parsing(self):
1923
"""With skip_tool_parsing in REASONING state, drop tokens are
1938
- removed but configured terminals still fire their transitions.
1939
- """
1924
+ removed but configured terminals still fire their transitions."""
1925
engine = _make_engine(
1926
vocab=_DROP_VOCAB,
1927
special_tokens=list(_DROP_VOCAB.keys()),
@@ -1972,8 +1957,7 @@ class TestDropSpecialTokens:
1957
1958
def test_mixed_configured_and_drop_terminals(self):
1959
"""Configured terminals trigger transitions while drop terminals
1975
- are silently removed in the same stream.
1976
- """
1960
+ are silently removed in the same stream."""
1961
engine = _make_engine(
1962
vocab=_DROP_VOCAB,
1963
special_tokens=list(_DROP_VOCAB.keys()),
@@ -1997,8 +1981,7 @@ class TestTruncatedToolOpenerStreamParity:
1981
"""Regression tests for #47137: when generation terminates inside a
1982
``<tool_call>`` opener that has not been promoted to a tool call
1983
(via ``max_tokens`` or a ``stop`` string), the non-streaming path
2000
- must drop the incomplete markup, matching the streaming path.
2001
- """
1984
+ must drop the incomplete markup, matching the streaming path."""
1985
1986
_QWEN3_VOCAB = {
1987
"<tool_call>": 100,
@@ -2044,8 +2027,7 @@ class TestTruncatedToolOpenerStreamParity:
2027
)
2028
def test_truncated_opener_dropped_in_both_paths(self, mock_request, chunks):
2029
"""A cutoff inside the opener yields no content and no tool calls
2047
- in both the non-streaming and streaming paths.
2048
- """
2030
+ in both the non-streaming and streaming paths."""
2031
text = "".join(chunks)
2032
2033
_, content, tool_calls = self._make_parser().parse(
@@ -2058,8 +2040,7 @@ class TestTruncatedToolOpenerStreamParity:
2040
2041
def test_content_before_truncated_opener_preserved(self, mock_request):
2042
"""Only the incomplete markup is dropped; content generated before
2061
- the opener is returned identically by both paths.
2062
- """
2043
+ the opener is returned identically by both paths."""
2044
chunks = ["Checking the weather. ", "<tool_call>", "\n", "<function"]
2045
text = "".join(chunks)
2046
@@ -2073,8 +2054,7 @@ class TestTruncatedToolOpenerStreamParity:
2054
2055
def test_content_around_unpromoted_tool_block_stays_ordered(self, mock_request):
2056
"""Text surrounding a complete-but-unparsable tool block keeps its
2076
- original order in the non-streaming path, matching streaming.
2077
- """
2057
+ original order in the non-streaming path, matching streaming."""
2058
chunks = ["A ", "<tool_call>", "garbage", "</tool_call>", " B"]
2059
text = "".join(chunks)
2060
@@ -2088,8 +2068,7 @@ class TestTruncatedToolOpenerStreamParity:
2068
2069
def test_complete_tool_call_still_promoted(self, mock_request):
2070
"""Sanity check: a complete tool call still parses in the
2091
- non-streaming path after the truncation fix.
2092
- """
2071
+ non-streaming path after the truncation fix."""
2072
text = (
2073
"<tool_call>\n"
2074
"<function=get_weather>\n"
@@ -2109,8 +2088,7 @@ class TestThinkMarkupWithoutReasoningParser:
2088
"""With no reasoning parser configured, reasoning markup is plain
2089
content: engine-backed tool parsers must return it verbatim in both
2090
the non-streaming and streaming paths, not consume the markers or
2112
- reclassify the block as reasoning and drop it.
2113
- """
2091
+ reclassify the block as reasoning and drop it."""
2092
2093
_VOCAB = {
2094
"<think>": 90,
@@ -2176,8 +2154,7 @@ class TestThinkMarkupWithoutReasoningParser:
2154
2155
def test_think_block_preserved_alongside_tool_call(self, mock_request):
2156
"""The tools-called branch also returns the tool parser's content;
2179
- a think block preceding a promoted tool call must survive in it.
2180
- """
2157
+ a think block preceding a promoted tool call must survive in it."""
2158
think = "<think>plan</think>"
2159
text = think + (
2160
"<tool_call>\n"
tests/parser/engine/test_qwen3.py
+5
-10
@@ -318,8 +318,7 @@ class TestStreaming:
318
319
def test_streaming_args_arrive_incrementally(self, parser, mock_request):
320
"""Arguments must stream as intermediate deltas, not batch at
321
- tool-end.
322
- """
321
+ tool-end."""
322
chunks = [
323
"<tool_call>\n",
324
"<function=get_weather>\n",
@@ -524,8 +523,7 @@ class TestStreaming:
523
524
def test_streaming_split_tool_call_tag(self, parser, mock_request):
525
"""<tool_call> arrives as a single special token; the rest of
527
- the content is split into fine-grained chunks.
528
- """
526
+ the content is split into fine-grained chunks."""
527
chunks = [
528
"<tool_call>\n",
529
"<function=test>\n",
@@ -702,8 +700,7 @@ class TestArgConverter:
700
701
class TestSchemaAwareTypeCoercion:
702
"""Verify that _fix_arg_types corrects miscoerced values using the
705
- tool schema.
706
- """
703
+ tool schema."""
704
705
@pytest.fixture
706
def tools(self):
@@ -845,8 +842,7 @@ class TestAnyOfTypeCoercion:
842
843
def test_anyof_string_param_not_coerced(self, parser_with_anyof, mock_request):
844
"""A param with anyOf including 'string' must not be coerced
848
- to integer.
849
- """
845
+ to integer."""
846
text = (
847
"<tool_call>\n"
848
"<function=set_config>\n"
@@ -862,8 +858,7 @@ class TestAnyOfTypeCoercion:
858
859
class TestSchemaCoercionBoolNumberNull:
860
"""Verify that _fix_arg_types coerces string values to non-string
865
- schema types using coerce_to_schema_type.
866
- """
861
+ schema types using coerce_to_schema_type."""
862
863
@pytest.fixture
864
def tools(self):
tests/parser/engine/test_qwen3_reasoning.py
+6
-12
@@ -276,8 +276,7 @@ class TestIsReasoningEndTurnBoundaries:
276
277
def test_empty_boundary_config_keeps_global_walk(self):
278
"""Configs without turn_boundary_tokens keep the pre-existing
279
- behavior: any </think> in the sequence ends reasoning.
280
- """
279
+ behavior: any </think> in the sequence ends reasoning."""
280
cfg = qwen3_config(turn_boundary_tokens=frozenset())
281
parser = Qwen3Parser(
282
make_mock_tokenizer(_QWEN3_VOCAB), parser_engine_config=cfg
@@ -289,8 +288,7 @@ class TestIsReasoningEndTurnBoundaries:
288
def test_boundary_tokens_missing_from_vocab_keep_global_walk(self):
289
"""Boundary tokens absent from the vocabulary resolve to nothing,
290
so subclasses reusing the default on a non-ChatML vocab keep the
292
- pre-existing behavior.
293
- """
291
+ pre-existing behavior."""
292
vocab = {
293
token: token_id
294
for token, token_id in _QWEN3_VOCAB.items()
@@ -301,8 +299,7 @@ class TestIsReasoningEndTurnBoundaries:
299
300
def test_boundary_with_thinking_disabled_is_end(self, mock_tokenizer):
301
"""With thinking disabled (initial state CONTENT) a walk that stops at a turn
304
- boundary must report reasoning as ended: the model never emits a marker.
305
- """
302
+ boundary must report reasoning as ended: the model never emits a marker."""
303
parser = Qwen3Parser(
304
mock_tokenizer, chat_template_kwargs={"enable_thinking": False}
305
)
@@ -310,8 +307,7 @@ class TestIsReasoningEndTurnBoundaries:
307
308
def test_boundary_with_thinking_enabled_not_end(self, parser):
309
"""With thinking disabled (initial state REASONING) a walk that stops at a turn
313
- boundary must keep reasoning open
314
- """
310
+ boundary must keep reasoning open"""
311
assert not parser.is_reasoning_end([_IM_START_ID, _TEXT_ID])
312
313
@@ -672,8 +668,7 @@ class TestTrailingWhitespaceStripping:
668
669
class TestWhitespaceStrippingDisabled:
670
"""When strip_trailing_reasoning_whitespace is False,
675
- trailing whitespace in reasoning must be preserved.
676
- """
671
+ trailing whitespace in reasoning must be preserved."""
672
673
@pytest.fixture
674
def parser_no_strip(self):
@@ -731,8 +726,7 @@ class TestThinkingDisabled:
726
def test_thinking_disabled_streaming_content_only(self, mock_tokenizer):
727
"""Plain text with thinking disabled must stream as content, not
728
reasoning. Before the fix, the REASONING initial state caused all
734
- output to be emitted as reasoning chunks.
735
- """
729
+ output to be emitted as reasoning chunks."""
730
p = Qwen3Parser(
731
mock_tokenizer,
732
chat_template_kwargs={"enable_thinking": False},
tests/parser/engine/test_replay.py
+4
-8
@@ -440,8 +440,7 @@ class TestToolCallFilteringReplay:
440
)
441
class TestToolCallFilteringNonStreaming:
442
"""Non-streaming parse() with tool_choice='none' must suppress tool
443
- calls and not leak special tokens into content.
444
- """
443
+ calls and not leak special tokens into content."""
444
445
def test_parse(self, parser_cls, sample, think_end, tool_start):
446
tokenizer = make_mock_tokenizer(sample)
@@ -484,8 +483,7 @@ _WS_TOOL_SAMPLES = [(t[0], t[1]) for t in _TOOL_CALL_SAMPLES if "whitespace" in
483
)
484
class TestToolChoiceNoneStreamingParity:
485
"""Streaming and non-streaming must return the same content
487
- when tool_choice='none' suppresses tool calls.
488
- """
486
+ when tool_choice='none' suppresses tool calls."""
487
488
def test_content_matches(self, parser_cls, sample):
489
tokenizer = make_mock_tokenizer(sample)
@@ -543,8 +541,7 @@ def _inject_drop_tokens(sample):
541
542
class TestDropTokenReplay:
543
"""Verify unconfigured special tokens are silently dropped across
546
- all parsers and chunk sizes.
547
- """
544
+ all parsers and chunk sizes."""
545
546
@pytest.mark.parametrize(
547
"parser_info",
@@ -601,8 +598,7 @@ class TestDropTokenNonStreaming:
598
599
class TestAdapterReferences:
600
"""Verify make_adapters sets reasoning/tool parser class refs on parser engine
604
- parser classes so the serving layer finds them and calls adjust_request.
605
- """
601
+ parser classes so the serving layer finds them and calls adjust_request."""
602
603
@pytest.mark.parametrize(
604
"parser_name",
tests/parser/engine/test_seed_oss.py
+2
-4
@@ -129,8 +129,7 @@ def test_single_tool_call(tool_parser, mock_request):
129
130
def test_malformed_function_end_does_not_drop_siblings(tool_parser, mock_request):
131
"""Regression for #46314: a malformed ``</function>`` with no closing ``>``
132
- on the header must not discard the other, well-formed calls.
133
- """
132
+ on the header must not discard the other, well-formed calls."""
133
text = (
134
f"{TOOL_CALL_START}\n<function=broken</function>\n{TOOL_CALL_END}"
135
f"{TOOL_CALL_START}\n<function=get_weather>\n"
@@ -172,8 +171,7 @@ def test_reasoning_then_tool_call(parser):
171
172
def test_streaming_think_end_and_tool_call_same_delta(parser):
173
"""``</seed:think>`` and ``<seed:tool_call>`` arriving in one delta must
175
- not leak the terminal tokens into the reasoning text.
176
- """
174
+ not leak the terminal tokens into the reasoning text."""
175
reasoning, content = simulate_reasoning_streaming(
176
parser,
177
[
tests/parser/engine/test_ufffd_reasoning_transition.py
+1
-2
@@ -146,8 +146,7 @@ class TestUfffdReasoningTransition:
146
147
def test_byte_fallback_tokenizer_produces_ufffd(self):
148
"""Validate the fixture: decode() returns U+FFFD for isolated
149
- byte-fallback token IDs, proving the old code path would leak.
150
- """
149
+ byte-fallback token IDs, proving the old code path would leak."""
150
vocab = dict(_MODEL_CONFIGS[0].values[0])
151
tokenizer = ByteFallbackMockTokenizer(vocab, _SHARED_TOKENS, _SHARED_UFFFD_IDS)
152
assert tokenizer.decode([200]) == "�"
tests/parser/engine/trace_builder.py
+1
-2
@@ -992,8 +992,7 @@ def _inkling_block(
992
) -> None:
993
"""Append one Inkling content block; blocks after the first start with
994
the ``<|message_model|>`` role token (the first block continues the
995
- generation prompt directly).
996
- """
995
+ generation prompt directly)."""
996
if segs:
997
segs.append(("<|message_model|>", True))
998
segs.append((kind_token, True))
tests/parser/mistral/test_tool_calls.py
+5
-10
@@ -492,8 +492,7 @@ def test_extract_tool_calls_pre_v11_regex_fallback(
492
):
493
"""The regex fallback path finds valid JSON via regex when the primary
494
raw_decode fails on leading junk. It should re-serialize arguments
495
- and return a valid tool call.
496
- """
495
+ and return a valid tool call."""
496
model_output = (
497
'[TOOL_CALLS] junk [{"name": "add", "arguments":{"a": 1, "b": 2}}] trail'
498
)
@@ -2004,8 +2003,7 @@ def test_streaming_pre_v11_parallel_calls_batched_deltas(
2003
mistral_pre_v11_tool_parser, mistral_pre_v11_tokenizer, chunk_size, driver
2004
):
2005
"""A batched delta spanning the boundary between two parallel calls must
2007
- keep them on distinct indices (the bug collapsed both onto index 0).
2008
- """
2006
+ keep them on distinct indices (the bug collapsed both onto index 0)."""
2007
model_output = (
2008
'[TOOL_CALLS] [{"name": "add", "arguments": {"a": 3.5, "b": 4}}, '
2009
'{"name": "get_current_weather", "arguments": '
@@ -2123,8 +2121,7 @@ def test_reasoning_active_no_think_block_no_leak(
2121
chunk_size,
2122
):
2123
"""Tool call without a preceding think block must not leak as content
2126
- when the reasoning parser is active.
2127
- """
2124
+ when the reasoning parser is active."""
2125
accumulated_content = ""
2126
function_names: list[str] = []
2127
function_args_strs: list[str] = []
@@ -2225,8 +2222,7 @@ def test_adjust_request_pre_v11_required_clears_response_format(
2222
response_format so the tool schema is the sole structured-output
2223
constraint, matching the base ToolParser (otherwise the request either
2224
hits the "multiple constraints" engine error or, with no constraint,
2228
- rambles to finish_reason='length').
2229
- """
2225
+ rambles to finish_reason='length')."""
2226
request = _make_request(tool_choice="required", response_format=response_format)
2227
result = mistral_pre_v11_tool_parser.adjust_request(request)
2228
@@ -2243,8 +2239,7 @@ def test_adjust_request_non_mistral_tokenizer_required_injects_schema(
2239
) -> None:
2240
"""The guided-schema injection must also fire for non-Mistral (e.g. HF-mode)
2241
tokenizers driving the Mistral tool parser, mirroring the base ToolParser so
2246
- required + response_format does not fall back to an unconstrained ramble.
2247
- """
2242
+ required + response_format does not fall back to an unconstrained ramble."""
2243
request = _make_request(
2244
tool_choice="required", response_format={"type": "json_object"}
2245
)
tests/parser/test_streaming.py
+12
-24
@@ -229,8 +229,7 @@ def _boundary_chunks(tokenizer, parser, end_token_id=None):
229
230
def test_parse_delta_reasoning_not_dropped_on_boundary(tokenizer, request_obj):
231
"""Regression: reasoning must not be lost when a multi-token delta
232
- spans the reasoning/tool-call boundary.
233
- """
232
+ spans the reasoning/tool-call boundary."""
233
parser = make_parser(tokenizer, reasoning=True, tool=True)
234
chunks = _boundary_chunks(tokenizer, parser)
235
results = stream_chunks(parser, tokenizer, chunks, request_obj)
@@ -248,8 +247,7 @@ def test_parse_delta_reasoning_not_dropped_on_boundary(tokenizer, request_obj):
247
248
def test_parse_delta_reasoning_boundary_no_tool_parser(tokenizer, request_obj):
249
"""When no tool parser is active, boundary-spanning chunks must still
251
- preserve reasoning and pass post-</think> text as content.
252
- """
250
+ preserve reasoning and pass post-</think> text as content."""
251
parser = make_parser(tokenizer, reasoning=True, tool=False)
252
chunks = _boundary_chunks(tokenizer, parser)
253
results = stream_chunks(parser, tokenizer, chunks, request_obj)
@@ -263,8 +261,7 @@ def test_parse_delta_reasoning_boundary_no_tool_parser(tokenizer, request_obj):
261
262
def test_parse_delta_reasoning_only_no_think_leak(tokenizer, request_obj):
263
"""Regression: </think> must not leak into content when streaming
266
- token-by-token with reasoning=True, tool=False.
267
- """
264
+ token-by-token with reasoning=True, tool=False."""
265
parser = make_parser(tokenizer, reasoning=True, tool=False)
266
results = stream_text(
267
parser, tokenizer, MODEL_OUTPUT, request_obj, prompt_token_ids=[]
@@ -306,8 +303,7 @@ def test_parse_delta_reasoning_only_thinking_disabled(tokenizer, request_obj):
303
304
def test_parse_delta_finished_no_flush_without_tool_call_delta(tokenizer, request_obj):
305
"""When finished=True but the final parse_delta produces no
309
- tool-call delta, unstreamed args are not flushed.
310
- """
306
+ tool-call delta, unstreamed args are not flushed."""
307
parser = make_parser(tokenizer, reasoning=False, tool=True)
308
309
results = stream_text(
@@ -330,8 +326,7 @@ def test_parse_delta_finished_no_flush_without_tool_call_delta(tokenizer, reques
326
327
def test_parse_delta_finished_no_extra_args_when_fully_streamed(tokenizer, request_obj):
328
"""When all args have been streamed, finished=True must not
333
- produce extra or duplicate arguments.
334
- """
329
+ produce extra or duplicate arguments."""
330
parser = make_parser(tokenizer, reasoning=False, tool=True)
331
results = stream_text(
332
parser, tokenizer, MODEL_OUTPUT, request_obj, prompt_token_ids=[]
@@ -351,8 +346,7 @@ def test_parse_delta_finished_no_extra_args_when_fully_streamed(tokenizer, reque
346
347
def test_parse_delta_finished_appends_remaining_args(tokenizer, request_obj):
348
"""When finished=True and the tool parser has unstreamed args,
354
- parse_delta appends the remaining arguments to the tool-call delta.
355
- """
349
+ parse_delta appends the remaining arguments to the tool-call delta."""
350
parser = make_parser(tokenizer, reasoning=False, tool=True)
351
token_ids = tokenizer.encode(MODEL_OUTPUT, add_special_tokens=False)
352
@@ -499,8 +493,7 @@ def test_engine_reasoning_hermes_tool_token_by_token(tokenizer, request_obj):
493
"""Qwen3 engine reasoning + Hermes tool parser, token-by-token.
494
495
Sanity check that the mixed engine/non-engine configuration works
502
- when tokens arrive one at a time (no deferred content).
503
- """
496
+ when tokens arrive one at a time (no deferred content)."""
497
parser = Qwen3ReasoningHermesToolParser(tokenizer)
498
499
assert parser._reasoning_parser.engine_based_streaming is True
@@ -527,8 +520,7 @@ def test_engine_reasoning_hermes_tool_boundary(tokenizer, request_obj):
520
521
When </think> and <tool_call> are in the same chunk with aligned
522
text and token IDs, the engine processes both terminals and returns
530
- the <tool_call> text as content.
531
- """
523
+ the <tool_call> text as content."""
524
parser = Qwen3ReasoningHermesToolParser(tokenizer)
525
end_token_id = parser._reasoning_parser._parser_engine._reasoning_end_token_id
526
chunks = _boundary_chunks(tokenizer, parser, end_token_id=end_token_id)
@@ -559,8 +551,7 @@ def test_engine_reasoning_hermes_tool_text_holdback(tokenizer, request_obj):
551
Without the fix, finish_streaming() is never called at the
552
reasoning->tool transition when _engine_based is False, so the '<'
553
is lost and the Hermes parser sees 'tool_call>...' instead of
562
- '<tool_call>...'.
563
- """
554
+ '<tool_call>...'."""
555
parser = Qwen3ReasoningHermesToolParser(tokenizer)
556
vocab = tokenizer.get_vocab()
557
think_end_id = vocab["</think>"]
@@ -651,8 +642,7 @@ def test_engine_reasoning_no_tool_batched_content_passthrough(tokenizer, request
642
batched delta carries ``</think>`` plus the following content
643
(as happens with stream_interval > 1). The post-``</think>`` text
644
must be emitted as content -- not dropped, not reclassified as
654
- reasoning -- and the ``</think>`` marker must not leak either way.
655
- """
645
+ reasoning -- and the ``</think>`` marker must not leak either way."""
646
parser = Qwen3ReasoningNoToolParser(tokenizer)
647
assert parser._reasoning_parser.engine_based_streaming is True
648
assert parser._tool_parser is None
@@ -680,8 +670,7 @@ def _decode_stream_deltas(tokenizer, groups):
670
This mirrors how vLLM's detokenizer feeds ``parse_delta`` in
671
production: byte-level UTF-8 hold-back means a character whose bytes
672
span multiple tokens is only surfaced once complete (a naive
683
- per-token ``decode`` would instead emit U+FFFD replacement chars).
684
- """
673
+ per-token ``decode`` would instead emit U+FFFD replacement chars)."""
674
from tokenizers.decoders import DecodeStream
675
676
stream = DecodeStream(skip_special_tokens=False)
@@ -713,8 +702,7 @@ def test_engine_reasoning_hermes_tool_multibyte_holdback(tokenizer, request_obj)
702
``DecodeStream``. Its UTF-8 hold-back yields the correct
703
character round-trip (a naive per-token decode would corrupt it),
704
verifying the boundary stays byte-safe for multi-token
716
- characters.
717
- """
705
+ characters."""
706
parser = Qwen3ReasoningHermesToolParser(tokenizer)
707
vocab = tokenizer.get_vocab()
708
think_end_id = vocab["</think>"]
tests/plugins_tests/test_endpoint_plugins.py
+4
-8
@@ -81,8 +81,7 @@ def test_no_plugins_loaded_when_allowlist_is_empty_string(
81
):
82
"""`VLLM_PLUGINS=""` parses to `[""]`, not `None` (see `vllm.envs`), so it
83
must be treated as a (non strict) allowlist matching no plugin name, not
84
- as "unset".
85
- """
84
+ as "unset"."""
85
monkeypatch.setenv("VLLM_PLUGINS", "")
86
87
assert load_endpoint_plugins(("generate",)) == []
@@ -167,8 +166,7 @@ def test_attach_is_noop_when_nothing_discovered(monkeypatch: pytest.MonkeyPatch)
166
async def test_init_state_is_noop_without_phase_a(monkeypatch: pytest.MonkeyPatch):
167
"""`init_app_state` callers that never ran `build_app` (e.g.
168
`run_batch.py`, which builds a bare `State()`) must not crash just
170
- because `state.endpoint_plugins` was never set.
171
- """
169
+ because `state.endpoint_plugins` was never set."""
170
from starlette.datastructures import State
171
172
monkeypatch.setenv("VLLM_PLUGINS", "dummy_admin_endpoint_plugin")
@@ -186,8 +184,7 @@ async def test_render_server_attaches_endpoint_plugins_with_no_engine_client(
184
"""The CPU only render server has no `EngineClient` but a plugin eligible
185
for the `render` task (`required_tasks` is `None` or includes `"render"`)
186
still gets its routes attached at Phase A. Phase B passes `None` for
189
- `engine_client` and it's up to the plugin to handle that.
190
- """
187
+ `engine_client` and it's up to the plugin to handle that."""
188
monkeypatch.setenv("VLLM_PLUGINS", "dummy_admin_endpoint_plugin")
189
190
args = _build_args()
@@ -213,8 +210,7 @@ async def test_render_server_attaches_endpoint_plugins_with_no_engine_client(
210
@pytest.mark.asyncio
211
async def test_endpoint_plugin_end_to_end(monkeypatch: pytest.MonkeyPatch):
212
"""Phase A (attach) + Phase B (init) wired through `build_app` then
216
- exercised with a real HTTP request against the worked example plugin.
217
- """
213
+ exercised with a real HTTP request against the worked example plugin."""
214
monkeypatch.setenv("VLLM_PLUGINS", "dummy_admin_endpoint_plugin")
215
216
args = _build_args()
tests/plugins_tests/test_io_processor_plugins.py
+1
-2
@@ -38,8 +38,7 @@ def my_plugin_entry_points():
38
"""Patch importlib.metadata.entry_points to expose a single 'my_plugin'
39
entry point backed by DummyIOProcessor, exercising the full plugin-loading
40
code path: entry_points → plugin.load() → func() →
41
- resolve_obj_by_qualname → IOProcessor.__init__.
42
- """
41
+ resolve_obj_by_qualname → IOProcessor.__init__."""
42
qualname = f"{DummyIOProcessor.__module__}.{DummyIOProcessor.__qualname__}"
43
ep = MagicMock()
44
ep.name = "my_plugin"
tests/quantization/test_auto_round.py
+5
-10
@@ -382,8 +382,7 @@ def test_inc_get_quant_method_unquantized_layer_with_model_prefix(
382
layer_factory,
383
) -> None:
384
"""``model.``-prefixed extra_config entries trigger early exit for both
385
- LinearBase and ParallelLMHead layers.
386
- """
385
+ LinearBase and ParallelLMHead layers."""
386
config = make_config(extra_config={"model.layer": {"bits": 16}})
387
layer = layer_factory()
388
@@ -396,8 +395,7 @@ def test_inc_get_quant_method_unquantized_routed_experts_with_model_prefix(
395
monkeypatch,
396
) -> None:
397
"""``model.``-prefixed extra_config entries trigger early exit for
399
- RoutedExperts layers, returning UnquantizedFusedMoEMethod.
400
- """
398
+ RoutedExperts layers, returning UnquantizedFusedMoEMethod."""
399
400
class DummyUnquantizedFusedMoEMethod:
401
def __init__(self, moe_config) -> None:
@@ -420,8 +418,7 @@ def test_inc_get_quant_method_unquantized_routed_experts_with_model_prefix(
418
419
def test_inc_get_quant_method_unknown_layer_with_model_prefix_returns_none() -> None:
420
"""``model.``-prefixed extra_config entries return None for unhandled
423
- layer types (non-Linear, non-MoE).
424
- """
421
+ layer types (non-Linear, non-MoE)."""
422
config = make_config(extra_config={"model.unknown": {"bits": 16}})
423
424
method = config.get_quant_method(DummyLayer(), "unknown")
@@ -736,8 +733,7 @@ def test_wna16_cuda_low_bit_moe_routes_to_humming(monkeypatch, bits) -> None:
733
@pytest.mark.parametrize("bits", [4, 8])
734
def test_wna16_cuda_high_bit_skips_humming(monkeypatch, bits) -> None:
735
"""4/8-bit int stays on the Marlin/GPTQ/AWQ path even on CUDA so a single
739
- model can mix high-bit Marlin and low-bit humming layers.
740
- """
736
+ model can mix high-bit Marlin and low-bit humming layers."""
737
called = {"humming": False}
738
739
monkeypatch.setattr(current_platform, "is_cuda", lambda: True)
@@ -1668,8 +1664,7 @@ def test_inc_get_quant_method_unquantized_moe_returns_unquantized(
1664
monkeypatch,
1665
) -> None:
1666
"""Early-exit returns UnquantizedFusedMoEMethod for FusedMoE layers
1671
- when extra_config has bits >= 16.
1672
- """
1667
+ when extra_config has bits >= 16."""
1668
config = make_config(extra_config={"layer": {"bits": 16}})
1669
layer = object.__new__(RoutedExperts)
1670
layer.moe_config = None # UnquantizedFusedMoEMethod accepts moe_config
tests/quantization/test_fp8.py
+1
-2
@@ -213,8 +213,7 @@ def test_deepseek_v41_vl_mapper_routes_linear_scales(
213
):
214
"""The VL wrapper must map ``.scale`` keys to the parameter the linear
215
quant method registers, as the text model does. A hardcoded
216
- ``weight_scale_inv`` raised KeyError for native MXFP8 checkpoints.
217
- """
216
+ ``weight_scale_inv`` raised KeyError for native MXFP8 checkpoints."""
217
from vllm.models.deepseek_v41.nvidia import model as model_module
218
from vllm.models.deepseek_v41.nvidia import vl_model as vl_module
219
tests/quantization/test_gfx950_moe.py
+1
-2
@@ -160,8 +160,7 @@ def test_qwen38_tep8_auto_fallback_respects_explicit_backend(
160
@pytest.fixture
161
def mxfp4_oracle_config():
162
"""Stub the config the oracle reads (``model_config.quantization_config``)
163
- so backend dispatch resolves without a real model / user override.
164
- """
163
+ so backend dispatch resolves without a real model / user override."""
164
from unittest.mock import patch
165
166
with patch(
tests/quantization/test_humming_mxfp4_block_fp8.py
+2
-4
@@ -85,8 +85,7 @@ def test_block_fp8_activation_quant_config_is_block_quantized():
85
(FP8 dtype, [1, 128] block, not per-act-token). This is what makes the
86
DeepEP prepare/finalize step quantize activations to block FP8 *before* the
87
all-to-all dispatch instead of deferring to Humming -- and what makes
88
- HummingExpertsBase.expects_unquantized_inputs return False.
89
- """
88
+ HummingExpertsBase.expects_unquantized_inputs return False."""
89
from vllm.model_executor.layers.quantization.utils.humming_utils import (
90
make_humming_moe_quant_config,
91
)
@@ -108,8 +107,7 @@ def test_block_fp8_activation_quant_config_is_block_quantized():
107
def test_default_activation_quant_config_defers_to_humming():
108
"""Without a block activation shape the config stays per-token (the deferred
109
path): Humming quantizes internally, preserving pre-existing behavior for
111
- every non-block-FP8 scheme.
112
- """
110
+ every non-block-FP8 scheme."""
111
from vllm.model_executor.layers.quantization.utils.humming_utils import (
112
make_humming_moe_quant_config,
113
)
tests/quantization/test_int8_moe_oracle.py
+1
-2
@@ -70,8 +70,7 @@ def _make_int8_moe_config(moe_backend: str = "auto") -> FusedMoEConfig:
70
)
71
def test_int8_dynamic_schemes_dispatch_to_triton(weight_key, activation_key):
72
"""Both dynamic-activation INT8 MoE schemes (per-channel + per-tensor
73
- weights) select the Triton backend.
74
- """
73
+ weights) select the Triton backend."""
74
config = _make_int8_moe_config()
75
backend, experts_cls = select_int8_moe_backend(
76
config, weight_key=weight_key, activation_key=activation_key
tests/quantization/test_modelopt.py
+4
-8
@@ -587,8 +587,7 @@ def test_modelopt_fp8_pb_wo_checkpoint_setup(monkeypatch, dist_init, workspace_i
587
def test_modelopt_nvfp4_config_dispatches_w4a4_method():
588
"""``quant_method="NVFP4"`` (W4A4) resolves to a
589
``(kNvfp4Static, kNvfp4Dynamic)`` QuantSpec under the generic
590
- ``ModelOptLinearMethod``.
591
- """
590
+ ``ModelOptLinearMethod``."""
591
from vllm.model_executor.layers.linear import LinearBase
592
593
config = ModelOptNvFp4Config(
@@ -637,8 +636,7 @@ def test_modelopt_linear_method_builder_registry_override(monkeypatch):
636
"""The bespoke-method escape hatch: a format registered in
637
``LINEAR_METHOD_BUILDERS`` routes that algo to its own method instead of the
638
generic ``ModelOptLinearMethod``. This is how a format that cannot be a
640
- ``(weight, activation)`` key pair plugs into dispatch.
641
- """
639
+ ``(weight, activation)`` key pair plugs into dispatch."""
640
from vllm.model_executor.layers.linear import LinearBase
641
from vllm.model_executor.layers.quantization import modelopt as m
642
@@ -669,8 +667,7 @@ def test_modelopt_linear_method_builder_registry_override(monkeypatch):
667
def test_modelopt_w4a16_respects_linear_backend(linear_backend, kernel_cls):
668
"""W4A16 (`activation=None`) kernel selection honors ``--linear-backend``:
669
``use_a16=True`` defaults to Marlin, but an explicit backend wins. The
672
- generic method routes this through ``select_linear_kernel``.
673
- """
670
+ generic method routes this through ``select_linear_kernel``."""
671
from vllm.config.quantization import QuantSpec
672
from vllm.model_executor.layers.quantization.modelopt import (
673
RuntimeDtypes,
@@ -941,8 +938,7 @@ def test_modelopt_fp8_pb_wo_hides_output_padding(monkeypatch):
938
def test_modelopt_fp8_pb_wo_rejects_non_128_input():
939
"""Input width must still be a multiple of 128 (same as #53132, which only
940
pads the output). A partial input block is refused loudly rather than
944
- silently loading wrong scales.
945
- """
941
+ silently loading wrong scales."""
942
from vllm.model_executor.layers.quantization import modelopt as mo
943
from vllm.model_executor.layers.quantization.utils.quant_utils import (
944
kFp8Static128BlockSym,
tests/quantization/test_online_mxfp4.py
+1
-2
@@ -411,8 +411,7 @@ def test_online_mxfp4_moe_matches_quark(
411
) -> tuple[torch.Tensor, torch.Tensor]:
412
"""Place the source weights into buffers of the padded size, the
413
way the weight loader writes only the unpadded slice of a larger
414
- allocation.
415
- """
414
+ allocation."""
415
w13 = torch.full(
416
(num_experts, 2 * intermediate_size, hidden_size),
417
padding_value,
tests/quantization/test_per_token_kv_cache.py
+1
-2
@@ -490,8 +490,7 @@ def test_per_token_head_negative_slot_skipped(qcfg: QuantConfig):
490
)
491
def test_process_weights_sets_placeholder_scales(kv_cache_dtype: str):
492
"""Per-token-head should set _k_scale=1.0, _v_scale=1.0
493
- and delete checkpoint attrs.
494
- """
493
+ and delete checkpoint attrs."""
494
from vllm.model_executor.layers.quantization.kv_cache import (
495
BaseKVCacheMethod,
496
)
tests/reasoning/test_kimi_k3_reasoning_parser.py
+4
-8
@@ -276,8 +276,7 @@ def _reference_is_reasoning_end(input_ids: list[int]) -> bool:
276
def test_is_reasoning_end_streaming_only_scans_the_step_window():
277
"""The decode-step check must not re-derive the answer from the whole
278
sequence: an already-closed think block earlier in the sequence is the
279
- engine's business (it latches `reasoning_ended`), not this call's.
280
- """
279
+ engine's business (it latches `reasoning_ended`), not this call's."""
280
parser = KimiK3ReasoningParser(DummyTokenizer())
281
prompt = [*CLOSE_IDS, *OPEN_IDS, 9, 9, 9]
282
@@ -287,8 +286,7 @@ def test_is_reasoning_end_streaming_only_scans_the_step_window():
286
287
def test_is_reasoning_end_streaming_detects_marker_across_step_boundary():
288
"""A 3-token marker can be split over decode steps; the check carries the
290
- preceding len(marker)-1 tokens so the final token still completes it.
291
- """
289
+ preceding len(marker)-1 tokens so the final token still completes it."""
290
parser = KimiK3ReasoningParser(DummyTokenizer())
291
history = [*OPEN_IDS, 5, *CLOSE_IDS[:2]]
292
@@ -299,8 +297,7 @@ def test_is_reasoning_end_streaming_detects_marker_across_step_boundary():
297
def test_is_reasoning_end_streaming_reopened_block_is_not_ended():
298
"""Kimi K3 may close and immediately reopen the think channel inside one
299
window (speculative decoding lands several tokens per step). The newest
302
- marker wins, matching is_reasoning_end.
303
- """
300
+ marker wins, matching is_reasoning_end."""
301
parser = KimiK3ReasoningParser(DummyTokenizer())
302
window = [*CLOSE_IDS, *OPEN_IDS]
303
@@ -327,8 +324,7 @@ def test_is_reasoning_end_streaming_thinking_disabled():
324
def test_reasoning_end_matches_reference_over_marker_dense_sequences(seed):
325
"""Both the full-sequence check and the per-step check must agree with the
326
two-scan reference, on sequences where the markers (which share the suffix
330
- [2, 3]) collide and overlap constantly.
331
- """
327
+ [2, 3]) collide and overlap constantly."""
328
import random
329
330
rnd = random.Random(seed)
tests/renderers/test_chat_utils_prompt_embeds.py
+3
-6
@@ -116,8 +116,7 @@ def test_prompt_embeds_keys_registered():
116
117
def test_ensure_placeholder_token_is_single_token_and_idempotent(tokenizer):
118
"""Ensure the placeholder token is a single token and that multiple calls to
119
- "ensure" are idempotent, across all tokenizer families.
120
- """
119
+ "ensure" are idempotent, across all tokenizer families."""
120
tid1 = _ensure_prompt_embeds_placeholder_token(tokenizer)
121
tid2 = _ensure_prompt_embeds_placeholder_token(tokenizer)
122
assert tid1 == tid2
@@ -470,8 +469,7 @@ def test_build_mixed_prompt_embeds(stream):
469
@pytest.mark.parametrize("role", ["user", "system"])
470
async def test_end_to_end_expand_and_build(tokenizer, parse_fn, role):
471
"""Full renderer pipeline: parse -> chat template -> expand -> locate
473
- -> build mixed prompt, across tokenizers, roles, and sync/async.
474
- """
472
+ -> build mixed prompt, across tokenizers, roles, and sync/async."""
473
tokenizer.chat_template = _SIMPLE_CHAT_TEMPLATE
474
tid = _ensure_prompt_embeds_placeholder_token(tokenizer)
475
@@ -526,8 +524,7 @@ async def test_end_to_end_expand_and_build(tokenizer, parse_fn, role):
524
@pytest.mark.asyncio
525
async def test_end_to_end_multi_message_conversation(tokenizer, parse_fn):
526
"""Full pipeline with prompt_embeds spread across system + user messages,
529
- verifying ordering and positioning in the final token stream.
530
- """
527
+ verifying ordering and positioning in the final token stream."""
528
tokenizer.chat_template = _SIMPLE_CHAT_TEMPLATE
529
tid = _ensure_prompt_embeds_placeholder_token(tokenizer)
530
tests/renderers/test_gemma4_chat_template.py
+9
-18
@@ -33,8 +33,7 @@ def _render(template, messages, **kwargs):
33
class TestGemma4ChatTemplate:
34
def test_basic_multiturn_thinking_disabled(self, gemma4_template):
35
"""With enable_thinking=False (default), generation prompt ends with
36
- an empty thought channel to suppress thinking.
37
- """
36
+ an empty thought channel to suppress thinking."""
37
messages = [
38
{"role": "user", "content": "Hello"},
39
{"role": "assistant", "content": "Hi there!"},
@@ -50,8 +49,7 @@ class TestGemma4ChatTemplate:
49
50
def test_basic_multiturn_thinking_enabled(self, gemma4_template):
51
"""With enable_thinking=True, generation prompt ends with model
53
- turn opener (no thought suppression).
54
- """
52
+ turn opener (no thought suppression)."""
53
messages = [
54
{"role": "user", "content": "Hello"},
55
{"role": "assistant", "content": "Hi there!"},
@@ -146,8 +144,7 @@ class TestGemma4ChatTemplate:
144
145
def test_tool_responses_openai_style(self, gemma4_template):
146
"""role='tool' messages are formatted as <|tool_response> blocks
149
- with content dumped as-is.
150
- """
147
+ with content dumped as-is."""
148
messages = [
149
{"role": "user", "content": "Weather?"},
150
{
@@ -205,8 +202,7 @@ class TestGemma4ChatTemplate:
202
203
def test_generation_prompt_not_after_tool_response(self, gemma4_template):
204
"""add_generation_prompt=True should NOT add <|turn>model when the
208
- last message type was tool_response (the model turn continues).
209
- """
205
+ last message type was tool_response (the model turn continues)."""
206
messages = [
207
{"role": "user", "content": "Weather?"},
208
{
@@ -233,8 +229,7 @@ class TestGemma4ChatTemplate:
229
230
def test_reasoning_in_tool_chains(self, gemma4_template):
231
"""Reasoning field on assistant with tool_calls after last user
236
- message emits <|channel>thought\\n...<channel|>.
237
- """
232
+ message emits <|channel>thought\\n...<channel|>."""
233
messages = [
234
{"role": "user", "content": "Calculate something"},
235
{
@@ -280,8 +275,7 @@ class TestGemma4ChatTemplate:
275
276
def test_strip_thinking_in_model_content(self, gemma4_template):
277
"""<|channel>...<channel|> in model content is stripped by the
283
- strip_thinking macro.
284
- """
278
+ strip_thinking macro."""
279
messages = [
280
{"role": "user", "content": "Hi"},
281
{
@@ -295,8 +289,7 @@ class TestGemma4ChatTemplate:
289
290
def test_multi_turn_tool_chain(self, gemma4_template):
291
"""assistant->tool->assistant->tool produces exactly one
298
- <|turn>model (later assistants continue the same turn).
299
- """
292
+ <|turn>model (later assistants continue the same turn)."""
293
messages = [
294
{"role": "user", "content": "Do two things"},
295
{
@@ -353,8 +346,7 @@ class TestGemma4ChatTemplate:
346
347
def test_tool_response_with_multimodal_content(self, gemma4_template):
348
"""Multimodal placeholders in tool messages are emitted after the
356
- tool_response block.
357
- """
349
+ tool_response block."""
350
messages = [
351
{"role": "user", "content": "Download the image and describe it."},
352
{
@@ -388,8 +380,7 @@ class TestGemma4ChatTemplate:
380
381
def test_tool_response_with_all_modalities(self, gemma4_template):
382
"""All multimodal types (image, audio, video) in a single tool
391
- response are rendered.
392
- """
383
+ response are rendered."""
384
messages = [
385
{"role": "user", "content": "Process media"},
386
{
tests/renderers/test_hf.py
+3
-6
@@ -308,8 +308,7 @@ def test_resolve_chat_template_kwargs(sample_json_schema, model, expected_kwargs
308
309
def test_resolve_chat_template_resolves_name():
310
"""When chat_template is a name, resolve_chat_template should return
311
- the actual Jinja content so that kwargs detection works correctly.
312
- """
311
+ the actual Jinja content so that kwargs detection works correctly."""
312
from unittest.mock import MagicMock
313
314
jinja_content = "{{ messages }}{% if tools %}{{ tools }}{% endif %}"
@@ -331,8 +330,7 @@ def test_resolve_chat_template_resolves_name():
330
331
def test_resolve_chat_template_kwargs_with_template_name():
332
"""Ensures template kwargs are not silently dropped when chat_template
334
- was originally a template name that has been resolved to Jinja content.
335
- """
333
+ was originally a template name that has been resolved to Jinja content."""
334
from unittest.mock import MagicMock
335
336
jinja_content = (
@@ -934,8 +932,7 @@ EFFORT_BREAKING_TEMPLATE = (
932
933
class TestApplyChatTemplateEffortTolerant:
934
"""Chat templates that reject unsupported reasoning_effort values should
937
- surface a 400-style client error instead of crashing the request.
938
- """
935
+ surface a 400-style client error instead of crashing the request."""
936
937
@pytest.fixture
938
def model_config(self):
tests/renderers/test_process_multi_modal_uuids.py
+1
-2
@@ -49,8 +49,7 @@ def _build_text_only_renderer() -> HfRenderer:
49
50
def test_text_only_model_mm_data_maps_to_bad_request():
51
"""Sending multimodal data to a text-only model is a client mistake, so it
52
- must surface as a ValueError and reach the client as HTTP 400, not 500.
53
- """
52
+ must surface as a ValueError and reach the client as HTTP 400, not 500."""
53
renderer = _build_text_only_renderer()
54
55
with pytest.raises(ValueError, match="text-only") as exc_info:
tests/renderers/test_prompt_embeds_payload_validation.py
+1
-2
@@ -127,8 +127,7 @@ def test_a_long_reason_is_truncated_and_says_how_much_was_left_out(model_config)
127
128
def test_a_short_reason_is_passed_through_whole(model_config):
129
"""A reason that fits is not annotated -- the count only appears when it is
130
- telling the reader something.
131
- """
130
+ telling the reader something."""
131
reason = "invalid magic number; corrupt file?"
132
assert len(reason) <= _MAX_EMBED_ERROR_REASON_CHARS
133
tests/renderers/test_sparse_tensor_concurrent_race.py
+1
-2
@@ -218,8 +218,7 @@ class TestCrossLoaderLockSharing:
218
219
def test_prompt_and_image_share_lock(self, model_config):
220
"""Prompt and image loaders cannot run their sparse guards
221
- concurrently.
222
- """
221
+ concurrently."""
222
valid_prompt = _encode_tensor(_create_valid_dense_tensor())
223
valid_image = _encode_tensor(_create_valid_dense_tensor(hidden_size=10))
224
tests/renderers/test_sparse_tensor_validation.py
+7
-14
@@ -157,8 +157,7 @@ class TestPromptEmbedsValidation:
157
158
def test_hidden_size_mismatch_rejected(self, model_config):
159
"""Tensors whose trailing dim doesn't match the model's hidden_size
160
- must be rejected at parse time.
161
- """
160
+ must be rejected at parse time."""
161
# opt-125m has hidden_size=768, passing 512 triggers the check.
162
wrong_hidden = torch.randn(10, 512, dtype=torch.float32)
163
encoded = _encode_tensor(wrong_hidden)
@@ -169,8 +168,7 @@ class TestPromptEmbedsValidation:
168
def test_float_dtype_mismatch_cast_to_model_dtype(self, model_config):
169
"""Tensors whose dtype doesn't match the model's dtype but are still
170
floating-point are cast, since API clients generally can't know the
172
- server's `--dtype` setting ahead of time.
173
- """
171
+ server's `--dtype` setting ahead of time."""
172
# Fixture pins model dtype to float32, upload a bfloat16 tensor.
173
mismatched_float = torch.randn(10, 768, dtype=torch.bfloat16)
174
encoded = _encode_tensor(mismatched_float)
@@ -183,8 +181,7 @@ class TestPromptEmbedsValidation:
181
def test_non_float_dtype_rejected(self, model_config):
182
"""Non-floating-point dtypes cannot be safely cast for embeddings
183
(e.g. integer tensors almost certainly indicate caller confusion),
186
- so they are rejected at parse time.
187
- """
184
+ so they are rejected at parse time."""
185
non_float = torch.randint(0, 100, (10, 768), dtype=torch.int32)
186
encoded = _encode_tensor(non_float)
187
@@ -193,8 +190,7 @@ class TestPromptEmbedsValidation:
190
191
def test_non_2d_tensor_rejected(self, model_config):
192
"""Tensors that aren't 2D (even after squeezing a leading dim)
196
- must be rejected with a clear error.
197
- """
193
+ must be rejected with a clear error."""
194
# A 1D tensor cannot be interpreted as (num_tokens, hidden_size).
195
bad = torch.randn(768, dtype=torch.float32)
196
encoded = _encode_tensor(bad)
@@ -204,8 +200,7 @@ class TestPromptEmbedsValidation:
200
201
def test_non_tensor_payload_rejected(self, model_config):
202
"""Deserializing to a non-Tensor object must raise a clear error
207
- instead of propagating an AssertionError.
208
- """
203
+ instead of propagating an AssertionError."""
204
# `torch.save` will serialize a plain dict; `weights_only=True` allows
205
# loading built-in containers, so this exercises the isinstance check.
206
buffer = io.BytesIO()
@@ -463,8 +458,7 @@ class TestEmbeddingDecodeSizeLimit:
458
def test_default_limit_would_reject_the_real_payload(self):
459
"""The shipped default has to bound the actual attack, not just the
460
shrunken shape used above. Checked arithmetically so no test ever asks
466
- the allocator for 4 TiB.
467
- """
461
+ the allocator for 4 TiB."""
462
dense_bytes = BOMB_SHAPE[0] * BOMB_SHAPE[1] * 4
463
assert dense_bytes > envs.VLLM_MAX_EMBED_DECODE_BYTES > 0
464
@@ -522,8 +516,7 @@ class TestEmbeddingDecodeSizeLimit:
516
@pytest.mark.parametrize("io_cls,parameter", EMBEDDING_MEDIA_IO)
517
def test_media_io_rejects_non_tensor_payload(self, io_cls, parameter):
518
"""These three had no `isinstance` check, so a non-tensor payload
525
- surfaced as an `AttributeError` (500) rather than a 4xx.
526
- """
519
+ surfaced as an `AttributeError` (500) rather than a 4xx."""
520
buffer = io.BytesIO()
521
torch.save({"not": "a tensor"}, buffer)
522
encoded = base64.b64encode(buffer.getvalue()).decode("utf-8")
tests/renderers/test_token_offsets.py
+5
-10
@@ -26,8 +26,7 @@ def fast_tokenizer():
26
def _make_base_renderer_with(tokenizer):
27
"""Build a minimal BaseRenderer subclass that exposes the tokenizer so we
28
can call ``_tokenize_prompt`` directly. BaseRenderer is abstract because of
29
- ``render_messages``; we just need a stub.
30
- """
29
+ ``render_messages``; we just need a stub."""
30
from vllm.renderers.base import BaseRenderer
31
32
class _StubRenderer(BaseRenderer):
@@ -92,8 +91,7 @@ class TestTokenizePromptOffsets:
91
def test_base_renderer_without_override_yields_no_offsets(self, fast_tokenizer):
92
"""A renderer that does not override ``_can_produce_offsets`` never
93
emits offsets, even with a fast tokenizer and the flag set. This locks
95
- in the base-default-False / subclass-override design.
96
- """
94
+ in the base-default-False / subclass-override design."""
95
from vllm.renderers.base import BaseRenderer
96
97
class _BareRenderer(BaseRenderer):
@@ -127,8 +125,7 @@ class TestTokenizePromptOffsets:
125
126
def test_slow_tokenizer_with_flag_no_offsets(self, fast_tokenizer):
127
"""Force is_fast=False to simulate a Slow tokenizer: the flag is set
130
- but offsets must not be returned because it cannot produce them.
131
- """
128
+ but offsets must not be returned because it cannot produce them."""
129
from unittest.mock import PropertyMock, patch
130
131
renderer = _make_base_renderer_with(fast_tokenizer)
@@ -147,8 +144,7 @@ class TestTokenizePromptOffsets:
144
@pytest.mark.parametrize("mm_key", ["multi_modal_data", "multi_modal_uuids"])
145
def test_multimodal_with_flag_no_offsets(self, fast_tokenizer, mm_key):
146
"""Offsets index the text prompt, which is meaningless once multimodal
150
- data is interleaved, so they are suppressed when MM inputs are present.
151
- """
147
+ data is interleaved, so they are suppressed when MM inputs are present."""
148
renderer = _make_base_renderer_with(fast_tokenizer)
149
params = TokenizeParams(max_total_tokens=None, return_token_offsets=True)
150
prompt = {"prompt": "Hello.", mm_key: {"image": ["x"]}}
@@ -160,8 +156,7 @@ class TestTokenizePromptOffsets:
156
@pytest.mark.asyncio
157
async def test_tokenize_prompt_async_returns_offsets(self, fast_tokenizer):
158
"""The async path offloads the sync tokenizer; it must yield the same
163
- offsets as the sync path.
164
- """
159
+ offsets as the sync path."""
160
renderer = _make_base_renderer_with(fast_tokenizer)
161
params = TokenizeParams(max_total_tokens=None, return_token_offsets=True)
162
tests/test_cmake_utils.py
+1
-2
@@ -40,8 +40,7 @@ def test_extract_archs_prefers_sass_target_over_corrupted_virtual_arch(
40
):
41
"""Torch's autodetection can emit a bogus arch=compute_* half (e.g.
42
capability 12.1 corrupted to arch=compute_20,code=sm_121); the SASS
43
- target must win, while PTX-only entries keep the virtual arch.
44
- """
43
+ target must win, while PTX-only entries keep the virtual arch."""
44
repo_root = Path(__file__).parents[1]
45
script = tmp_path / "test_extract_archs.cmake"
46
script.write_text(
tests/test_config.py
+10
-20
@@ -441,8 +441,7 @@ def test_no_hisparse_connector_keeps_attention_config_unset(monkeypatch):
441
442
def test_rocm_keeps_compiled_deepseek_defaults(monkeypatch):
443
"""ROCm keeps the DSA models (DeepSeek V3.2/V4, GLM-5.2) on their compiled
444
- MRV1 paths and off breakable cudagraphs by default.
445
- """
444
+ MRV1 paths and off breakable cudagraphs by default."""
445
from vllm.config.vllm import (
446
ROCM_DEFAULT_MRV1_ARCHITECTURES,
447
default_breakable_cudagraph_architectures,
@@ -657,8 +656,7 @@ def test_v2_model_runner_supports_extract_hidden_states():
656
657
def test_dflash2_draft_forces_v2_model_runner():
658
"""A DFlash2 draft must reach the V2 speculator, the only one that runs its
660
- candidate selector; on V1 it would draft as DFlash1 without raising.
661
- """
659
+ candidate selector; on V1 it would draft as DFlash1 without raising."""
660
661
def config(method, architectures):
662
return SimpleNamespace(
@@ -771,8 +769,7 @@ def test_late_piecewise_restrictions_without_compilation(monkeypatch, engine_kwa
769
770
def test_resolve_cudagraph_mode_skips_mamba_block_check_while_profiling():
771
"""Cudagraph memory profiling uses a minimal KV cache, so the Mamba
774
- block-count guard must only fire for the real cache sizing.
775
- """
772
+ block-count guard must only fire for the real cache sizing."""
773
kv_cache_config = SimpleNamespace(has_mamba_layers=True, num_blocks=4)
774
775
compilation_config = CompilationConfig(
@@ -1097,8 +1094,7 @@ def test_v1_model_runner_rejects_v2_only_features():
1094
1095
def test_batch_sharded_sampling_rejects_return_sampling_mask():
1096
"""The batch-sharded gather drops sampling masks, so the combination must
1100
- fail loudly instead of returning ``sampling_mask=None``.
1101
- """
1097
+ fail loudly instead of returning ``sampling_mask=None``."""
1098
config = SimpleNamespace(
1099
parallel_config=SimpleNamespace(
1100
enable_batch_sharded_sampling=True, tensor_parallel_size=2
@@ -2195,8 +2191,7 @@ class MockConfig:
2191
@patch("vllm.transformers_utils.runai_utils.ObjectStorageModel.pull_files")
2192
def test_s3_url_model_tokenizer_paths(mock_pull_files, s3_url):
2193
"""Test that S3 URLs create deterministic local directories for model and
2198
- tokenizer.
2199
- """
2194
+ tokenizer."""
2195
# Mock pull_files to avoid actually downloading files during tests
2196
mock_pull_files.return_value = None
2197
@@ -2294,8 +2289,7 @@ def test_s3_url_different_models_create_different_directories(mock_pull_files):
2289
@patch("vllm.transformers_utils.runai_utils.ObjectStorageModel.pull_files")
2290
def test_s3_url_different_model_and_tokenizer(mock_pull_files):
2291
"""Test that when model and tokenizer are different cloud URIs,
2297
- pull_files receives the correct URI for each.
2298
- """
2292
+ pull_files receives the correct URI for each."""
2293
mock_pull_files.return_value = None
2294
2295
model_url = "s3://bucket/model/"
@@ -2840,8 +2834,7 @@ def test_vllm_config_explicit_overrides():
2834
2835
def test_fusion_pass_op_priority():
2836
"""This test checks that custom op enablement & IR op priority
2843
- correctly control default fusions
2844
- """
2837
+ correctly control default fusions"""
2838
# Default config, O2, rms_norm+quant fusion disabled
2839
cfg1 = VllmConfig()
2840
assert not cfg1.compilation_config.pass_config.fuse_norm_quant
@@ -2925,8 +2918,7 @@ def test_needs_dp_coordination(
2918
2919
def test_fault_tolerance_requires_single_api_server():
2920
"""Fault tolerance assumes one AsyncMPClient manages all engines, so it
2928
- is incompatible with API server scale-out (_api_process_count > 1).
2929
- """
2921
+ is incompatible with API server scale-out (_api_process_count > 1)."""
2922
with pytest.raises(ValueError, match="single API server"):
2923
ParallelConfig(enable_fault_tolerance=True, _api_process_count=2)
2924
@@ -2936,8 +2928,7 @@ def test_fault_tolerance_requires_single_api_server():
2928
2929
def test_renderer_num_workers_with_mm_cache():
2930
"""Disallow renderer_num_workers > 1 with the mm processor cache only for
2939
- pooling models, whose preprocessing runs on the renderer workers.
2940
- """
2931
+ pooling models, whose preprocessing runs on the renderer workers."""
2932
mm_model = "Qwen/Qwen2-VL-2B-Instruct"
2933
2934
# Should raise: pooling + multi-worker + cache enabled (default cache_gb=4)
@@ -3263,8 +3254,7 @@ def test_watermarking_forces_model_runner_v2(monkeypatch):
3254
def test_mtp_draft_uses_model_weights_not_local_cache(mock_model_config_cls):
3255
"""Regression test: MTP + runai_streamer should use model_weights (original
3256
S3 URL) for the draft model, not model (local cache dir set by
3266
- pull_runai_model_from_obj_storage).
3267
- """
3257
+ pull_runai_model_from_obj_storage)."""
3258
from unittest.mock import MagicMock
3259
3260
s3_url = "s3://my-bucket/Qwen3-35B-A3B-FP8"
tests/test_logger.py
+8
-16
@@ -51,8 +51,7 @@ def test_trace_function_call():
51
def test_default_vllm_root_logger_configuration(monkeypatch):
52
"""This test presumes that VLLM_CONFIGURE_LOGGING (default: True) and
53
VLLM_LOGGING_CONFIG_PATH (default: None) are not configured and default
54
- behavior is activated.
55
- """
54
+ behavior is activated."""
55
monkeypatch.setenv("VLLM_LOGGING_COLOR", "0")
56
_configure_vllm_root_logger()
57
@@ -76,8 +75,7 @@ def test_default_vllm_root_logger_configuration(monkeypatch):
75
def test_descendent_loggers_depend_on_and_propagate_logs_to_root_logger(monkeypatch):
76
"""This test presumes that VLLM_CONFIGURE_LOGGING (default: True) and
77
VLLM_LOGGING_CONFIG_PATH (default: None) are not configured and default
79
- behavior is activated.
80
- """
78
+ behavior is activated."""
79
monkeypatch.setenv("VLLM_CONFIGURE_LOGGING", "1")
80
monkeypatch.delenv("VLLM_LOGGING_CONFIG_PATH", raising=False)
81
@@ -107,8 +105,7 @@ def test_descendent_loggers_depend_on_and_propagate_logs_to_root_logger(monkeypa
105
def test_logger_configuring_can_be_disabled(monkeypatch):
106
"""This test calls _configure_vllm_root_logger again to test custom logging
107
config behavior, however mocks are used to ensure no changes in behavior or
110
- configuration occur.
111
- """
108
+ configuration occur."""
109
monkeypatch.setenv("VLLM_CONFIGURE_LOGGING", "0")
110
monkeypatch.delenv("VLLM_LOGGING_CONFIG_PATH", raising=False)
111
@@ -120,8 +117,7 @@ def test_logger_configuring_can_be_disabled(monkeypatch):
117
def test_an_error_is_raised_when_custom_logging_config_file_does_not_exist(monkeypatch):
118
"""This test calls _configure_vllm_root_logger again to test custom logging
119
config behavior, however it fails before any change in behavior or
123
- configuration occurs.
124
- """
120
+ configuration occurs."""
121
monkeypatch.setenv("VLLM_CONFIGURE_LOGGING", "1")
122
monkeypatch.setenv(
123
"VLLM_LOGGING_CONFIG_PATH",
@@ -137,8 +133,7 @@ def test_an_error_is_raised_when_custom_logging_config_file_does_not_exist(monke
133
def test_an_error_is_raised_when_custom_logging_config_is_invalid_json(monkeypatch):
134
"""This test calls _configure_vllm_root_logger again to test custom logging
135
config behavior, however it fails before any change in behavior or
140
- configuration occurs.
141
- """
136
+ configuration occurs."""
137
monkeypatch.setenv("VLLM_CONFIGURE_LOGGING", "1")
138
139
with NamedTemporaryFile(encoding="utf-8", mode="w") as logging_config_file:
@@ -165,8 +160,7 @@ def test_an_error_is_raised_when_custom_logging_config_is_unexpected_json(
160
):
161
"""This test calls _configure_vllm_root_logger again to test custom logging
162
config behavior, however it fails before any change in behavior or
168
- configuration occurs.
169
- """
163
+ configuration occurs."""
164
monkeypatch.setenv("VLLM_CONFIGURE_LOGGING", "1")
165
166
with NamedTemporaryFile(encoding="utf-8", mode="w") as logging_config_file:
@@ -182,8 +176,7 @@ def test_an_error_is_raised_when_custom_logging_config_is_unexpected_json(
176
def test_custom_logging_config_is_parsed_and_used_when_provided(monkeypatch):
177
"""This test calls _configure_vllm_root_logger again to test custom logging
178
config behavior, however mocks are used to ensure no changes in behavior or
185
- configuration occur.
186
- """
179
+ configuration occur."""
180
monkeypatch.setenv("VLLM_CONFIGURE_LOGGING", "1")
181
182
valid_logging_config = {
@@ -207,8 +200,7 @@ def test_custom_logging_config_is_parsed_and_used_when_provided(monkeypatch):
200
def test_custom_logging_config_causes_an_error_if_configure_logging_is_off(monkeypatch):
201
"""This test calls _configure_vllm_root_logger again to test custom logging
202
config behavior, however mocks are used to ensure no changes in behavior or
210
- configuration occur.
211
- """
203
+ configuration occur."""
204
monkeypatch.setenv("VLLM_CONFIGURE_LOGGING", "0")
205
206
valid_logging_config = {
tests/test_ray_env.py
+2
-4
@@ -15,8 +15,7 @@ from vllm.v1.executor.ray_utils import WORKER_SPECIFIC_ENV_VARS
15
16
class TestDefaultPrefixes:
17
"""Built-in prefixes (VLLM_, LMCACHE_, NCCL_, UCX_, HF_, HUGGING_FACE_)
18
- should be forwarded without any extra configuration.
19
- """
18
+ should be forwarded without any extra configuration."""
19
20
@patch.dict(os.environ, {"LMCACHE_LOCAL_CPU": "True"}, clear=False)
21
def test_lmcache_prefix(self):
@@ -54,8 +53,7 @@ class TestDefaultExtraVars:
53
54
def test_pythonhashseed_in_result(self):
55
"""PYTHONHASHSEED should always be in the result set (as a name to
57
- copy) regardless of whether it is actually set in os.environ.
58
- """
56
+ copy) regardless of whether it is actually set in os.environ."""
57
result = get_env_vars_to_copy()
58
assert "PYTHONHASHSEED" in result
59
tests/tokenizers_/test_deepseek_v4.py
+1
-2
@@ -452,8 +452,7 @@ def test_deepseek_v4_image_blocks_become_placeholders():
452
453
def test_deepseek_v4_image_sentinel_ids_match_tokenizer():
454
"""The borrowed sentinel ids must line up with the reserved
455
- ``<|place_holder_mm_span_XXXX|>`` tokens in the tokenizer.
456
- """
455
+ ``<|place_holder_mm_span_XXXX|>`` tokens in the tokenizer."""
456
from vllm.models.deepseek_v4.common.mm_preprocess import (
457
IMAGE_SENTINEL_BASE_ID,
458
IMAGE_SENTINEL_TOKEN_NAMES,
tests/tokenizers_/test_hf.py
+1
-2
@@ -51,8 +51,7 @@ def _check_consistency(target: TokenizerLike, expected: TokenizerLike):
51
def test_thread_pool_tokenizer_pickle(model_id: str):
52
"""Regression test for issue #45433: the thread-pool tokenizer wrapper
53
reconstructs through maybe_make_thread_pool on unpickling, which used to
54
- fall off the end and return None.
55
- """
54
+ fall off the end and return None."""
55
reference_tokenizer = AutoTokenizer.from_pretrained(model_id)
56
57
pooled_tokenizer = maybe_make_thread_pool(deepcopy(reference_tokenizer))
tests/tool_parsers/test_apertus_tool_parser.py
+4
-8
@@ -341,8 +341,7 @@ class TestStreamingExtraction:
341
342
def test_mtp_streaming_massive_chunk(self, parser, mock_request):
343
"""Simulates MTP predicting text, tool calls,
344
- and trailing text all in a single chunk.
345
- """
344
+ and trailing text all in a single chunk."""
345
chunks = [
346
"Sure! "
347
'<|tools_prefix|>[{"get_weather": {"location": "London"}}]<|tools_suffix|>'
@@ -375,8 +374,7 @@ class TestStreamingExtraction:
374
375
def test_mtp_streaming_skip_and_catch_up(self, parser, mock_request):
376
"""Simulates MTP chunks that jump over entire tools
378
- (e.g., from middle of tool 1 to middle of tool 3).
379
- """
377
+ (e.g., from middle of tool 1 to middle of tool 3)."""
378
chunks = [
379
'<|tools_prefix|>[{"t1": {"a": 1}',
380
'}, {"t2": {"b": 2}}, {"t3": {"c": 3',
@@ -395,8 +393,7 @@ class TestStreamingExtraction:
393
394
def test_vllm_streaming_character_by_character(self, parser, mock_request):
395
"""Simulates worst-case vLLM fragmentation where
398
- chunks arrive character-by-character.
399
- """
396
+ chunks arrive character-by-character."""
397
text = (
398
'Hi <|tools_prefix|>[{"get_weather": '
399
'{"location": "London"}}]<|tools_suffix|> '
@@ -414,8 +411,7 @@ class TestStreamingExtraction:
411
412
def test_vllm_streaming_empty_deltas(self, parser, mock_request):
413
"""Simulates vLLM stream producing empty string chunks
417
- (e.g., hidden tokens or artifacts).
418
- """
414
+ (e.g., hidden tokens or artifacts)."""
415
chunks = [
416
"Wait",
417
"",
tests/tool_parsers/test_deepseekv32_tool_parser.py
+10
-20
@@ -173,8 +173,7 @@ class TestExtractToolCalls:
173
174
def test_string_attr_true_coerced_by_schema(self):
175
"""string="true" delivers a string, but the engine's schema-aware
176
- type fixer coerces it to the schema type (integer).
177
- """
176
+ type fixer coerces it to the schema type (integer)."""
177
tool = ChatCompletionToolsParam(
178
function=FunctionDefinition(
179
name="score",
@@ -288,8 +287,7 @@ class TestExtractToolCalls:
287
288
def test_string_attr_true_coerced_by_composed_schema(self):
289
"""string="true" delivers a JSON string, but the engine's schema-aware
291
- type fixer coerces it to the composed schema type (object).
292
- """
290
+ type fixer coerces it to the composed schema type (object)."""
291
tool = ChatCompletionToolsParam(
292
function=FunctionDefinition(
293
name="set_timer",
@@ -323,8 +321,7 @@ class TestExtractToolCalls:
321
322
def test_arguments_wrapper_repaired(self):
323
"""A single 'arguments' wrapper parameter must be unwrapped when it
326
- is not part of the tool schema and the inner object matches schema fields.
327
- """
324
+ is not part of the tool schema and the inner object matches schema fields."""
325
tool = ChatCompletionToolsParam(
326
function=FunctionDefinition(
327
name="get_weather",
@@ -495,8 +492,7 @@ class TestExtractToolCalls:
492
493
def test_null_coerced_back_to_string_by_schema(self):
494
"""string="false" with 'null' is json-parsed to None, but the
498
- engine's schema fixer coerces it back to "null" for string schemas.
499
- """
495
+ engine's schema fixer coerces it back to "null" for string schemas."""
496
tool = ChatCompletionToolsParam(
497
function=FunctionDefinition(
498
name="echo",
@@ -659,8 +655,7 @@ class TestExtractToolCallsStreaming:
655
656
def test_string_attr_true_coerced_by_schema_streaming(self):
657
"""Streaming: string='true' delivers a string but the engine's
662
- schema fixer coerces it to the schema type (integer).
663
- """
658
+ schema fixer coerces it to the schema type (integer)."""
659
tool = ChatCompletionToolsParam(
660
function=FunctionDefinition(
661
name="score",
@@ -976,8 +971,7 @@ class TestExtractToolCallsStreaming:
971
972
def test_no_marker_leak_chunked(self, parser):
973
"""Chunked streaming must NOT leak DSML start-marker fragments
979
- as content (GitHub #40801).
980
- """
974
+ as content (GitHub #40801)."""
975
full_text = build_tool_call("fn", {"k": "v"})
976
deltas = self._stream_chunked(parser, full_text, chunk_size=5)
977
content = "".join(d.content for d in deltas if d.content is not None)
@@ -987,8 +981,7 @@ class TestExtractToolCallsStreaming:
981
982
def test_no_marker_leak_with_prefix_chunked(self, parser):
983
"""Content before a tool call must not include start-marker
990
- fragments when chunked (GitHub #40801).
991
- """
984
+ fragments when chunked (GitHub #40801)."""
985
full_text = "Hello!" + build_tool_call("fn", {"a": "b"})
986
deltas = self._stream_chunked(parser, full_text, chunk_size=5)
987
content = "".join(d.content for d in deltas if d.content is not None)
@@ -1000,8 +993,7 @@ class TestExtractToolCallsStreaming:
993
994
def test_no_marker_leak_char_by_char(self, parser):
995
"""Character-by-character streaming must not leak marker
1003
- fragments (GitHub #40801).
1004
- """
996
+ fragments (GitHub #40801)."""
997
full_text = build_tool_call("fn", {"k": "v"})
998
deltas = self._stream_chunked(parser, full_text, chunk_size=1)
999
content = "".join(d.content for d in deltas if d.content is not None)
@@ -1011,8 +1003,7 @@ class TestExtractToolCallsStreaming:
1003
1004
def test_no_marker_leak_all_split_points(self, parser):
1005
"""Start token split at every possible boundary must not
1014
- leak (GitHub #40801).
1015
- """
1006
+ leak (GitHub #40801)."""
1007
for chunk_size in range(1, len(FC_START) + 2):
1008
p = make_parser()
1009
full_text = build_tool_call("fn", {"k": "v"})
@@ -1024,8 +1015,7 @@ class TestExtractToolCallsStreaming:
1015
1016
def test_false_partial_marker_emitted(self, parser):
1017
"""Text ending with a prefix of the start token that turns out
1027
- NOT to be a marker must still be emitted as content.
1028
- """
1018
+ NOT to be a marker must still be emitted as content."""
1019
full_text = "<|DSM some regular text"
1020
deltas = self._stream_chunked(parser, full_text, chunk_size=3)
1021
content = "".join(d.content for d in deltas if d.content is not None)
tests/tool_parsers/test_gemma4_tool_parser.py
+1
-2
@@ -124,8 +124,7 @@ def mock_request():
124
125
class TestParseGemma4Args:
126
"""Values are returned as strings; type coercion to proper JSON types
127
- happens at the engine layer.
128
- """
127
+ happens at the engine layer."""
128
129
def test_empty_string(self):
130
assert _parse_gemma4_args("") == {}
tests/tool_parsers/test_gigachat3_tool_parser.py
+1
-2
@@ -18,8 +18,7 @@ from vllm.tool_parsers import ToolParser, ToolParserManager
18
@pytest.fixture(scope="function")
19
def default_tokenizer() -> TokenizerLike:
20
"""Override module-scoped default_tokenizer because gigachat tests
21
- mutate the tokenizer via ``add_tokens``.
22
- """
21
+ mutate the tokenizer via ``add_tokens``."""
22
return AutoTokenizer.from_pretrained("openai-community/gpt2")
23
24
tests/tool_parsers/test_kimi_k3_named_tool_choice.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Named tool choice for Kimi K3: allowed when the XTML structural tag is
4
-attached (strict tool calling), rejected otherwise.
5
-"""
4
+attached (strict tool calling), rejected otherwise."""
5
6
import pytest
7
tests/tool_parsers/test_lfm2_tool_parser.py
+9
-18
@@ -416,8 +416,7 @@ def test_tool_call(
416
def test_empty_tool_call_block(body: str, lfm2_tokenizer: TokenizerLike):
417
"""An empty block ([] or [ ]) means the model called no tools; it must
418
not report tools_called=True with zero tool calls (the invariant
419
- run_tool_extraction asserts).
420
- """
419
+ run_tool_extraction asserts)."""
420
cls = ToolParserManager.get_tool_parser("lfm2")
421
model_output = f"{TOOL_CALL_START}[{body}]{TOOL_CALL_END}"
422
@@ -437,8 +436,7 @@ def test_whitespace_after_start_token(lfm2_tokenizer: TokenizerLike):
436
not break parsing. The streaming path used to feed the indented text to
437
ast.parse verbatim, so every completion candidate raised
438
IndentationError and the call was silently dropped (non-streaming
440
- stripped it and succeeded).
441
- """
439
+ stripped it and succeeded)."""
440
cls = ToolParserManager.get_tool_parser("lfm2")
441
model_output = f"{TOOL_CALL_START} [{SIMPLE_FUNCTION_OUTPUT}]{TOOL_CALL_END}"
442
@@ -478,8 +476,7 @@ def test_streaming_full_block_and_trailing_in_single_delta(
476
):
477
"""The entire <|tool_call_start|>[...]<|tool_call_end|> block plus
478
trailing assistant text arrive in one delta. Trailing content must
481
- still be emitted — not silently dropped.
482
- """
479
+ still be emitted — not silently dropped."""
480
tool_parser: ToolParser = ToolParserManager.get_tool_parser("lfm2")(lfm2_tokenizer)
481
full_text = f"{TOOL_CALL_START}[{SIMPLE_FUNCTION_OUTPUT}]{TOOL_CALL_END}\nDone."
482
@@ -494,8 +491,7 @@ def test_streaming_leading_content_and_full_block_in_single_delta(
491
lfm2_tokenizer: TokenizerLike,
492
):
493
"""Leading assistant text plus the entire tool block arrive in one
497
- delta. Leading content must be emitted — not silently dropped.
498
- """
494
+ delta. Leading content must be emitted — not silently dropped."""
495
tool_parser: ToolParser = ToolParserManager.get_tool_parser("lfm2")(lfm2_tokenizer)
496
full_text = (
497
f"Let me check. {TOOL_CALL_START}[{SIMPLE_FUNCTION_OUTPUT}]{TOOL_CALL_END}"
@@ -512,8 +508,7 @@ def test_streaming_leading_block_and_trailing_in_single_delta(
508
lfm2_tokenizer: TokenizerLike,
509
):
510
"""Leading text + complete tool block + trailing text in one delta.
515
- Both leading and trailing content must be preserved.
516
- """
511
+ Both leading and trailing content must be preserved."""
512
tool_parser: ToolParser = ToolParserManager.get_tool_parser("lfm2")(lfm2_tokenizer)
513
full_text = (
514
"Let me check. "
@@ -534,8 +529,7 @@ def test_echoed_tool_call_body_not_leaked_to_content(
529
"""LFM2 sometimes emits the tool call body again after the first
530
<|tool_call_end|>, capped with a second <|tool_call_end|>. The
531
echoed body must not surface as assistant content — neither in
537
- streaming nor non-streaming paths.
538
- """
532
+ streaming nor non-streaming paths."""
533
tool_parser: ToolParser = ToolParserManager.get_tool_parser("lfm2")(lfm2_tokenizer)
534
body = (
535
"[grocery.orderIngredients("
@@ -570,8 +564,7 @@ def test_streaming_char_by_char_multi_dict_list(lfm2_tokenizer: TokenizerLike):
564
character at a time. Every prefix lands in some partial-parse state
565
(mid-key, mid-value, open quote inside dict, empty dict, etc.). The
566
parser must not raise — incomplete prefixes should silently wait for
573
- more text instead of logging exceptions.
574
- """
567
+ more text instead of logging exceptions."""
568
tool_parser: ToolParser = ToolParserManager.get_tool_parser("lfm2")(lfm2_tokenizer)
569
full_text = (
570
f"{TOOL_CALL_START}[grocery.orderIngredients("
@@ -602,8 +595,7 @@ def test_streaming_char_by_char_multi_dict_list(lfm2_tokenizer: TokenizerLike):
595
def test_streaming_dotted_name_in_single_delta(lfm2_tokenizer: TokenizerLike):
596
"""A pythonic call with a dotted/attribute function name (e.g.
597
``domain.method(arg=...)``) must be parsed correctly in streaming mode
605
- just as in non-streaming mode.
606
- """
598
+ just as in non-streaming mode."""
599
tool_parser: ToolParser = ToolParserManager.get_tool_parser("lfm2")(lfm2_tokenizer)
600
full_text = f"{TOOL_CALL_START}[{DOTTED_NAME_FUNCTION_OUTPUT}]{TOOL_CALL_END}"
601
@@ -619,8 +611,7 @@ def test_adjust_request_disables_skip_special_tokens(
611
"""When tools are present, the parser must force
612
``skip_special_tokens=False`` so the engine does not strip the
613
<|tool_call_start|>/<|tool_call_end|> sentinels before they reach the
622
- parser.
623
- """
614
+ parser."""
615
from vllm.entrypoints.openai.chat_completion.protocol import (
616
ChatCompletionRequest,
617
)
tests/tool_use/test_muse_glimmer.py
+1
-2
@@ -220,8 +220,7 @@ def test_reasoning_then_parallel_calls():
220
221
def _stream(raw: str, chunk: int):
222
"""Feed ``raw`` incrementally in ``chunk``-char steps through BOTH streaming
223
- parsers; return (reasoning, content, tool_calls).
224
- """
223
+ parsers; return (reasoning, content, tool_calls)."""
224
reasoning, content, toolcalls = [], [], []
225
prev = ""
226
i = 0
tests/tool_use/test_tool_choice_required.py
+1
-2
@@ -376,8 +376,7 @@ WEB_SEARCH_TOOL = WebSearchTool(type="web_search")
376
377
class TestNonFunctionToolsSkipped:
378
"""Non-function tools (web_search, etc.) must be silently skipped
379
- by the tool-schema utilities instead of raising TypeError.
380
- """
379
+ by the tool-schema utilities instead of raising TypeError."""
380
381
def test_find_tool_properties_skips_web_search(self):
382
tools = [WEB_SEARCH_TOOL, FUNCTION_TOOL]
tests/transformers_utils/processors/test_glm5next.py
+2
-4
@@ -330,8 +330,7 @@ def test_sample_frames_fps_interval(video_processor):
330
331
def test_defaults_mirror_checkpoint_config():
332
"""Bare instantiation matches the checkpoint's ``processor_config.json``
333
- token-budget style defaults; ``size`` carries no budget.
334
- """
333
+ token-budget style defaults; ``size`` carries no budget."""
334
image_processor = Glm5NextImageProcessor()
335
assert image_processor.patch_expand_factor == 1
336
assert image_processor.min_image_tokens == 16
@@ -365,8 +364,7 @@ def test_missing_token_budgets_rejected():
364
365
def test_video_config_fields_land():
366
"""fps_interval / max_frame_count_dynamic from the dedicated config
368
- shape sampling without any request overrides.
369
- """
367
+ shape sampling without any request overrides."""
368
proc = Glm5NextVideoProcessor(
369
fps_interval=4,
370
max_frame_count_dynamic=32,
tests/transformers_utils/test_config.py
+2
-4
@@ -188,8 +188,7 @@ def test_model_config_generation_fallback_forwards_code_revision():
188
189
def test_safetensors_metadata_of_repo_without_safetensors():
190
"""A repo storing its weights in another format is an answer, not a failure,
191
- so it must not be retried.
192
- """
191
+ so it must not be retried."""
192
from huggingface_hub.errors import LocalEntryNotFoundError, NotASafetensorsRepoError
193
194
get_safetensors_metadata = MagicMock(
@@ -228,8 +227,7 @@ def test_mrope_num_dims(section_key, mrope_section, expected_num_dims):
227
@pytest.mark.parametrize("section_name", ["mrope_section", "xdrope_section"])
228
def test_mrope_num_dims_from_config_attribute(section_name):
229
"""Some configs expose the section as an attribute rather than under
231
- `rope_parameters`.
232
- """
230
+ `rope_parameters`."""
231
config = PretrainedConfig()
232
setattr(config, section_name, [16, 16, 16, 16])
233
tests/transformers_utils/test_hf_overrides_model_type.py
+1
-2
@@ -22,8 +22,7 @@ def test_hf_overrides_model_type_returns_correct_config_class():
22
"""When hf_overrides sets model_type to a registered custom type whose
23
checkpoint has a *different* model_type on disk, get_config() must return
24
an instance of the registered config class — not the class that matches
25
- the on-disk model_type.
26
- """
25
+ the on-disk model_type."""
26
# Register the custom config
27
_CONFIG_REGISTRY["test_custom_model"] = _TestCustomConfig
28
tests/utils.py
+2
-4
@@ -72,8 +72,7 @@ FP8_DTYPE = current_platform.fp8_dtype()
72
def prewarm_hf_cache(assets: list[tuple[str, str]]) -> None:
73
"""Pre-populate the HF cache for (repo_id, filename) pairs that upstream
74
trust_remote_code modules would otherwise fetch from third-party CDNs
75
- (often unreachable from US-based CI).
76
- """
75
+ (often unreachable from US-based CI)."""
76
if HF_HUB_OFFLINE:
77
return
78
for repo_id, filename in assets:
@@ -893,8 +892,7 @@ class RemoteOpenAIServerCustom(RemoteOpenAIServer):
892
max_wait_seconds: float | None = None,
893
) -> None:
894
"""Store custom child process function then invoke superclass
896
- constructor which will indirectly launch it.
897
- """
895
+ constructor which will indirectly launch it."""
896
self.child_process_fxn = child_process_fxn
897
super().__init__(
898
model=model,
tests/utils_/test_gpu_sync_debug.py
+5
-10
@@ -59,8 +59,7 @@ def test_with_env_set(monkeypatch, mode):
59
@create_new_process_for_each_test()
60
def test_other_threads_are_not_policed(monkeypatch):
61
"""A background thread that syncs deliberately must not be broken by the
62
- check being armed on the thread running the decorated function.
63
- """
62
+ check being armed on the thread running the decorated function."""
63
monkeypatch.setattr(gsd, "_SYNC_CHECK_MODE", "error")
64
monkeypatch.setattr(gsd, "_sync_check_enabled", True)
65
@@ -85,8 +84,7 @@ def test_other_threads_are_not_policed(monkeypatch):
84
def test_allow_on_other_thread_does_not_disarm(monkeypatch):
85
"""`gpu_sync_allowed()` on one thread must not suppress the check on
86
another. It is scoped by ContextVar rather than torch's process-global
88
- sync debug mode, which a previous implementation mutated.
89
- """
87
+ sync debug mode, which a previous implementation mutated."""
88
monkeypatch.setattr(gsd, "_SYNC_CHECK_MODE", "error")
89
monkeypatch.setattr(gsd, "_sync_check_enabled", True)
90
@@ -115,8 +113,7 @@ def test_allow_on_other_thread_does_not_disarm(monkeypatch):
113
def test_suppressing_works_while_compiling(monkeypatch):
114
"""`_suppressing` wraps torch compile entry points, which run with
115
`torch.compiler.is_compiling()` true. `gpu_sync_allowed()` deliberately
118
- no-ops in that state, so `_suppressing` must not route through it.
119
- """
116
+ no-ops in that state, so `_suppressing` must not route through it."""
117
monkeypatch.setattr(gsd, "_SYNC_CHECK_MODE", "error")
118
monkeypatch.setattr(gsd, "_sync_check_enabled", True)
119
# Emulate being inside a torch compile, as inductor passes are.
@@ -148,8 +145,7 @@ def test_copy_checker_is_traceable_while_compiling(monkeypatch):
145
def test_sync_debug_mode_restored_after_checked_call(monkeypatch):
146
"""The mode is armed only for the duration of a checked call. Leaving it
147
on process-wide made every sync outside a checked region emit a
151
- `UserWarning` whenever our handler was not the installed one.
152
- """
148
+ `UserWarning` whenever our handler was not the installed one."""
149
monkeypatch.setattr(gsd, "_SYNC_CHECK_MODE", "error")
150
monkeypatch.setattr(gsd, "_sync_check_enabled", True)
151
@@ -294,8 +290,7 @@ def test_genuinely_async_transfers_pass(monkeypatch):
290
asynchronous in both directions -- even with a dtype conversion, which
291
runs GPU-side, and even permuted (e.g. transposed), which uses pitched
292
cudaMemcpy2D/3DAsync; D2H `Tensor.to` allocates a pinned destination.
297
- None of these may be flagged.
298
- """
293
+ None of these may be flagged."""
294
monkeypatch.setattr(gsd, "_SYNC_CHECK_MODE", "error")
295
monkeypatch.setattr(gsd, "_sync_check_enabled", True)
296
gsd._install_copy_checkers()
tests/utils_/test_network_utils.py
+5
-10
@@ -29,8 +29,7 @@ def test_get_file_store_init_method_is_unique():
29
30
def _call_with_timeout(func, timeout: float = 10.0):
31
"""Run func in a daemon thread so a livelock regression fails the test
32
- quickly instead of hanging the suite.
33
- """
32
+ quickly instead of hanging the suite."""
33
result: dict = {}
34
35
def target():
@@ -97,8 +96,7 @@ def test_get_open_port_skips_reserved_dp_master_ports(
96
monkeypatch: pytest.MonkeyPatch,
97
):
98
"""VLLM_PORT == VLLM_DP_MASTER_PORT must not livelock by returning the
100
- same free-but-reserved port forever (upstream issue #50024).
101
- """
99
+ same free-but-reserved port forever (upstream issue #50024)."""
100
base = 42123
101
with monkeypatch.context() as m:
102
m.setenv("VLLM_PORT", str(base))
@@ -111,8 +109,7 @@ def test_get_open_ports_list_skips_reserved_dp_master_ports(
109
monkeypatch: pytest.MonkeyPatch,
110
):
111
"""The VLLM_PORT band scan must not hand out ports inside the window
114
- reserved for the data parallel master process.
115
- """
112
+ reserved for the data parallel master process."""
113
base = 42223
114
reserved = range(base, base + 10)
115
with monkeypatch.context() as m:
@@ -128,8 +125,7 @@ def test_get_open_port_ephemeral_skips_reserved_range(
125
monkeypatch: pytest.MonkeyPatch,
126
):
127
"""An ephemeral port that happens to fall in the reserved range is
131
- replaced by a rescan starting past the range.
132
- """
128
+ replaced by a rescan starting past the range."""
129
base = 42323
130
with monkeypatch.context() as m:
131
m.delenv("VLLM_PORT", raising=False)
@@ -148,8 +144,7 @@ def test_get_open_port_ephemeral_without_dp_master_port(
144
monkeypatch: pytest.MonkeyPatch,
145
):
146
"""Without VLLM_PORT and VLLM_DP_MASTER_PORT, an ephemeral port is
151
- returned as before.
152
- """
147
+ returned as before."""
148
with monkeypatch.context() as m:
149
m.delenv("VLLM_PORT", raising=False)
150
m.delenv("VLLM_DP_MASTER_PORT", raising=False)
tests/utils_/test_numa_utils.py
+6
-12
@@ -157,8 +157,7 @@ def test_pct_binding_filters_cpus(monkeypatch):
157
)
158
def test_pct_binding_fires_on_every_capable_sku(monkeypatch, sku, expected_cpus):
159
"""Each SKU in ``_PCT_CAPABLE_SKUS`` engages the gate at its own
160
- expected ``highest_perf`` and uses its own priority-core stride.
161
- """
160
+ expected ``highest_perf`` and uses its own priority-core stride."""
161
sku_config = numa_utils._PCT_CAPABLE_SKUS[sku]
162
_patch_pct_gates(
163
monkeypatch,
@@ -243,8 +242,7 @@ def test_get_numactl_args_engine_core_baseline_spans_shard_numa_nodes():
242
def test_get_numactl_args_engine_core_pct_spans_shard_numa_nodes(monkeypatch):
243
"""PCT: EngineCore for a multi-NUMA shard binds to the union of priority
244
cores across all shard nodes, so worker `--physcpubind` is always a
246
- subset of EngineCore's `cpus_allowed`.
247
- """
245
+ subset of EngineCore's `cpus_allowed`."""
246
_patch_pct_gates(
247
monkeypatch,
248
model_match=True,
@@ -294,8 +292,7 @@ def test_get_numactl_args_engine_core_pct_external_launcher_spans_local_nodes(
292
"""external_launcher (or multi-node-within-DP, or Ray) hits the
293
fallback branch. EngineCore must still span every local NUMA node
294
so it can mp-spawn its local workers without ``--physcpubind``
297
- strict-validation failures.
298
- """
295
+ strict-validation failures."""
296
_patch_pct_gates(
297
monkeypatch,
298
model_match=True,
@@ -319,8 +316,7 @@ def test_get_numactl_args_engine_core_pct_external_launcher_spans_local_nodes(
316
317
def test_get_numactl_args_engine_core_baseline_multi_node_within_dp_spans_locals():
318
"""Multi-node-within-DP fallback: bind EngineCore to all local NUMA
322
- nodes that the visible ``numa_bind_nodes`` reference.
323
- """
319
+ nodes that the visible ``numa_bind_nodes`` reference."""
320
vllm_config = _make_config(
321
numa_bind=True,
322
numa_bind_nodes=[0, 0, 0, 0, 1, 1, 1, 1],
@@ -343,8 +339,7 @@ def test_get_numactl_args_engine_core_skips_user_cpu_list(monkeypatch):
339
``--physcpubind`` spawns need. We fall back to ``--cpunodebind`` over
340
the shard's NUMA nodes instead. PCT auto-detect is also bypassed when
341
the user is explicit (its priority-core union may not be a superset
346
- of the user's per-worker cores).
347
- """
342
+ of the user's per-worker cores)."""
343
_patch_pct_gates(monkeypatch, model_match=True, highest_perf=46)
344
vllm_config = _make_config(
345
numa_bind=True,
@@ -397,8 +392,7 @@ def test_get_numactl_args_requires_detectable_nodes(monkeypatch):
392
def test_configure_subprocess_rejects_unknown_process_kind():
393
"""configure_subprocess only knows 'worker' and 'EngineCore'; anything
394
else must raise ValueError instead of silently routing to the worker
400
- path.
401
- """
395
+ path."""
396
vllm_config = _make_config(numa_bind=True, numa_bind_nodes=[0])
397
with (
398
pytest.raises(ValueError, match="process_kind"),
tests/v1/attention/test_attention_backends.py
+1
-2
@@ -1392,8 +1392,7 @@ def test_non_causal_backend_correctness(
1392
model: str,
1393
):
1394
"""Test backend's correctness with non-causal (bidirectional) decoder
1395
- attention, as used by DFlash speculative decoding.
1396
- """
1395
+ attention, as used by DFlash speculative decoding."""
1396
1397
def bidirectional_mask_mod(
1398
b: torch.Tensor,
tests/v1/attention/test_attention_backends_selection.py
+1
-2
@@ -115,8 +115,7 @@ def test_mamba_layers_have_unified_interface(
115
layer_class, expected_backend, expected_mamba_type
116
):
117
"""Test that all Mamba layers have the unified get_attn_backend
118
- interface.
119
- """
118
+ interface."""
119
assert hasattr(layer_class, "get_attn_backend"), (
120
f"{layer_class.__name__} should have get_attn_backend method"
121
)
tests/v1/attention/test_attention_splitting.py
+1
-2
@@ -164,8 +164,7 @@ def apply_split_decodes_and_prefills(
164
treat_short_extends_as_decodes: bool = True,
165
):
166
"""Helper function to apply split_decodes_and_prefills and return
167
- the results.
168
- """
167
+ the results."""
168
device = torch.device("cpu")
169
seq_lens = [10 * (i + 1) for i in range(len(query_lens))]
170
common_metadata = create_common_attn_metadata(
tests/v1/attention/test_dcp_a2a_pack_mask.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""The empty-shard mask fused into the DCP A2A pack kernel must be bit-exact
4
-with the eager ``mask_dcp_empty_shards_`` pass it replaces.
5
-"""
4
+with the eager ``mask_dcp_empty_shards_`` pass it replaces."""
5
6
import pytest
7
import torch
tests/v1/attention/test_dspark_noncausal_sparse_mla.py
+1
-2
@@ -495,8 +495,7 @@ def test_dspark_noncausal_sparse_mla_matches_sdpa(
495
num_heads,
496
):
497
"""Non-causal (window ∪ block, future-pointing) per-token indices must match
498
- a dense SDPA reference over the same indices, for both sparse-MLA backends.
499
- """
498
+ a dense SDPA reference over the same indices, for both sparse-MLA backends."""
499
_skip_if_backend_unavailable(backend_cls, kv_cache_dtype, block_size)
500
501
window, block, topk_width = _DSPARK_CONFIGS[config_name]
tests/v1/attention/test_flashinfer_mla_sparse_sm90.py
+1
-2
@@ -231,8 +231,7 @@ def test_plan_uses_state_params(monkeypatch):
231
232
def test_kv_lens_host_formula():
233
"""Per-row host lengths: context == position + 1; capped at
234
- index_topk + trailing-pool remainder past the sparse threshold.
235
- """
234
+ index_topk + trailing-pool remainder past the sparse threshold."""
235
builder = object.__new__(FlashInferMLASparseSM90Builder)
236
builder._index_topk = 2048
237
builder._index_kpool = 4
tests/v1/attention/test_gdn_metadata_builder.py
+1
-2
@@ -187,8 +187,7 @@ def test_gdn_build_classification(test_case: GDNBuildTestCase):
187
def test_has_initial_state_after_reclassification():
188
"""After reclassification, num_prefills > 0 so the prefill kernel path
189
should compute has_initial_state. For the reclassified request with
190
- context_lens > 0, the corresponding entry must be True.
191
- """
190
+ context_lens > 0, the corresponding entry must be True."""
191
builder = _create_gdn_builder(num_speculative_tokens=2)
192
batch = BatchSpec(seq_lens=[65, 20], query_lens=[1, 3])
193
meta = _build(builder, batch, num_decode_draft_tokens=[-1, 2])
tests/v1/attention/test_indexer_dcp_localize.py
+6
-12
@@ -56,8 +56,7 @@ def _ref_stable_topk_from_candidates_fp64(
56
) -> torch.Tensor:
57
"""Pure-PyTorch reference for the CuteDSL stable-topk selector order
58
(score desc, then lowest global token id). Selects the same SET as the
59
- kernel; only the set is compared in tests.
60
- """
59
+ kernel; only the set is compared in tests."""
60
num_rows, num_candidates = candidate_scores.shape
61
device = candidate_scores.device
62
select_k = min(k, num_candidates)
@@ -122,8 +121,7 @@ def _dcp_lse_merge(
121
class _FakeDCPGroup:
122
"""Single-process stand-in: ``all_gather`` returns the pre-built
123
concatenation of every rank's packed ``(score, global_id)`` candidates,
125
- mirroring the one packed all-gather the merge issues.
126
- """
124
+ mirroring the one packed all-gather the merge issues."""
125
126
def __init__(self, gathered_packed: torch.Tensor) -> None:
127
self.gathered_packed = gathered_packed
@@ -209,8 +207,7 @@ def _merge_local_topks_global_with_fake_dcp(
207
"""Run ``_merge_dcp_topk_global`` for every rank against a faked
208
all-gather and return each rank's global-index result (all ranks should
209
agree). The fake pre-builds the packed candidate concatenation the merge's
212
- single ``all_gather`` would return.
213
- """
210
+ single ``all_gather`` would return."""
211
# The merge is now CuteDSL-only (no PyTorch fallback), so it runs the real
212
# Triton pack + CuteDSL selector kernels even behind the faked all-gather.
213
if not current_platform.is_cuda() or not has_cutedsl():
@@ -712,8 +709,7 @@ def test_dcp_filter_compaction_matches_reference(
709
"""In-kernel compaction must, for every row, produce exactly the rank-owned
710
physical slots packed into [0, valid_count) with -1 in the tail -- the same
711
SET a reference filter + sort/gather produces. Uses wide rows (> BLOCK_N
715
- valid slots), with interior -1 gaps.
716
- """
712
+ valid slots), with interior -1 gaps."""
713
device = torch.device("cuda")
714
torch.manual_seed(7)
715
dcp_size = 2
@@ -871,8 +867,7 @@ def test_decode_topk_pads_surplus_with_negative_one():
867
so a non-(-1) pad would be silently attended. This is the common case under
868
DCP, where each rank's local seq_len = global / world is usually << topk.
869
Checked on the *set* of valid indices (the kernel may order them by score,
874
- not position).
875
- """
870
+ not position)."""
871
torch.manual_seed(0)
872
device = torch.device("cuda")
873
topk = 8
@@ -918,8 +913,7 @@ def test_sparse_decode_dcp_short_context_matches_non_dcp():
913
"""End-to-end DCP decode where the global seq_len < topk (so every rank's
914
local top-k is surplus-padded). Exercises the kernel surplus -> merge mask
915
-> global top-k -> physical localize -> LSE merge chain for the common
921
- short-context decode case, vs the non-DCP reference.
922
- """
916
+ short-context decode case, vs the non-DCP reference."""
917
torch.manual_seed(4)
918
device = torch.device("cuda")
919
world = 2
tests/v1/attention/test_kpool_tail_slot_mapping.py
+7
-14
@@ -58,8 +58,7 @@ def test_tail_backend_layout_matches_kernel_pointer_arithmetic():
58
def make_tail_block_table(own_blocks, width=64):
59
"""Tail-group block table as BlockTables produces it: column 0 holds the
60
request's single KpoolTailManager block, the remaining columns are never
61
- written and stay zero.
62
- """
61
+ written and stay zero."""
62
bt = torch.zeros(len(own_blocks), width, dtype=torch.int32)
63
bt[:, 0] = torch.tensor(own_blocks, dtype=torch.int32)
64
return bt
@@ -67,8 +66,7 @@ def make_tail_block_table(own_blocks, width=64):
66
67
def legacy_generic_tail_slots(block_table, query_start_loc, positions):
68
"""Reference of the generic ``_compute_slot_mappings_kernel`` arithmetic
70
- (block_table.py:305-313) applied to the tail group's table.
71
- """
69
+ (block_table.py:305-313) applied to the tail group's table."""
70
slots = []
71
for req in range(block_table.shape[0]):
72
for i in range(query_start_loc[req], query_start_loc[req + 1]):
@@ -109,8 +107,7 @@ def make_batch(per_req_positions, padded_len=None):
107
108
def test_legacy_generic_mapping_collapses_onto_block_zero():
109
"""The bug: with the manager's 1-column block table, the generic kernel
112
- maps every pos >= kpool onto tail block 0, and distinct requests collide.
113
- """
110
+ maps every pos >= kpool onto tail block 0, and distinct requests collide."""
111
own_blocks = [5, 9]
112
per_req = [list(range(10)), list(range(12))] # prompts of len 10 and 12
113
positions, qsl, _, num_actual, num_reqs = make_batch(per_req)
@@ -140,8 +137,7 @@ def test_legacy_generic_mapping_collapses_onto_block_zero():
137
def test_circular_mapping_isolates_requests():
138
"""The fix: every token lands in its own request's block at pos % kpool,
139
and no slot is ever shared by two different requests (slots do recur
143
- within a request every kpool positions -- that is the circular design).
144
- """
140
+ within a request every kpool positions -- that is the circular design)."""
141
own_blocks = [5, 9]
142
per_req = [list(range(10)), list(range(12))]
143
positions, qsl, slot_mapping, num_actual, num_reqs = make_batch(per_req)
@@ -169,8 +165,7 @@ def test_circular_mapping_isolates_requests():
165
def test_circular_mapping_matches_generic_for_short_requests(prompt_len):
166
"""For pos < kpool the generic kernel already picks the own block, so the
167
two mappings agree while every position fits the request's first block
172
- (single-request behavior is unchanged).
173
- """
168
+ (single-request behavior is unchanged)."""
169
own_blocks = [7]
170
per_req = [list(range(prompt_len))]
171
positions, qsl, slot_mapping, num_actual, num_reqs = make_batch(per_req)
@@ -280,8 +275,7 @@ class TailRingMirror:
275
"""Mirror of _kpool_tail_seed_kernel / _kpool_decode_update_batched_kernel
276
addressing: block = tail_slot // kpool, ring offset = pos % kpool; a pool
277
completing at pos reads ring slots (pool_start + s) % kpool and uses the
283
- current token's own K/score for the last member.
284
- """
278
+ current token's own K/score for the last member."""
279
280
def __init__(self, num_blocks, kpool=KPOOL):
281
self.kpool = kpool
@@ -324,8 +318,7 @@ def tail_slot_for(mapping, req, pos, own_block):
318
319
def run_scenario(mapping, interleave):
320
"""Requests A (block 5, prompt len 9) and B (block 9, prompt len 11)
327
- decode concurrently; returns A's boundary pool [8, 9, 10, 11].
328
- """
321
+ decode concurrently; returns A's boundary pool [8, 9, 10, 11]."""
322
ring = TailRingMirror(num_blocks=16)
323
blocks = {"A": 5, "B": 9}
324
prompts = {"A": 9, "B": 11}
tests/v1/attention/test_mamba_update_block_table.py
+7
-14
@@ -28,8 +28,7 @@ def _make_vllm_config(
28
block_size: int | None = None,
29
):
30
"""Create a minimal mock VllmConfig with only the fields the builder
31
- accesses, avoiding any model download / HF config inspection.
32
- """
31
+ accesses, avoiding any model download / HF config inspection."""
32
speculative_config = (
33
SimpleNamespace(
34
num_speculative_tokens=num_speculative_tokens,
@@ -75,8 +74,7 @@ def test_mamba_single_token_prompt_runs_as_prefill():
74
def test_update_block_table_copies_block_idx_to_persistent_buffers():
75
"""update_block_table() must write block_idx tensors to the current
76
builder's persistent buffers, not leave them pointing to a different
78
- builder's buffers.
79
- """
77
+ builder's buffers."""
78
block_size = 16
79
max_model_len = 256
80
num_reqs = 4
@@ -180,8 +178,7 @@ def test_state_indices_tensor_d_includes_num_speculative_blocks():
178
bug 1: with mamba_cache_mode='all' and speculative decoding enabled,
179
the cudagraph buffer for state_indices_tensor_d must allocate the same
180
per-request column count as the runtime block table, which includes
183
- num_speculative_blocks trailing scratch columns.
184
- """
181
+ num_speculative_blocks trailing scratch columns."""
182
block_size = 16
183
max_model_len = 256
184
max_num_seqs = 4
@@ -214,8 +211,7 @@ def test_block_idx_cudagraph_capture_padded_by_num_reqs():
211
bug 2: with mamba_cache_mode='all' and spec decode, _update_metadata_for
212
_cudagraph_capture must slice block_idx_last_{scheduled,computed}_token
213
by the request count (padded_bs == num_reqs), not by num_decode_tokens.
217
- Past num_decodes, the slice must be zero-filled.
218
- """
214
+ Past num_decodes, the slice must be zero-filled."""
215
block_size = 16
216
max_model_len = 256
217
max_num_seqs = 8
@@ -295,8 +291,7 @@ def test_block_idx_prev_step_persistent_buffer_allocated():
291
block_idx_last_scheduled_token_prev_step as a persistent buffer with the
292
same shape as the existing block_idx_last_{scheduled,computed}_token
293
buffers, so cudagraph capture records a stable pointer for the prev-step
298
- input anchor consumed by mamba_mixer2's input gather.
299
- """
294
+ input anchor consumed by mamba_mixer2's input gather."""
295
block_size = 16
296
max_model_len = 256
297
max_num_seqs = 8
@@ -324,8 +319,7 @@ def test_block_idx_prev_step_persistent_buffer_allocated():
319
320
def test_block_idx_prev_step_persistent_buffer_skipped_without_spec_decode():
321
"""Without spec decode, the prev-step buffer is unused and must not be
327
- allocated — the input anchor reduces to last_computed_token.
328
- """
322
+ allocated — the input anchor reduces to last_computed_token."""
323
block_size = 16
324
max_model_len = 256
325
max_num_seqs = 8
@@ -349,8 +343,7 @@ def test_block_idx_prev_step_cudagraph_capture_uses_persistent_buffer():
343
"""_update_metadata_for_cudagraph_capture must copy the prev-step anchor
344
into the builder's persistent buffer (so cudagraph replay reads from the
345
same underlying memory), pad past num_decodes with zero, and return a
352
- slice of the persistent buffer in the metadata.
353
- """
346
+ slice of the persistent buffer in the metadata."""
347
block_size = 16
348
max_model_len = 256
349
max_num_seqs = 8
tests/v1/attention/test_mla_backends.py
+1
-2
@@ -171,8 +171,7 @@ def test_glm5_flashinfer_masked_mha_routing(
171
def test_concat_k_nope_k_pe_matches_torch_cat(qk_rope_head_dim):
172
"""The K concat used by the MLA prefill context loop must equal torch.cat of
173
k_nope with the broadcast k_pe; with no RoPE part it returns k_nope itself
174
- instead of allocating and copying.
175
- """
174
+ instead of allocating and copying."""
175
torch.manual_seed(0)
176
num_tokens, num_heads, qk_nope_head_dim = 5, 4, 256
177
k_nope = torch.randn(num_tokens, num_heads, qk_nope_head_dim, dtype=torch.bfloat16)
tests/v1/attention/test_mla_prefill_quant_output.py
+3
-6
@@ -134,8 +134,7 @@ def test_flash_attn_registers_warmup_only_for_fa4(
134
135
def test_flash_attn_prefill_backend_signature_accepts_fused_kwargs():
136
"""run_prefill_new_tokens must accept out/output_scale so the direct
137
- (non-**kwargs) call in forward_mha type- and runtime-checks.
138
- """
137
+ (non-**kwargs) call in forward_mha type- and runtime-checks."""
138
import inspect
139
140
params = inspect.signature(
@@ -151,8 +150,7 @@ def test_flash_attn_prefill_backend_signature_accepts_fused_kwargs():
150
151
def test_mla_impl_forward_mha_accepts_output_scale():
152
"""The abstract MLA impl forward_mha must carry output_scale so every
154
- override (and the unconditional forward_impl call) stays compatible.
155
- """
153
+ override (and the unconditional forward_impl call) stays compatible."""
154
import inspect
155
156
from vllm.v1.attention.backend import MLAAttentionImpl
@@ -179,8 +177,7 @@ _FUSED_FP8_SKIP = _fused_fp8_skip_reason()
177
def test_fa4_fused_fp8_output_matches_post_quant(default_vllm_config):
178
"""FA4's fused FP8 write (output_scale, flash-attention#135) must match the
179
bf16-attention + standalone static-FP8-quant path it replaces, since
182
- production uses the same output_scale for both.
183
- """
180
+ production uses the same output_scale for both."""
181
from vllm.model_executor.layers.quantization.input_quant_fp8 import QuantFP8
182
from vllm.model_executor.layers.quantization.utils.quant_utils import GroupShape
183
from vllm.platforms import current_platform
tests/v1/attention/test_mla_prefill_selector.py
+1
-2
@@ -315,8 +315,7 @@ class TestBackendValidation:
315
316
def test_flash_attn_accepts_glm53_flash_nope_dimensions(self):
317
"""(256, 0, 256) runs the same FA kernels as GLM-5's (192, 64, 256); a
318
- RoPE-carrying 320-wide query does not.
319
- """
318
+ RoPE-carrying 320-wide query does not."""
319
try:
320
from vllm.v1.attention.backends.mla.prefill.flash_attn import (
321
FlashAttnPrefillBackend,
tests/v1/attention/test_replayssm_metadata_builder.py
+1
-2
@@ -257,8 +257,7 @@ def test_replayssm_write_pos(case: ReplaySSMBuildCase):
257
258
def test_resumed_request_differs_from_fresh():
259
"""Same token count, different decode_base: fresh (base 100) -> write_pos 5,
260
- resumed (base 105) -> write_pos 0.
261
- """
260
+ resumed (base 105) -> write_pos 0."""
261
builder = _create_replayssm_builder(16)
262
batch = BatchSpec(seq_lens=[106, 106], query_lens=[1, 1])
263
common = create_common_attn_metadata(batch, BLOCK_SIZE, DEVICE).replace(
tests/v1/attention/test_rocm_attention_backends_selection.py
+1
-2
@@ -517,8 +517,7 @@ def test_auto_selection_for_kv_connector(
517
aiter_found, expected_backend, mock_vllm_config, mock_get_cdna_version
518
):
519
"""Auto-selection with a KV connector and AITER enabled resolves to unified attn,
520
- and to triton attn if AITER not enabled.
521
- """
520
+ and to triton attn if AITER not enabled."""
521
from vllm.platforms.rocm import RocmPlatform
522
523
with patch(
tests/v1/attention/test_sparse_indexer_decode_seq_lens.py
+4
-8
@@ -102,8 +102,7 @@ def expected_row_seq_lens(per_req_positions, batch_size, next_n):
102
103
def test_legacy_flat_layout_misaligns_and_bleeds():
104
"""The bug: ``positions[:n] + 1`` with padded-row coordinates reads other
105
- requests' positions and prefill positions.
106
- """
105
+ requests' positions and prefill positions."""
106
decode_lens, per_req, positions = make_non_uniform_batch()
107
batch_size = decode_lens.shape[0]
108
next_n = int(decode_lens.max())
@@ -138,8 +137,7 @@ def test_helper_uniform_layout_matches_flat_slice():
137
138
def test_helper_padded_layout_per_row():
139
"""Non-uniform batches map every padded row to its own token's position;
141
- pad rows get 0 (empty tail).
142
- """
140
+ pad rows get 0 (empty tail)."""
141
decode_lens, per_req, positions = make_non_uniform_batch()
142
out = _decode_topk_seq_lens(positions, decode_lens, 8, 3, 4, requires_padding=True)
143
expected = expected_row_seq_lens(per_req, 3, 4)
@@ -151,8 +149,7 @@ def test_helper_padded_layout_per_row():
149
def expand_tail_region(dec_seq):
150
"""Run the production pure-torch expand + append pair (the fused kernel
151
replicates it exactly on the identity path) and return the tail columns
154
- [TOPK_TOKENS, TOPK_TOKENS + KPOOL - 1).
155
- """
152
+ [TOPK_TOKENS, TOPK_TOKENS + KPOOL - 1)."""
153
rows = dec_seq.shape[0]
154
pool_ids = torch.arange(SELECT_K, dtype=torch.int64).expand(rows, SELECT_K)
155
valid = torch.ones_like(pool_ids, dtype=torch.bool)
@@ -166,8 +163,7 @@ def expand_tail_region(dec_seq):
163
def test_tail_expansion_legacy_vs_fixed():
164
"""End-to-end tail consequence: the fixed mapping appends exactly the
165
request's trailing incomplete pool; the legacy flat slice drops real tail
169
- tokens and emits indices far past the request's own sequence.
170
- """
166
+ tokens and emits indices far past the request's own sequence."""
167
decode_lens, per_req, positions = make_non_uniform_batch()
168
n = 12
169
fixed = _decode_topk_seq_lens(
tests/v1/attention/test_sparse_mla_backends.py
+9
-18
@@ -909,8 +909,7 @@ def test_index_group_convert_during_piecewise_capture():
909
runs in the following eager break. The convert's side stream must not
910
wait on ``logical_topk_ready`` there: an event recorded inside a captured
911
segment is graph-local, and an eager wait on it raises
912
- cudaErrorInvalidValue.
913
- """
912
+ cudaErrorInvalidValue."""
913
device = torch.device(DEVICE_TYPE)
914
num_tokens, num_topk, num_requests, blocks_per_req, block_size = 8, 128, 4, 4, 16
915
@@ -1049,8 +1048,7 @@ def test_triton_convert_rejects_req_id_longer_than_token_indices():
1048
req_id but the output is allocated like token_indices, so a full-batch
1049
req_id combined with an MQA-subset token_indices wrote past the end of
1050
the output buffer. The wrapper must reject the length mismatch instead
1052
- of corrupting memory.
1053
- """
1051
+ of corrupting memory."""
1052
device = torch.device(DEVICE_TYPE)
1053
num_topk_tokens = 128
1054
block_size = 64
@@ -1105,8 +1103,7 @@ def test_flashmla_forward_bf16_kv_slices_req_id_to_mqa_tokens():
1103
is active, forward_mqa only receives the leading decode tokens, but
1104
_forward_bf16_kv passed the full-batch req_id_per_token to the index
1105
conversion, making it write past the end of its output buffer. The call
1108
- site must slice req_id_per_token to the MQA tokens.
1109
- """
1106
+ site must slice req_id_per_token to the MQA tokens."""
1107
device = torch.device(DEVICE_TYPE)
1108
num_topk_tokens = 128
1109
block_size = 64
@@ -1204,8 +1201,7 @@ def test_split_prefill_chunks(seq_lens, max_buf, expected):
1201
)
1202
def test_masked_mha_workspace_fits_single_request_boundary(max_query_len, expected):
1203
"""A 32K prefill needs the default workspace exactly; shrinking it would
1207
- push a supported request onto MQA.
1208
- """
1204
+ push a supported request onto MQA."""
1205
assert (
1206
_masked_mha_workspace_fits(
1207
batch_size=1,
@@ -1263,8 +1259,7 @@ def test_is_masked_mha_available_model_dims(
1259
):
1260
"""The allow-list gates masked MHA per exact model geometry: the DeepSeek-V3.2,
1261
GLM-5 and NoPE GLM-5.3-Flash layouts on an SM100-family GPU with FA4 and an
1266
- unquantized KV cache, nothing else.
1267
- """
1262
+ unquantized KV cache, nothing else."""
1263
import vllm.model_executor.layers.attention.sparse_mla_attention as mod
1264
1265
monkeypatch.setattr(
@@ -3604,8 +3599,7 @@ def test_fp8_mixed_batch_dcp_neutralizes_empty_rows(monkeypatch):
3599
"""A decode row whose top-k shard holds no local candidates (all -1) has
3600
undefined kernel out/lse; it must come back as (0, -inf), the identity of
3601
the cross-rank LSE merge, or a NaN would survive the merge even at zero
3607
- weight (0 * NaN = NaN).
3608
- """
3602
+ weight (0 * NaN = NaN)."""
3603
num_tokens, num_heads, head_dim = 3, 2, 3
3604
q = torch.empty(num_tokens, num_heads, head_dim, device=DEVICE_TYPE)
3605
local_indices = torch.tensor(
@@ -3778,8 +3772,7 @@ def test_hisparse_fp8_prefill_gather_uses_dedicated_stream(monkeypatch):
3772
def test_sparse_impl_observes_repointed_indexer_buffer():
3773
"""The MTP proposer repoints the draft's indexer at the target model's buffer
3774
after the backend impl is built, so the impl must resolve the buffer per read.
3781
- Snapshotting it in __init__ leaves the layer reading indices nothing writes.
3782
- """
3775
+ Snapshotting it in __init__ leaves the layer reading indices nothing writes."""
3776
impl = object.__new__(FlashInferMLASparseImpl)
3777
own = torch.zeros(4, 8, dtype=torch.int32)
3778
target = torch.ones(4, 8, dtype=torch.int32)
@@ -3795,8 +3788,7 @@ def test_sparse_impl_observes_repointed_indexer_buffer():
3788
3789
def test_explicit_topk_buffer_supersedes_indexer():
3790
"""Backbone skip-topk layers have no indexer, and the proposer also assigns the
3798
- shared buffer directly onto draft submodules.
3799
- """
3791
+ shared buffer directly onto draft submodules."""
3792
impl = object.__new__(FlashInferMLASparseImpl)
3793
indexer = SimpleNamespace(
3794
topk_indices_buffer=torch.zeros(2, 2, dtype=torch.int32),
@@ -3811,8 +3803,7 @@ def test_explicit_topk_buffer_supersedes_indexer():
3803
3804
def test_sparse_mla_common_impl_resolves_buffer_lazily():
3805
"""Guards the whole SparseMLACommonImpl family at once: a backend that
3814
- snapshots the buffer instead silently loses MTP buffer sharing.
3815
- """
3806
+ snapshots the buffer instead silently loses MTP buffer sharing."""
3807
assert issubclass(SparseMLACommonImpl, SharedTopkIndicesBuffer)
3808
assert isinstance(SparseMLACommonImpl.topk_indices_buffer, property), (
3809
"topk_indices_buffer must stay a lazily-resolved property"
tests/v1/attention/test_trtllm_attention_integration.py
+3
-6
@@ -198,8 +198,7 @@ def _create_nvfp4_hnd_kv_cache(
198
199
def _run_trtllm_integration(batch_spec, kv_cache_dtype="auto", model_name=MODEL):
200
"""Run TRTLLM attention through the full FlashInfer pipeline
201
- and compare against an SDPA reference.
202
- """
201
+ and compare against an SDPA reference."""
202
set_random_seed(42)
203
device = torch.device(f"{DEVICE_TYPE}:0")
204
@@ -427,8 +426,7 @@ def _run_trtllm_integration(batch_spec, kv_cache_dtype="auto", model_name=MODEL)
426
def test_trtllm_gen_full_attention_integration(batch_spec_name: str):
427
"""Test TRTLLM gen-full attention through the full FlashInfer
428
MetadataBuilder.build() -> FlashInferImpl.forward() pipeline,
430
- with real TRTLLM kernels on Blackwell.
431
- """
429
+ with real TRTLLM kernels on Blackwell."""
430
_run_trtllm_integration(BATCH_SPECS[batch_spec_name])
431
432
@@ -439,8 +437,7 @@ def test_trtllm_gen_full_attention_integration(batch_spec_name: str):
437
@torch.inference_mode()
438
def test_trtllm_gen_nvfp4_kv_integration(batch_spec_name: str):
439
"""Test TRTLLM attention with nvfp4 KV cache through the full
442
- FlashInfer MetadataBuilder.build() -> FlashInferImpl.forward() pipeline.
443
- """
440
+ FlashInfer MetadataBuilder.build() -> FlashInferImpl.forward() pipeline."""
441
_run_trtllm_integration(
442
BATCH_SPECS[batch_spec_name],
443
kv_cache_dtype="nvfp4",
tests/v1/core/prefix_cache/test_partial_prefix_cache_hits.py
+17
-34
@@ -2,8 +2,7 @@
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Fine-grained partial prefix-cache hits for hybrid (full attention + mamba
4
"align") models: scheduler chunk splitting, partial tail registration, CoW
5
-on partial hits, and same-step deferral.
6
-"""
5
+on partial hits, and same-step deferral."""
6
7
from math import lcm
8
from types import SimpleNamespace
@@ -175,8 +174,7 @@ def test_mamba_align_split_partial_tail_schedule(dcp_world_size: int):
174
"""Chunk ends with partial hits on: block-aligned chunks, one extra stop
175
at the prompt's last hash boundary (registering the partial tail), then
176
the remaining tokens. block=512, hash=32, prompt=10000, budget=8192:
178
- 0 -> 8192 -> 9728 -> 9984 -> 10000.
179
- """
177
+ 0 -> 8192 -> 9728 -> 9984 -> 10000."""
178
block_size = 512
179
scheduler_block_size = block_size * dcp_world_size
180
hash_block_size = 32
@@ -744,8 +742,7 @@ def test_hash_aligned_query_end_uses_regular_partial_tail():
742
743
def test_external_mamba_hit_same_block_uses_running_cow_on_continue():
744
"""An external mid-block hit must become a running request even when its
747
- first continuation does not need another Mamba block.
748
- """
745
+ first continuation does not need another Mamba block."""
746
hash_block_size = 2
747
mamba_block_size = 4 * hash_block_size
748
kv_cache_config = KVCacheConfig(
@@ -817,8 +814,7 @@ def test_external_mamba_hit_same_block_uses_running_cow_on_continue():
814
815
def test_boundary_state_offloads_returns_cow_target():
816
"""Boundary hand-offs expose aligned snapshots and the partial-tail CoW
820
- target, never the overwritten CoW source.
821
- """
817
+ target, never the overwritten CoW source."""
818
hash_block_size = 2
819
block_size = 2 * hash_block_size
820
kv_cache_config = KVCacheConfig(
@@ -1004,8 +1000,7 @@ def test_connector_finish_registers_partial_tail_before_cleanup():
1000
def test_boundary_state_offload_dropped_when_request_freed_before_drain():
1001
"""A hand-off recorded in the same scheduling pass as the request's death
1002
must not be drained: its release hook has already run, so draining would
1007
- leak a pinned block.
1008
- """
1003
+ leak a pinned block."""
1004
hash_block_size = 2
1005
block_size = 2 * hash_block_size
1006
kv_cache_config = KVCacheConfig(
@@ -1052,8 +1047,7 @@ def test_boundary_state_offload_dropped_when_request_freed_before_drain():
1047
1048
def test_boundary_state_offloads_block_aligned_prompt():
1049
"""A prompt ending on a block boundary registers no CoW partial tail; its
1055
- boundary state block is handed off as a snapshot instead (once).
1056
- """
1050
+ boundary state block is handed off as a snapshot instead (once)."""
1051
hash_block_size = 2
1052
block_size = 2 * hash_block_size
1053
kv_cache_config = KVCacheConfig(
@@ -1107,8 +1101,7 @@ def test_boundary_state_offloads_block_aligned_prompt():
1101
def test_truncate_computed_blocks_preserves_sparse_prefix_positions():
1102
"""truncate_computed_blocks slices each group by its own block size,
1103
keeps null placeholders in the retained prefix, and leaves the original
1110
- lookup result untouched (pure view, no refcount changes).
1111
- """
1104
+ lookup result untouched (pure view, no refcount changes)."""
1105
hash_block_size = 2
1106
kv_cache_config = KVCacheConfig(
1107
num_blocks=24,
@@ -1163,8 +1156,7 @@ def test_truncate_computed_blocks_preserves_sparse_prefix_positions():
1156
1157
def test_truncate_computed_blocks_allows_short_mamba_group_only():
1158
"""External state may replace a short Mamba hit, but other groups must
1166
- cover the aligned local endpoint.
1167
- """
1159
+ cover the aligned local endpoint."""
1160
hash_block_size = 2
1161
kv_cache_config = KVCacheConfig(
1162
num_blocks=24,
@@ -1306,8 +1298,7 @@ def test_hybrid_mamba_partial_tail_owner_continue_preserves_later_hit():
1298
def test_hybrid_mamba_moved_partial_entry_defers_same_step_hit():
1299
"""The owner's move re-arms the same-step guard: the moved entry is
1300
filled by this step's copy, and chained same-step copies read stale
1309
- sources, so a request hitting it in the move step must be deferred.
1310
- """
1301
+ sources, so a request hitting it in the move step must be deferred."""
1302
hash_block_size = 2
1303
block_size = 2 * hash_block_size
1304
kv_cache_config = KVCacheConfig(
@@ -1597,8 +1588,7 @@ def test_hybrid_partial_hash_truncates_full_attention_hit_length():
1588
1589
def test_cow_retained_blocks_returned_for_release():
1590
"""new_step_starts returns the CoW copy retentions instead of freeing
1600
- them; the scheduler owns releasing them once the copy has run.
1601
- """
1591
+ them; the scheduler owns releasing them once the copy has run."""
1592
hash_block_size = 2
1593
block_size = 2 * hash_block_size
1594
kv_cache_config = KVCacheConfig(
@@ -1651,8 +1641,7 @@ def test_cow_retained_blocks_returned_for_release():
1641
1642
def test_free_cow_retained_blocks_defers_until_copy_step_processed():
1643
"""Scheduler releases CoW retentions immediately when the copy's step has
1654
- been processed (or deferral is off), and defers them otherwise.
1655
- """
1644
+ been processed (or deferral is off), and defers them otherwise."""
1645
from collections import deque
1646
1647
freed: list = []
@@ -1689,8 +1678,7 @@ def test_free_cow_retained_blocks_defers_until_copy_step_processed():
1678
def test_full_attention_eagle_drops_one_hash_unit():
1679
"""With fine-grained partial hits, eagle rewinds the hit by one hash unit
1680
instead of a whole cache block: the tail block's KV is append-only, so it
1692
- still covers the reduced length and stays in the hit as a partial block.
1693
- """
1681
+ still covers the reduced length and stays in the hit as a partial block."""
1682
from vllm.v1.core.block_pool import BlockPool
1683
from vllm.v1.core.single_type_kv_cache_manager import FullAttentionManager
1684
@@ -1766,8 +1754,7 @@ def test_hybrid_partial_hit_with_eagle_stays_within_group_blocks():
1754
"""Regression: with eagle, the mamba group must not receive the eagle
1755
lookup margin — its finder never applies the drop, so it could return a
1756
hit past the blocks the (dropped) full-attention group covers, crashing
1769
- the consumer's CoW with block_idx >= len(req_blocks).
1770
- """
1757
+ the consumer's CoW with block_idx >= len(req_blocks)."""
1758
hash_block_size = 2
1759
block_size = 2 * hash_block_size
1760
kv_cache_config = KVCacheConfig(
@@ -2369,8 +2356,7 @@ def test_retention_snapshots_handed_off_with_exact_block_ids():
2356
"""Under sparse retention, each retained mamba boundary state block is
2357
handed to the connector with its exact block id. Connectors must not resolve
2358
align-mode state blocks positionally because the block table is not
2372
- append-only.
2373
- """
2359
+ append-only."""
2360
hash_block_size = 2
2361
block_size = 4
2362
manager = make_kv_cache_manager(
@@ -2411,8 +2397,7 @@ def test_snapshot_handoff_dense_default_retention():
2397
"""With dense (default) retention, every materialized mamba boundary
2398
state block is handed off — regular mamba-align + prefix-match-unit
2399
deployments get store-able boundary snapshots without setting a
2414
- prefix-cache retention interval.
2415
- """
2400
+ prefix-cache retention interval."""
2401
hash_block_size = 2
2402
block_size = 4
2403
manager = make_kv_cache_manager(
@@ -2444,8 +2429,7 @@ def test_snapshot_handoff_dense_default_retention():
2429
2430
def _run_chunked_prefill(manager, req, chunk_size, num_chunks):
2431
"""Prefill ``req`` one ``chunk_size`` chunk per scheduler step, yielding the
2447
- boundary-state hand-offs offered (and claimed) at each step.
2448
- """
2432
+ boundary-state hand-offs offered (and claimed) at each step."""
2433
computed_blocks, num_computed, _ = manager.get_computed_blocks(req)
2434
for step in range(num_chunks):
2435
manager.new_step_starts()
@@ -2509,8 +2493,7 @@ def test_boundary_states_offered_past_prompt_for_resumed_prefill():
2493
``num_prompt_tokens``. A resumed request re-prefills its generated tokens
2494
and every group re-saves them, so filtering on the original prompt length
2495
would silently strip the mamba key for boundaries full attention still
2512
- stores; only the connector knows where its save window ends.
2513
- """
2496
+ stores; only the connector knows where its save window ends."""
2497
block_size = 8
2498
prompt_len = block_size
2499
manager = make_kv_cache_manager(
tests/v1/core/test_async_scheduler.py
+2
-4
@@ -552,8 +552,7 @@ def _create_async_pp_scheduler(
552
553
def _assert_ordered_subset(delivered: list[int], emitted: list[int]) -> None:
554
"""Delivered tokens must be an order-preserving subset of the emitted
555
- tokens with no duplicates (tokens are globally unique).
556
- """
555
+ tokens with no duplicates (tokens are globally unique)."""
556
it = iter(emitted)
557
for token in delivered:
558
assert token in it, f"token {token} delivered out of order or twice"
@@ -563,8 +562,7 @@ def _assert_positions_consistent(req, engine: PipelinedEngine) -> None:
562
"""The i-th delivered output token must be one the runner sampled for
563
exactly sequence position prompt_len + i: catches a preempted request's
564
stale output landing on a position the resumed request resampled (or
566
- vice versa), which token-stream equality alone cannot see.
567
- """
565
+ vice versa), which token-stream equality alone cannot see."""
566
for i, token in enumerate(req.output_token_ids):
567
expected = req.num_prompt_tokens + i
568
actual = engine.emitted_position[token]
tests/v1/core/test_contiguous_kv_packing.py
+6
-12
@@ -178,8 +178,7 @@ def _shared_layout_config():
178
class TestCSALinearGrouping:
179
"""A CSA + linear-attention model (sparse attention with a compressor ring,
180
plus sharded GDN and one TP-replicated PLE state) goes through the generic
181
- packed-group path; no model-specific branch is involved.
182
- """
181
+ packed-group path; no model-specific branch is involved."""
182
183
@staticmethod
184
def _mamba_groups(groups):
@@ -194,8 +193,7 @@ class TestCSALinearGrouping:
193
def test_replicated_state_gets_its_own_group(self):
194
"""The PLE state is TP-replicated and a different size, so it must not
195
share a manager group with the sharded GDN states (the NIXL worker
197
- requires exactly one single-layer replicated group).
198
- """
196
+ requires exactly one single-layer replicated group)."""
197
groups = get_kv_cache_groups(_shared_layout_config(), _make_csa_linear_specs())
198
199
mamba_groups = self._mamba_groups(groups)
@@ -248,8 +246,7 @@ class TestCSALinearGrouping:
246
def test_scratch_group_survives_computed_block_truncation(self):
247
"""The scratch group contributes no computed blocks, so truncating a
248
lookup result must skip it: its block size is the ring capacity, which
251
- neither divides the hit length nor bounds the (empty) block list.
252
- """
249
+ neither divides the hit length nor bounds the (empty) block list."""
250
config = _shared_layout_config()
251
config.cache_config.enable_prefix_caching = True
252
groups = get_kv_cache_groups(config, _make_csa_linear_specs())
@@ -363,8 +360,7 @@ class TestCSALinearGrouping:
360
per page size, which is emitted whole, or a single-layer state that
361
cannot be split at all -- the mamba layers must be sized against it.
362
Sizing them against a narrower bucket splits them past what the block
366
- already fits, spending a pool block per extra group for no saving.
367
- """
363
+ already fits, spending a pool block per extra group for no saving."""
364
config = _mock_vllm_config("BLNHC")
365
config.speculative_config = None
366
specs = {}
@@ -409,8 +405,7 @@ class TestSlidingWindowBucketCap:
405
unbalanced 8-layer paged MLA bucket. Left whole, the SWA bucket would
406
set the block width and the MLA group would fill under a third of
407
every block; capped, it splits into groups no wider than the MLA
412
- page.
413
- """
408
+ page."""
409
config = _shared_layout_config()
410
specs: dict[str, KVCacheSpec] = {}
411
for layer, ratio in ((2, 2), (8, 2), (14, 2), (20, 1)):
@@ -611,8 +606,7 @@ class TestCompressorRingGroup:
606
"""DeepSeek-V4.1 compressor state: a CircularBufferSpec ring (capacity
607
8) beside 128-token paged MLA groups and 64-token SWA groups. The ring
608
claims one block per request, never hashes, and does not disturb the
614
- scheduler/hash block sizes the paged groups imply.
615
- """
609
+ scheduler/hash block sizes the paged groups imply."""
610
config = _shared_layout_config()
611
config.cache_config.enable_prefix_caching = True
612
specs: dict[str, KVCacheSpec] = {
tests/v1/core/test_encoder_cache_manager.py
+3
-6
@@ -367,8 +367,7 @@ def test_free_request_with_duplicate_mm_hashes():
367
"""Freeing a request whose two inputs share the same mm_hash must fully
368
clean up request_cached_ids. After the first free_encoder_input call,
369
cached[mm_hash] becomes empty; the second call must still remove the
370
- remaining input_id from request_cached_ids.
371
- """
370
+ remaining input_id from request_cached_ids."""
371
manager = EncoderCacheManager(cache_size=20)
372
373
req = MockRequest("r1", ["imgA", "imgA"], [4, 4])
@@ -384,8 +383,7 @@ def test_free_request_with_duplicate_mm_hashes():
383
384
def test_duplicate_mm_hash_stays_referenced_until_last_free():
385
"""`cached` holds one reference per request, not per position, so freeing
387
- the first of two occurrences must not release the entry.
388
- """
386
+ the first of two occurrences must not release the entry."""
387
manager = EncoderCacheManager(cache_size=20)
388
req = MockRequest("r1", ["imgA", "imgA"], [4, 4])
389
@@ -406,8 +404,7 @@ def test_duplicate_mm_hash_stays_referenced_until_last_free():
404
def test_duplicate_mm_hash_is_not_evicted_before_last_use():
405
"""An item repeated within one request (an image carried across
406
conversation turns) must not become reclaimable capacity while a later
409
- occurrence still has to be spliced in, or the encoder recomputes it.
410
- """
407
+ occurrence still has to be spliced in, or the encoder recomputes it."""
408
manager = EncoderCacheManager(cache_size=8)
409
req = MockRequest("r1", ["imgA", "imgA"], [4, 4])
410
other = MockRequest("r2", ["imgB"], [8])
tests/v1/core/test_kv_cache_utils.py
+10
-20
@@ -2593,8 +2593,7 @@ def test_get_kv_cache_config_kpool_tail_coowns_indexer_tensor():
2593
"""The kpool tail parasitizes the indexer tensors instead of getting its
2594
own: sibling idx/tail tensors paired by layer order, zero standalone tail
2595
bytes, one shared block per request, and no prefix-caching leakage from
2596
- the kpool-sized scratch group.
2597
- """
2596
+ the kpool-sized scratch group."""
2597
model_config = ModelConfig(max_model_len=8192)
2598
vllm_config = VllmConfig(model_config=model_config)
2599
@@ -2665,8 +2664,7 @@ def test_get_kv_cache_config_kpool_tail_coowns_indexer_tensor():
2664
2665
def test_glm5_kpool_tail_does_not_drag_hash_block_size():
2666
"""The tail's kpool-sized scratch block (4 tokens) must not constrain the
2668
- prefix-cache hash granularity: participating groups alone decide it.
2669
- """
2667
+ prefix-cache hash granularity: participating groups alone decide it."""
2668
model_config = ModelConfig(max_model_len=8192)
2669
vllm_config = VllmConfig(model_config=model_config)
2670
@@ -2742,8 +2740,7 @@ def test_get_kv_cache_config_mamba_hybrid_sharing_infeasible_no_indexer():
2740
2741
def test_get_kv_cache_config_mamba_hybrid_sharing_prepadded_mamba():
2742
"""Platform-prepadded mamba pages (mamba_page_size_padded hint) must not
2745
- disable slot sharing; the layout re-pads them to the MLA page.
2746
- """
2743
+ disable slot sharing; the layout re-pads them to the MLA page."""
2744
model_config = ModelConfig(max_model_len=8192)
2745
vllm_config = VllmConfig(model_config=model_config)
2746
@@ -2774,8 +2771,7 @@ def test_get_kv_cache_config_mamba_hybrid_sharing_prepadded_mamba():
2771
def test_get_kv_cache_config_mamba_hybrid_sharing_pp_balanced_projection():
2772
"""Round-robin mamba grouping keeps practical PP splits balanced: every
2773
stage's largest projected mamba group slice fits its projected MLA
2777
- layers, so per-stage slot tensors all have an MLA owner.
2778
- """
2774
+ layers, so per-stage slot tensors all have an MLA owner."""
2775
model_config = ModelConfig(max_model_len=8192)
2776
vllm_config = VllmConfig(model_config=model_config)
2777
@@ -2819,8 +2815,7 @@ def test_get_kv_cache_config_mamba_hybrid_sharing_pp_group_count_bump(monkeypatc
2815
"""PP=4's default partition [11,11,12,11] leaves stage 0 with 2 MLA
2816
layers but a round-robin slice of 3 under the minimum 4 mamba groups;
2817
grouping bumps to 5 groups so every stage's projection keeps sharing
2822
- on instead of silently falling back on stage 0.
2823
- """
2818
+ on instead of silently falling back on stage 0."""
2819
from vllm.config import ParallelConfig
2820
from vllm.distributed.utils import get_pp_indices
2821
@@ -2869,8 +2864,7 @@ def test_get_kv_cache_config_mamba_hybrid_sharing_pp_starved_stage(monkeypatch):
2864
def test_get_kv_cache_config_mamba_hybrid_sharing_beats_cross_layers_flag():
2865
"""Hybrid slot sharing must take precedence over the experimental
2866
enable_cross_layers_blocks packed layout: generic packing would give the
2872
- MLA slots a strided view, breaking the contiguous virtual split.
2873
- """
2867
+ MLA slots a strided view, breaking the contiguous virtual split."""
2868
model_config = ModelConfig(max_model_len=8192)
2869
kv_transfer_config = KVTransferConfig(
2870
kv_connector="NixlConnector",
@@ -3172,8 +3166,7 @@ def test_multi_run_layer_compact_strides_place_hoisted_heads():
3166
"""A layer-compact run region is its own dense allocation: under LHBNC the head
3167
groups sit between the layers and the blocks, so a run's block stride is one head
3168
group's slice, not the whole page (regression test for setStorage out-of-bounds
3175
- on ROCm hybrid models).
3176
- """
3169
+ on ROCm hybrid models)."""
3170
full = new_kv_cache_spec()
3171
swa = new_sliding_window_spec(sliding_window=full.block_size * 2)
3172
page = full.page_size_bytes
@@ -3252,8 +3245,7 @@ def test_mla_with_incompatible_swa_uses_one_full_allocation_group(caplog_vllm):
3245
def test_hidden_states_with_tp_scales_page_size():
3246
"""When TP shrinks KV pages below the hidden-state per-token cost,
3247
get_kv_cache_groups must scale up target block sizes so that the
3255
- common page accommodates the unsharded hidden states.
3256
- """
3248
+ common page accommodates the unsharded hidden states."""
3249
# Simulate TP=4 sharding a model with 8 KV heads → 2 per rank.
3250
# KV page = block_size(16) * num_kv_heads(2) * head_size(64) * dtype(2)
3251
# = 16 * 2 * 64 * 2 = 4096 bytes.
@@ -4083,8 +4075,7 @@ def test_check_enough_kv_cache_memory_reserves_null_block():
4075
4076
def test_is_full_attention_spec_unwraps_uniform_type_specs():
4077
"""``UniformTypeKVCacheSpecs`` is not a ``FullAttentionSpec``, so callers
4086
- scanning groups with a bare isinstance miss DeepSeek-V4-shaped configs.
4087
- """
4078
+ scanning groups with a bare isinstance miss DeepSeek-V4-shaped configs."""
4079
common = dict(num_kv_heads=1, head_size=1, dtype=torch.float32)
4080
full = FullAttentionSpec(block_size=4, **common)
4081
mla = MLAAttentionSpec(block_size=4, **common)
@@ -4253,8 +4244,7 @@ def test_no_warning_when_draft_group_is_identified(caplog_vllm):
4244
4245
def _deepseek_v4_specs(model_version="deepseek_v4"):
4246
"""DeepseekV4-shaped specs: full MLA layers plus sliding-window MLA layers
4256
- at differing page sizes, with the MTP draft layer registered last.
4257
- """
4247
+ at differing page sizes, with the MTP draft layer registered last."""
4248
return {
4249
"model.layers.0.self_attn.attn": new_mla_spec(),
4250
"model.layers.1.self_attn.attn": new_mla_spec(),
tests/v1/core/test_output.py
+3
-6
@@ -55,8 +55,7 @@ def _mm_feature(offset: int, length: int) -> MultiModalFeatureSpec:
55
56
def test_strip_covered_mm_data() -> None:
57
"""Items fully inside the computed prefix lose their data; items touching
58
- the uncomputed region keep it; already-None data stays None.
59
- """
58
+ the uncomputed region keep it; already-None data stays None."""
59
from dataclasses import replace
60
61
covered = _mm_feature(offset=0, length=100)
@@ -108,8 +107,7 @@ def _mm_feature_mixed(offset: int, length: int) -> MultiModalFeatureSpec:
107
108
def test_strip_covered_mm_data_mrope() -> None:
109
"""For M-RoPE models, covered items keep their keep_on_cpu metadata fields
111
- (the worker needs them to compute positions); payload fields are dropped.
112
- """
110
+ (the worker needs them to compute positions); payload fields are dropped."""
111
covered = _mm_feature_mixed(offset=0, length=100)
112
uncovered = _mm_feature_mixed(offset=300, length=100)
113
@@ -129,8 +127,7 @@ def test_strip_covered_mm_data_shm_address_item() -> None:
127
"""SHM address descriptors must survive stripping even when covered: the
128
worker needs the address to resolve the payload and to acknowledge the
129
sender's writer reference. Stripping it crashed the SHM receiver cache on
132
- the second identical request (vllm-project/vllm#54994).
133
- """
130
+ the second identical request (vllm-project/vllm#54994)."""
131
address_item = MultiModalKwargsItem(
132
{
133
"address": MultiModalFieldElem(data=4096, field=MultiModalBatchedField()),
tests/v1/core/test_prefix_caching.py
+25
-50
@@ -126,8 +126,7 @@ def make_kv_cache_manager(kv_cache_config: KVCacheConfig, **kwargs) -> KVCacheMa
126
"""Build a ``KVCacheManager``, deriving ``scheduler_block_size`` from the
127
config (LCM of group block sizes) unless explicitly provided. This mirrors
128
``resolve_kv_cache_block_sizes`` for the non-context-parallel case used by
129
- these tests, so callers don't have to pass it at every site.
130
- """
129
+ these tests, so callers don't have to pass it at every site."""
130
kwargs.setdefault(
131
"scheduler_block_size",
132
lcm(*(g.kv_cache_spec.block_size for g in kv_cache_config.kv_cache_groups)),
@@ -3330,8 +3329,7 @@ def test_kv_cache_events_with_lora(blocks_to_cache: int):
3329
@pytest.mark.parametrize("group_id", [0, 1, 2])
3330
def test_block_stored_event_group_idx(group_id: int):
3331
"""Test BlockStored events emitted by cache_full_blocks carry the correct
3333
- group_idx.
3334
- """
3332
+ group_idx."""
3333
block_size = 4
3334
num_tokens = block_size * 2
3335
@@ -3624,8 +3622,7 @@ def test_block_removed_event_group_idx(group_id: int):
3622
def test_emit_cached_block_events():
3623
"""emit_cached_block_events emits one BlockStored for already-cached
3624
(reused) prefix blocks, carrying the correct group_idx /
3627
- parent_block_hash / token_ids, and without mutating block state.
3628
- """
3625
+ parent_block_hash / token_ids, and without mutating block state."""
3626
block_size = 4
3627
num_cached_blocks = 3
3628
kv_cache_group_id = 1
@@ -3738,8 +3735,7 @@ def test_emit_cached_block_events_zero_cached():
3735
3736
def test_eagle_enabled_removes_last_block():
3737
"""Verify Eagle does NOT remove blocks when request
3741
- length is divisible by block size.
3742
- """
3738
+ length is divisible by block size."""
3739
block_size = 16
3740
manager = make_kv_cache_manager(
3741
make_kv_cache_config(block_size, num_blocks=10),
@@ -4142,8 +4138,7 @@ def test_hybrid_cache_blocks_swa_tail_window_only():
4138
(its right-to-left scan stops once a contiguous match is found). Blocks
4139
earlier in the segment can never serve a hit, so
4140
``HybridKVCacheCoordinator.cache_blocks`` should skip them rather than
4145
- polluting the prefix-cache hash map.
4146
- """
4141
+ polluting the prefix-cache hash map."""
4142
block_size = 8
4143
# Full attn block_size=32, SWA block_size=8, sw=8 -> lcm=32.
4144
# tail = ceil(7/8) = 1; per_segment = 32/8 = 4.
@@ -4214,8 +4209,7 @@ def test_hybrid_cache_blocks_clamped_to_lcm():
4209
Chunks past the last lcm-aligned boundary can never participate in a
4210
cache hit (find_longest_cache_hit always returns lcm-aligned hits), so
4211
caching them only pollutes the prefix-cache hash map and keeps blocks
4217
- on the LRU list that could otherwise return to the free pool.
4218
- """
4212
+ on the LRU list that could otherwise return to the free pool."""
4213
block_size = 16
4214
# Full attn block_size=32, SWA block_size=16 -> lcm=32.
4215
kv_cache_config = KVCacheConfig(
@@ -4350,8 +4344,7 @@ def test_hybrid_local_kv_retention_interval_aligns_in_manager():
4344
)
4345
def test_hybrid_local_kv_retention_interval_rejects_invalid(interval, expected_match):
4346
"""A retention interval that is negative or not a multiple of
4353
- scheduler_block_size errors out at construction time.
4354
- """
4347
+ scheduler_block_size errors out at construction time."""
4348
block_size = 8
4349
kv_cache_config = KVCacheConfig(
4350
num_blocks=100,
@@ -4821,8 +4814,7 @@ def test_block_lookup_cache_multi_blocks_per_key():
4814
def test_can_fit_full_sequence_swa_cap_admits_long_prompt():
4815
"""Hybrid full+SWA model with a pool sized at the startup minimum should
4816
admit a prompt longer than the SWA cap, because SlidingWindowManager
4824
- recycles blocks during chunked prefill (issue #39734).
4825
- """
4817
+ recycles blocks during chunked prefill (issue #39734)."""
4818
block_size = 16
4819
sliding_window = 4 * block_size # 64 tokens
4820
max_num_batched_tokens = 8 * block_size # 128 tokens
@@ -4917,8 +4909,7 @@ def test_full_sequence_admission_reserves_device_blocks_for_immediate_chunk(
4909
4910
def test_can_fit_full_sequence_full_attention_still_gates_oversized():
4911
"""The cap only loosens the SWA group; a prompt that exceeds the
4920
- full-attention pool capacity must still be rejected.
4921
- """
4912
+ full-attention pool capacity must still be rejected."""
4913
block_size = 16
4914
sliding_window = 4 * block_size
4915
max_num_batched_tokens = 8 * block_size
@@ -5037,8 +5028,7 @@ def _take_free_blocks(manager: KVCacheManager, num_blocks: int) -> list[KVCacheB
5028
without removing them. These ref_cnt==0 blocks stand in for evictable
5029
cache-hit blocks left behind by a previous (e.g. preempted) request, and
5030
sitting at the head guarantees a later group's external ``get_new_blocks``
5040
- would contend for them on unpatched code (issue #33775).
5041
- """
5031
+ would contend for them on unpatched code (issue #33775)."""
5032
blocks: list[KVCacheBlock] = []
5033
head = manager.block_pool.free_block_queue.fake_free_list_head
5034
for _ in range(num_blocks):
@@ -5049,8 +5039,7 @@ def _take_free_blocks(manager: KVCacheManager, num_blocks: int) -> list[KVCacheB
5039
5040
def _assert_no_double_allocation(manager: KVCacheManager, req_id: str) -> None:
5041
"""No physical block may be handed out twice across groups, and every
5052
- block referenced by the request must have a live ref_cnt.
5053
- """
5042
+ block referenced by the request must have a live ref_cnt."""
5043
block_ids = manager.get_blocks(req_id).get_block_ids()
5044
flat = [block_id for group in block_ids for block_id in group]
5045
assert len(set(flat)) == len(flat), "Block IDs are not unique across groups"
@@ -5077,8 +5066,7 @@ def _cross_group_cache_hit(
5066
) -> Request:
5067
"""Allocate ``req_id`` with a per-group local prefix hit plus external
5068
(connector) computed tokens, driving the coordinator's two-phase path.
5080
- Returns the allocated request so callers can free it (e.g. to preempt).
5081
- """
5069
+ Returns the allocated request so callers can free it (e.g. to preempt)."""
5070
block_size = _two_phase_block_size(manager)
5071
hit_blocks = _take_free_blocks(manager, num_groups * local_blocks_per_group)
5072
cache_hit = KVCacheBlocks(
@@ -5173,8 +5161,7 @@ def test_swa_free_split_keeps_cached_tail_ahead_of_scratch():
5161
"""Dense retention: freeing an SWA request must place its
5162
uncached scratch blocks at the front of the free queue (recycled first)
5163
and keep its cached checkpoint blocks at the back (retained for prefix
5176
- hits). This split is always-on, independent of the retention interval.
5177
- """
5164
+ hits). This split is always-on, independent of the retention interval."""
5165
block_size = 8
5166
kv_cache_config = KVCacheConfig(
5167
num_blocks=100,
@@ -5285,8 +5272,7 @@ def _make_pure_swa_manager(block_size, sliding_window, num_blocks=100, **kwargs)
5272
def test_pure_swa_retention_interval_caches_sparse_tails():
5273
"""Sparse retention must work for a pure-SWA single-group model, not just
5274
hybrid models: only the per-interval tails plus the latest replay tail are
5288
- cached, and a replay still hits the latest replayable boundary.
5289
- """
5275
+ cached, and a replay still hits the latest replayable boundary."""
5276
block_size = 16
5277
manager = _make_pure_swa_manager(
5278
block_size, sliding_window=block_size, retention_interval=64
@@ -5358,8 +5344,7 @@ def test_pure_swa_retention_latest_only():
5344
5345
def test_pure_swa_dense_retention_caches_all():
5346
"""With retention set to ``None``, a pure-SWA model keeps dense behavior:
5361
- every block boundary is a potential hit, so all blocks are cached.
5362
- """
5347
+ every block boundary is a potential hit, so all blocks are cached."""
5348
block_size = 16
5349
manager = _make_pure_swa_manager(block_size, sliding_window=block_size)
5350
@@ -5388,8 +5373,7 @@ def test_mamba_reachable_block_mask_sparsifies_retention():
5373
"""Mamba state-snapshot retention: with a configured retention interval,
5374
the manager keeps one cached state per interval-sized segment (plus the
5375
latest replay boundary) instead of a snapshot per block, which is what
5391
- lets a small attention block_size avoid Mamba dominating the KV pool.
5392
- """
5376
+ lets a small attention block_size avoid Mamba dominating the KV pool."""
5377
from vllm.v1.core.single_type_kv_cache_manager import MambaManager
5378
5379
block_size = 16
@@ -5427,8 +5411,7 @@ def test_mamba_reachable_block_mask_pins_shared_prefix():
5411
"""A Marconi-detected shared prefix (``shared_prefix_boundary``) lands before
5412
``num_prompt`` so the replay-boundary rule alone would drop it. The mask must
5413
pin the single state block ending on that boundary so sparse retention does
5430
- not defeat cross-request shared-prefix reuse.
5431
- """
5414
+ not defeat cross-request shared-prefix reuse."""
5415
from vllm.v1.core.single_type_kv_cache_manager import MambaManager
5416
5417
block_size = 16
@@ -5476,8 +5459,7 @@ def test_mamba_shared_prefix_survives_zero_retention():
5459
detection) keeps its Mamba state block cached under
5460
``prefix_cache_retention_interval=0``, which otherwise retains only the
5461
end-of-prompt replay boundary. Without this, a shared prefix (junction
5479
- before ``num_prompt``) would be recomputed by every sharing request.
5480
- """
5462
+ before ``num_prompt``) would be recomputed by every sharing request."""
5463
block_size = 16
5464
5465
# 16-block (256-token) prompt; replay boundary is block 240 // 16 - 1 = 14.
@@ -5519,8 +5501,7 @@ def test_mamba_shared_prefix_reuse_under_zero_retention():
5501
detecting request must stay reusable by a later request under
5502
``prefix_cache_retention_interval=0``. Without the pin the junction is
5503
masked out and the later request misses; with it (and under dense) the reuse
5522
- is preserved.
5523
- """
5504
+ is preserved."""
5505
block_size = 16
5506
5507
def last_req_hit(retention, pin):
@@ -5603,8 +5584,7 @@ def test_swa_reachable_block_mask_final_partial_segment():
5584
def test_swa_reachable_block_mask_pins_shared_prefix():
5585
"""SWA analog of the Mamba pin: the shared-prefix junction must keep the
5586
``need``-block sliding-window tail ending on that boundary (not a single
5606
- block), so a windowed hit can land there under sparse retention.
5607
- """
5587
+ block), so a windowed hit can land there under sparse retention."""
5588
from vllm.v1.core.single_type_kv_cache_manager import SlidingWindowManager
5589
5590
block_size = 16
@@ -5649,8 +5629,7 @@ def test_swa_reachable_block_mask_pins_shared_prefix():
5629
def test_swa_reachable_block_mask_with_dcp_scaling():
5630
"""DCP shards each block's KV across ranks, scaling the effective block size.
5631
Verify that dcp_world_size > 1 scales block size in reachability calculations,
5652
- producing different masks than dcp_world_size=1.
5653
- """
5632
+ producing different masks than dcp_world_size=1."""
5633
from vllm.v1.core.single_type_kv_cache_manager import SlidingWindowManager
5634
5635
block_size = 16
@@ -5709,8 +5688,7 @@ def test_swa_reachable_block_mask_sub_block_alignment_is_dense(
5688
multiple of the DCP-scaled block size) cannot be represented exactly. This
5689
happens for hybrid offloading (e.g. Gemma), where alignment_tokens is the
5690
full-attention chunk size and need not divide the SWA block size. The mask
5712
- must fall back to dense (None) rather than raise.
5713
- """
5691
+ must fall back to dense (None) rather than raise."""
5692
from vllm.v1.core.single_type_kv_cache_manager import SlidingWindowManager
5693
5694
spec = SlidingWindowSpec(
@@ -5738,8 +5716,7 @@ def test_mamba_reachable_block_mask_ignores_dcp():
5716
"""Mamba uses TP, not DCP: each rank holds the full recurrent state, so a
5717
state block spans kv_cache_spec.block_size tokens regardless of DCP. The
5718
mask must not scale by dcp_world_size, so retention granularity is
5741
- identical for any DCP world size.
5742
- """
5719
+ identical for any DCP world size."""
5720
from vllm.v1.core.single_type_kv_cache_manager import MambaManager
5721
5722
spec = MambaSpec(
@@ -5773,8 +5750,7 @@ def test_mamba_reachable_block_mask_ignores_dcp():
5750
5751
def test_mamba_reachable_block_mask_large_dcp_stays_sparse():
5752
"""A large DCP world size must not scale the Mamba block size, so it can
5776
- never collapse sparse retention into dense caching.
5777
- """
5753
+ never collapse sparse retention into dense caching."""
5754
from vllm.v1.core.single_type_kv_cache_manager import MambaManager
5755
5756
spec = MambaSpec(
@@ -5809,8 +5785,7 @@ def test_swa_shared_prefix_reuse_under_zero_retention():
5785
"""SWA cross-request analog: a partial shared prefix's sliding-window tail
5786
must stay reusable under ``prefix_cache_retention_interval=0``. Without
5787
the pin the junction window is masked out and a later request misses; with
5812
- it (and under dense) reuse is preserved.
5813
- """
5788
+ it (and under dense) reuse is preserved."""
5789
block_size = 16
5790
5791
def last_req_hit(retention, pin):
tests/v1/core/test_scheduler.py
+28
-56
@@ -538,8 +538,7 @@ def test_throttle_defers_inflight_prefill_chunk():
538
"""DP prefill balancing throttles ALL prefill compute on a throttled step,
539
not just new admissions: an in-progress (chunked) prefill already in the
540
running queue is also deferred, so the step runs decode-only, while a
541
- separate decode keeps being scheduled.
542
- """
541
+ separate decode keeps being scheduled."""
542
scheduler = create_scheduler(
543
max_num_seqs=16, max_num_batched_tokens=50, enable_chunked_prefill=True
544
)
@@ -593,8 +592,7 @@ def test_throttle_capacity_bound_guard_admits():
592
"""Saturation guard: if a cadence-aligned release step cannot drain the
593
waiting prefill queue (it ran out of token budget), the throttle backs off on
594
the next step so the backlog cannot grow into a TTFT avalanche -- prefills are
596
- admitted even though throttle_prefills is set.
597
- """
595
+ admitted even though throttle_prefills is set."""
596
scheduler = create_scheduler(
597
max_num_seqs=16, max_num_batched_tokens=200, enable_chunked_prefill=True
598
)
@@ -1293,8 +1291,7 @@ def test_pending_hisparse_reclamation_defers_preemption(monkeypatch):
1291
1292
def test_prefix_cache_query_not_inflated_by_connector_defer():
1293
"""The GPU prefix-cache query is recorded at admission, so a request the
1296
- connector defers several times is counted once, not once per retry.
1297
- """
1294
+ connector defers several times is counted once, not once per retry."""
1295
num_defers_before_matching = 3
1296
scheduler = create_scheduler(
1297
enable_prefix_caching=True,
@@ -1322,8 +1319,7 @@ def test_prefix_cache_query_not_inflated_by_connector_defer():
1319
1320
def test_preemption_re_records_prefix_cache_query():
1321
"""A preempted request re-enters the lookup on resume, so its recomputation
1325
- is counted again into the preempted stats.
1326
- """
1322
+ is counted again into the preempted stats."""
1323
scheduler = create_scheduler(enable_prefix_caching=True)
1324
request = create_requests(num_requests=1)[0]
1325
scheduler.add_request(request)
@@ -1359,8 +1355,7 @@ def test_preemption_re_records_prefix_cache_query():
1355
1356
def test_prefix_cache_stats_not_recorded_when_caching_disabled():
1357
"""With prefix caching off there is no local lookup, so admitting a request
1362
- records no phantom miss.
1363
- """
1358
+ records no phantom miss."""
1359
scheduler = create_scheduler(enable_prefix_caching=False)
1360
for request in create_requests(num_requests=2):
1361
scheduler.add_request(request)
@@ -1374,8 +1369,7 @@ def test_prefix_cache_stats_not_recorded_when_caching_disabled():
1369
1370
def test_prefix_cache_stats_counted_once_for_retried_then_scheduled_request():
1371
"""A real cache hit rejected once by allocate_slots and admitted on the next
1377
- step is counted exactly once, hits included.
1378
- """
1372
+ step is counted exactly once, hits included."""
1373
block_size = 16
1374
scheduler = create_scheduler(
1375
enable_prefix_caching=True,
@@ -3094,8 +3088,7 @@ def create_requests_with_priority(
3088
3089
def test_priority_scheduling_basic_ordering():
3090
"""Test that requests are scheduled in priority order
3097
- (lower value = higher priority).
3098
- """
3091
+ (lower value = higher priority)."""
3092
scheduler = create_scheduler_with_priority()
3093
3094
# Create requests with different priorities
@@ -3124,8 +3117,7 @@ def test_priority_scheduling_basic_ordering():
3117
3118
def test_priority_scheduling_arrival_time_tiebreaker():
3119
"""Test that arrival time is used
3127
- as tiebreaker when priorities are equal.
3128
- """
3120
+ as tiebreaker when priorities are equal."""
3121
scheduler = create_scheduler_with_priority()
3122
3123
# Create requests with same priority but different arrival times
@@ -3282,8 +3274,7 @@ def test_priority_scheduling_preemption():
3274
3275
def test_priority_scheduling_no_preemption_when_space_available():
3276
"""Test that preemption doesn't happen
3285
- when there's space for new requests.
3286
- """
3277
+ when there's space for new requests."""
3278
scheduler = create_scheduler_with_priority(
3279
max_num_seqs=3, # Allow 3 concurrent requests
3280
max_num_batched_tokens=200, # Sufficient token budget
@@ -3336,8 +3327,7 @@ def test_priority_scheduling_no_preemption_when_space_available():
3327
3328
def test_priority_scheduling_preemption_victim_selection():
3329
"""Test that the correct victim is selected for
3339
- preemption based on priority and arrival time.
3340
- """
3330
+ preemption based on priority and arrival time."""
3331
# This test verifies the priority-based victim selection logic
3332
# by checking the waiting queue order after adding requests with different
3333
# priorities
@@ -3457,8 +3447,7 @@ def test_priority_scheduling_waiting_queue_order():
3447
3448
def test_priority_scheduling_fcfs_fallback():
3449
"""Test that FCFS behavior is maintained when all
3460
- requests have same priority.
3461
- """
3450
+ requests have same priority."""
3451
scheduler = create_scheduler_with_priority()
3452
3453
# Create requests with same priority but different arrival times
@@ -3527,8 +3516,7 @@ def test_priority_scheduling_with_limited_slots():
3516
3517
def test_priority_scheduling_heap_property():
3518
"""Test that the waiting queue maintains heap
3530
- property for priority scheduling.
3531
- """
3519
+ property for priority scheduling."""
3520
scheduler = create_scheduler_with_priority(
3521
max_num_seqs=1, # Only one request can run at a time
3522
)
@@ -3753,8 +3741,7 @@ def test_priority_scheduling_preemption_and_resumption_when_out_of_kv(
3741
use_ec_connector, ec_role, use_v2_model_runner
3742
):
3743
"""Test that priority scheduling preempts lower priority requests
3756
- when out of KV cache space.
3757
- """
3744
+ when out of KV cache space."""
3745
# Create scheduler with very limited memory to force preemption
3746
scheduler = create_scheduler_with_priority(
3747
max_num_seqs=2, # Allow multiple requests
@@ -3899,8 +3886,7 @@ def test_chunked_prefill_disabled_for_encoder_decoder(
3886
enable_chunked_prefill: bool, is_encoder_decoder: bool, expect_enabled: bool
3887
) -> None:
3888
"""Validate that chunked prefill is appropriately disabled for
3902
- encoder-decoder models.
3903
- """
3889
+ encoder-decoder models."""
3890
scheduler_config = SchedulerConfig(
3891
enable_chunked_prefill=enable_chunked_prefill,
3892
is_encoder_decoder=is_encoder_decoder,
@@ -3929,8 +3915,7 @@ def _validate_chunked_prefill_settings_for_encoder_decoder(
3915
scheduler_config: SchedulerConfig, is_encoder_decoder: bool, expect_enabled: bool
3916
) -> None:
3917
"""Validate chunked prefill settings in the scheduler config for
3932
- encoder-decoder models.
3933
- """
3918
+ encoder-decoder models."""
3919
assert scheduler_config.enable_chunked_prefill is expect_enabled
3920
if is_encoder_decoder:
3921
# Encoder-decoder models should automatically disable chunked multimodal
@@ -4020,8 +4005,7 @@ def _assert_right_encoder_inputs(
4005
):
4006
"""Verify that requests/mm_hashes should (not) in scheduled encoder input
4007
If check_exist is False, this function returns True
4023
- if requests are NOT in encoder inputs
4024
- """
4008
+ if requests are NOT in encoder inputs"""
4009
# Get the scheduled encoder inputs
4010
# NOTE: scheduled_encoder_inputs is a dictionary with request id as key
4011
scheduled_encoder_inputs = output.scheduled_encoder_inputs
@@ -4182,8 +4166,7 @@ def test_ec_connector_text_only_request(use_kv_connector):
4166
@pytest.mark.parametrize("use_kv_connector", [False, True])
4167
def test_ec_connector_cache_hit_external_load(use_kv_connector):
4168
"""Test ec_consumer loads from external cache when hit.
4185
- A normal basic operation for EPD disaggrgation
4186
- """
4169
+ A normal basic operation for EPD disaggrgation"""
4170
scheduler = create_scheduler(
4171
model="llava-hf/llava-1.5-7b-hf",
4172
enable_prefix_caching=True,
@@ -4630,8 +4613,7 @@ def test_priority_scheduling_ec_connector_preemption_and_resumption(
4613
cache_exist, use_kv_connector
4614
):
4615
"""Test that priority scheduling preempts lower priority requests
4633
- when out of KV cache space.
4634
- """
4616
+ when out of KV cache space."""
4617
# Create scheduler with very limited memory to force preemption
4618
scheduler = create_scheduler_with_priority(
4619
model="llava-hf/llava-1.5-7b-hf",
@@ -5300,8 +5282,7 @@ def test_scheduler_kv_connector_stats():
5282
5283
def test_ec_connector_update_connector_output_called():
5284
"""Test that worker-side EC connector output is forwarded to the
5303
- EC connector's update_connector_output hook.
5304
- """
5285
+ EC connector's update_connector_output hook."""
5286
scheduler = create_scheduler(
5287
model="llava-hf/llava-1.5-7b-hf",
5288
use_ec_connector=True,
@@ -5506,8 +5487,7 @@ def test_variable_length_cross_attn_block_allocation():
5487
5488
def test_cross_attn_blocks_not_over_allocated():
5489
"""Test that cross-attention blocks are not over-allocated compared to
5509
- what each request actually needs.
5510
- """
5490
+ what each request actually needs."""
5491
from math import ceil
5492
5493
block_size = 16
@@ -5603,8 +5583,7 @@ def test_cross_attn_blocks_not_under_allocated():
5583
5584
def test_cross_attn_zero_blocks_without_encoder_inputs():
5585
"""Test that requests without encoder inputs get zero cross-attention
5606
- blocks, even when the scheduler is configured for encoder-decoder.
5607
- """
5586
+ blocks, even when the scheduler is configured for encoder-decoder."""
5587
block_size = 16
5588
scheduler = _create_encoder_decoder_scheduler(block_size=block_size)
5589
@@ -5709,8 +5688,7 @@ def test_free_encoder_inputs_respects_unconfirmed_placeholders():
5688
evicted entry and crashes the engine with "Encoder cache miss". The
5689
scheduler must retain the input until the *confirmed* progress
5690
(num_computed_tokens - num_output_placeholders) passes the range end, so
5712
- that no pending rejection can rewind into the range.
5713
- """
5691
+ that no pending rejection can rewind into the range."""
5692
scheduler = create_scheduler(
5693
model="llava-hf/llava-1.5-7b-hf",
5694
num_speculative_tokens=3,
@@ -5821,8 +5799,7 @@ def test_free_encoder_inputs_defers_for_eagle_lookahead():
5799
position so the drafter's +1 look-ahead mm-embedding gather (which reads one
5800
position past the target's computed range) still finds it cached. This is
5801
the primary mechanism that prevents the drafter "Encoder cache miss"; the
5824
- worker-side token-embedding fallback is only a backstop.
5825
- """
5802
+ worker-side token-embedding fallback is only a backstop."""
5803
scheduler = create_scheduler(model="llava-hf/llava-1.5-7b-hf")
5804
# create_scheduler only builds ngram spec configs; force the eagle path that
5805
# _free_encoder_inputs keys off (its read-ahead deferral).
@@ -5852,8 +5829,7 @@ def test_free_encoder_inputs_defers_for_eagle_lookahead():
5829
5830
def test_free_encoder_inputs_unchanged_without_spec_decode():
5831
"""Without speculative decoding, encoder inputs are freed as soon as
5855
- num_computed_tokens passes the placeholder range, as before.
5856
- """
5832
+ num_computed_tokens passes the placeholder range, as before."""
5833
scheduler = create_scheduler(model="llava-hf/llava-1.5-7b-hf")
5834
mm_positions = [[PlaceholderRange(offset=50, length=100)]]
5835
request = create_requests(
@@ -5884,8 +5860,7 @@ def test_encoder_cache_retained_across_preemption_and_resume():
5860
encoder input must pull the still-cached entry back out of `freeable`
5861
without scheduling a recompute, keeping the scheduler and worker
5862
consistent. The spec-rollback retention margin does not gate this path,
5887
- so it is covered separately here.
5888
- """
5863
+ so it is covered separately here."""
5864
scheduler = create_scheduler(
5865
model="llava-hf/llava-1.5-7b-hf",
5866
num_speculative_tokens=3,
@@ -5929,8 +5904,7 @@ def test_encoder_cache_recomputed_when_evicted_during_preemption():
5904
pressure before it resumes, the scheduler reports the mm_hash as freed
5905
(so the worker drops it) and a resume must schedule a recompute rather
5906
than assume the worker still holds it. check_and_update_cache must
5932
- return False so the encoder input is re-scheduled.
5933
- """
5907
+ return False so the encoder input is re-scheduled."""
5908
scheduler = create_scheduler(
5909
model="llava-hf/llava-1.5-7b-hf",
5910
num_speculative_tokens=3,
@@ -6581,8 +6555,7 @@ def _decode_ready_request(scheduler):
6555
6556
def test_update_draft_token_ids_strips_ngram_padding():
6557
"""ngram_gpu pads unfilled draft slots with -1; manager validation must
6584
- strip them before grammar.validate_tokens (which otherwise raises).
6585
- """
6558
+ strip them before grammar.validate_tokens (which otherwise raises)."""
6559
scheduler = create_scheduler(num_speculative_tokens=4)
6560
request = _decode_ready_request(scheduler)
6561
@@ -6601,8 +6574,7 @@ def test_update_draft_token_ids_strips_ngram_padding():
6574
6575
def test_update_draft_token_ids_in_output_strips_padding():
6576
"""Same guard on the output path; the -1 pad-back for the rejected count
6604
- is preserved (only the input to manager validation is stripped).
6605
- """
6577
+ is preserved (only the input to manager validation is stripped)."""
6578
scheduler = create_scheduler(num_speculative_tokens=4)
6579
request = _decode_ready_request(scheduler)
6580
tests/v1/core/test_swa_inflight_window_free.py
+4
-8
@@ -97,8 +97,7 @@ def test_num_in_flight_tokens_accounting():
97
98
def test_swa_free_waits_for_in_flight_step():
99
"""Async: out-of-window blocks stay allocated until the step that still
100
- reads them has been processed.
101
- """
100
+ reads them has been processed."""
101
scheduler = _create_swa_scheduler(async_scheduling=True)
102
request = create_requests(
103
num_requests=1, num_tokens=NUM_PROMPT_TOKENS, block_size=BLOCK_SIZE
@@ -133,8 +132,7 @@ def test_swa_free_waits_for_in_flight_step():
132
133
def test_swa_free_immediate_when_sync():
134
"""Sync: no in-flight step at schedule time, frees happen at the first
136
- decode allocation as before.
137
- """
135
+ decode allocation as before."""
136
scheduler = _create_swa_scheduler(async_scheduling=False)
137
request = create_requests(
138
num_requests=1, num_tokens=NUM_PROMPT_TOKENS, block_size=BLOCK_SIZE
@@ -173,8 +171,7 @@ def test_swa_admission_cap_accounts_for_overlapping_batches():
171
def test_chunked_local_free_waits_for_in_flight_step():
172
"""Chunked-local attention frees whole chunks left of the current one, and
173
is exposed to the same load-WAR: with async scheduling those chunks must
176
- stay allocated until the in-flight step that still reads them settles.
177
- """
174
+ stay allocated until the in-flight step that still reads them settles."""
175
scheduler = _create_chunked_scheduler(async_scheduling=True)
176
request = create_requests(
177
num_requests=1, num_tokens=NUM_PROMPT_TOKENS, block_size=BLOCK_SIZE
@@ -229,8 +226,7 @@ def test_connector_finish_frees_on_settled_basis():
226
is handed to a KV connector (simple CPU offload / NIXL store), must use the
227
same processed-token basis. Otherwise the connector reads/hands off a block
228
the still-in-flight step is optimistically counted as done with, which is
232
- the load-path WAR this fix closes.
233
- """
229
+ the load-path WAR this fix closes."""
230
scheduler = create_scheduler(
231
block_size=BLOCK_SIZE,
232
async_scheduling=True,
tests/v1/cudagraph/test_breakable_cudagraph.py
+3
-6
@@ -80,8 +80,7 @@ def test_piecewise_capture_builds_fresh_metadata_for_both_passes():
80
@pytest.fixture(autouse=True)
81
def _reset_breakable_tls():
82
"""Defensively clear thread-local capture state between tests so a
83
- failure in one test can't leak "nested capture" errors into the next.
84
- """
83
+ failure in one test can't leak "nested capture" errors into the next."""
84
from vllm.compilation.breakable_cudagraph import BreakableCUDAGraphCapture
85
86
BreakableCUDAGraphCapture._tls.active = None
@@ -291,8 +290,7 @@ def test_capture_replay_matches_eager_simple(cuda_capture_stream):
290
def test_decorator_breaks_when_invoked_inside_capture(cuda_capture_stream):
291
"""Verify @eager_break_during_capture correctly routes through
292
add_eager when inside a capture context, and runs straight through
294
- when there's no active capture.
295
- """
293
+ when there's no active capture."""
294
from vllm.compilation.breakable_cudagraph import (
295
BreakableCUDAGraphCapture,
296
eager_break_during_capture,
@@ -554,8 +552,7 @@ def _mock_vllm_config():
552
553
def test_wrapper_falls_through_on_runtime_mode_mismatch():
554
"""A PIECEWISE-scoped wrapper runs other modes eagerly, capturing
557
- nothing, so an outer CUDAGraphWrapper can own them.
558
- """
555
+ nothing, so an outer CUDAGraphWrapper can own them."""
556
from vllm.compilation.breakable_cudagraph import BreakableCUDAGraphWrapper
557
from vllm.config import CUDAGraphMode
558
from vllm.forward_context import BatchDescriptor, set_forward_context
tests/v1/determinism/test_rms_norm_batch_invariant.py
+1
-2
@@ -275,8 +275,7 @@ def test_rms_norm_per_block_quant_batch_invariant(
275
hidden_size: int, dtype: torch.dtype, seed: int
276
):
277
"""C++ ``rms_norm_per_block_quant`` must be batch invariant across the
278
- block threshold (compiled fp8 block-quant path; block pinned to 512).
279
- """
278
+ block threshold (compiled fp8 block-quant path; block pinned to 512)."""
279
import vllm._custom_ops as ops
280
281
device = torch.device(DEVICE_TYPE)
tests/v1/distributed/test_async_llm_dp.py
+4
-8
@@ -547,8 +547,7 @@ async def test_dp_pause_keep_then_resume(expert_parallel: bool):
547
async def test_dp_pause_keep_race_staggered_engines():
548
"""Race: send pause(keep) to engine 0, then add two requests,
549
then pause(keep) to engine 1. Ensures no deadlock when pause
550
- requests are staggered and requests arrive in between.
551
- """
550
+ requests are staggered and requests arrive in between."""
551
if DP_SIZE != 2:
552
pytest.skip("test_dp_pause_keep_race_staggered_engines requires DP_SIZE=2")
553
@@ -718,8 +717,7 @@ async def test_dp_pause_barrier_request_deadlock():
717
async def test_dp_pause_wait_mode_drains_in_flight():
718
"""mode="wait" through the DP consensus path: the pause lets the
719
in-flight request run to completion while the consensus is pending,
721
- resolves only once drained, and the engine generates again on resume.
722
- """
720
+ resolves only once drained, and the engine generates again on resume."""
721
with ExitStack() as after:
722
engine = AsyncLLM.from_engine_args(_get_dp_pause_engine_args(True))
723
after.callback(engine.shutdown)
@@ -750,8 +748,7 @@ async def test_dp_pause_wait_mode_drains_in_flight():
748
async def test_dp_pause_while_asleep():
749
"""Pausing a sleeping DP engine: sleeping ranks skip dummy batches yet
750
must still reach the pause consensus, and the completion barrier must
753
- be harmless on workers whose memory is unmapped.
754
- """
751
+ be harmless on workers whose memory is unmapped."""
752
with ExitStack() as after:
753
engine = AsyncLLM.from_engine_args(_get_dp_pause_engine_args(True))
754
after.callback(engine.shutdown)
@@ -787,8 +784,7 @@ async def test_dp_pause_completion_implies_device_idle(
784
"""A resolved pause future promises an idle device. Inflate the dummy
785
batches the pause consensus manufactures so any work the pause fails to
786
wait on stays visible, then require a quiet worker stream the moment
790
- pause_generation() returns.
791
- """
787
+ pause_generation() returns."""
788
with ExitStack() as after:
789
# The probes below ship functions through collective_rpc.
790
monkeypatch.setenv("VLLM_ALLOW_INSECURE_SERIALIZATION", "1")
tests/v1/distributed/test_external_lb_dp.py
+1
-2
@@ -24,8 +24,7 @@ TP_SIZE = int(os.getenv("TP_SIZE", "1"))
24
25
class ExternalLBServerManager:
26
"""Manages data parallel vLLM server instances for external
27
- load balancer testing.
28
- """
27
+ load balancer testing."""
28
29
def __init__(
30
self,
tests/v1/distributed/test_hybrid_lb_dp.py
+1
-2
@@ -30,8 +30,7 @@ DP_SIZE_LOCAL = DP_SIZE // NUM_NODES # 2 ranks per node
30
class HybridLBServerManager:
31
"""Manages hybrid data parallel vLLM server instances where each node
32
runs a single logical API server that balances requests only to the
33
- DP engines running on that same node.
34
- """
33
+ DP engines running on that same node."""
34
35
def __init__(
36
self,
tests/v1/distributed/test_internal_lb_dp.py
+3
-6
@@ -107,8 +107,7 @@ async def _run_request_bursts(
107
108
class MultinodeInternalLBServerManager:
109
"""Manages multi-node data parallel vLLM server instances for internal
110
- load balancer testing using --headless mode.
111
- """
110
+ load balancer testing using --headless mode."""
111
112
def __init__(
113
self,
@@ -242,8 +241,7 @@ class MultinodeInternalLBServerManager:
241
242
class APIOnlyServerManager:
243
"""Manages API-only server (Node 0) and headless engines server (Node 1)
245
- for testing separated API server and engine configuration.
246
- """
244
+ for testing separated API server and engine configuration."""
245
246
def __init__(
247
self,
@@ -645,8 +643,7 @@ async def test_api_only_multinode_dp_completion_streaming(
643
model_name: str,
644
) -> None:
645
"""Test API-only server streaming with all engines on separate
648
- headless server.
649
- """
646
+ headless server."""
647
prompt = "What is an LLM?"
648
649
async def make_streaming_request():
tests/v1/distributed/test_pp_dp_v2.py
+4
-8
@@ -82,8 +82,7 @@ async def _generate(engine: AsyncLLM, prompt: str, max_tokens: int) -> int:
82
@pytest.mark.parametrize("async_scheduling", [True, False])
83
async def test_pp_dp_v2_low_concurrency(async_scheduling: bool):
84
"""A single in-flight request at a time, repeated, to exercise the
85
- PP slot ring under empty batches between decodes.
86
- """
85
+ PP slot ring under empty batches between decodes."""
86
with ExitStack() as after:
87
engine = AsyncLLM.from_engine_args(_engine_args(async_scheduling))
88
after.callback(engine.shutdown)
@@ -97,8 +96,7 @@ async def test_pp_dp_v2_low_concurrency(async_scheduling: bool):
96
@pytest.mark.parametrize("async_scheduling", [True, False])
97
async def test_pp_dp_v2_mid_concurrency(async_scheduling: bool):
98
"""64 concurrent requests, staggered, to exercise the steady-state
100
- DP all-reduce + PP slot-ring path.
101
- """
99
+ DP all-reduce + PP slot-ring path."""
100
with ExitStack() as after:
101
engine = AsyncLLM.from_engine_args(_engine_args(async_scheduling))
102
after.callback(engine.shutdown)
@@ -114,8 +112,7 @@ async def test_pp_dp_v2_mid_concurrency(async_scheduling: bool):
112
@pytest.mark.asyncio
113
async def test_pp_dp_v2_abort_mid_decode():
114
"""Cancel half the in-flight requests mid-stream and confirm the
117
- engine survives the abort storm.
118
- """
115
+ engine survives the abort storm."""
116
with ExitStack() as after:
117
engine = AsyncLLM.from_engine_args(_engine_args(async_scheduling=True))
118
after.callback(engine.shutdown)
@@ -155,8 +152,7 @@ async def test_pp_dp_v2_abort_mid_decode():
152
@pytest.mark.asyncio
153
async def test_pp_dp_v2_pause_resume():
154
"""Pause an engine with a request in flight, then resume and confirm
158
- new requests still work.
159
- """
155
+ new requests still work."""
156
with ExitStack() as after:
157
engine = AsyncLLM.from_engine_args(_engine_args(async_scheduling=True))
158
after.callback(engine.shutdown)
tests/v1/e2e/general/test_async_scheduling.py
+2
-4
@@ -48,8 +48,7 @@ def test_without_spec_decoding(
48
monkeypatch: pytest.MonkeyPatch,
49
):
50
"""Test consistency of combos of async scheduling, preemption,
51
- uni/multiproc executor, prefill chunking.
52
- """
51
+ uni/multiproc executor, prefill chunking."""
52
struct_outputs = StructuredOutputsParams(json=sample_json_schema)
53
test_sampling_params: list[dict[str, Any]] = [
54
dict(),
@@ -205,8 +204,7 @@ def run_tests(
204
test_sampling_params: list[dict[str, Any]],
205
):
206
"""Test consistency of combos of async scheduling, preemption,
208
- uni/multiproc executor with spec decoding.
209
- """
207
+ uni/multiproc executor with spec decoding."""
208
# Flex attention supports float32.
209
attention_config = {"backend": "FLEX_ATTENTION"}
210
tests/v1/e2e/general/test_attention_backend_per_kind.py
+1
-2
@@ -72,8 +72,7 @@ def test_backend_per_kind_splits_groups(backend_per_kind, monkeypatch):
72
)
73
def test_backend_per_kind_overrides_global_backend(monkeypatch):
74
"""A per-kind entry wins over the global ``backend`` for its kind; other
75
- kinds fall back to the global backend.
76
- """
75
+ kinds fall back to the global backend."""
76
monkeypatch.setenv("VLLM_ALLOW_INSECURE_SERIALIZATION", "1")
77
llm = LLM(
78
model=MODEL,
tests/v1/e2e/general/test_context_length.py
+2
-4
@@ -34,8 +34,7 @@ def test_decoder_max_context_length_validation(
34
max_tokens: int,
35
) -> None:
36
"""Check vLLM decoder model input validation for edge cases where
37
- the prompt length is (almost) equal to the max model length.
38
- """
37
+ the prompt length is (almost) equal to the max model length."""
38
prompt_ids = [[43] * prompt_len]
39
40
with vllm_runner(
@@ -72,8 +71,7 @@ def test_auto_fit_max_model_len_rejects_oversized_input(
71
"""When max_model_len='auto' and KV cache memory is very limited,
72
the engine auto-fits max_model_len to a small value. The frontend
73
must see this reduced value and reject prompts that exceed it,
75
- rather than accepting them and hanging.
76
- """
74
+ rather than accepting them and hanging."""
75
# Use a small KV cache budget to force auto-fit to a small
76
# max_model_len. Pin block_size=16 so the budget is independent
77
# of the platform's default block size. One block for this model is
tests/v1/e2e/general/test_min_tokens.py
+1
-2
@@ -172,8 +172,7 @@ def llm_v1():
172
173
def test_min_tokens_with_terminal_structured_output(llm_v1: LLM):
174
"""A grammar whose only legal continuation is EOS must stop under
175
- min_tokens instead of sampling outside the grammar.
176
- """
175
+ min_tokens instead of sampling outside the grammar."""
176
params = SamplingParams(
177
temperature=GREEDY,
178
min_tokens=20,
tests/v1/e2e/general/test_sharded_sampling.py
+2
-4
@@ -7,8 +7,7 @@ slightly different kernel/collective states (measured: same-state boots are
7
bitwise identical across the two modes; cross-state boots differ by up to
8
~0.25 logprob and can flip a near-tie token). A real sharding bug — rows
9
routed to the wrong request, misaligned gathers — produces many-nats
10
-divergence and scrambled top-k sets, far outside these bounds.
11
-"""
10
+divergence and scrambled top-k sets, far outside these bounds."""
11
12
import pytest
13
@@ -107,8 +106,7 @@ def _assert_logprob_dicts_close(ref_lps, out_lps, what: str) -> None:
106
@multi_gpu_test(num_gpus=2)
107
def test_sharded_sampling_outputs_match(monkeypatch: pytest.MonkeyPatch):
108
"""Generation, logprobs, and prompt logprobs match between batch-sharded
110
- sampling and the replicated fallback, up to measured boot-state noise.
111
- """
109
+ sampling and the replicated fallback, up to measured boot-state noise."""
110
monkeypatch.setenv("VLLM_USE_V2_MODEL_RUNNER", "1")
111
# Required for the collective_rpc mode check below.
112
monkeypatch.setenv("VLLM_ALLOW_INSECURE_SERIALIZATION", "1")
tests/v1/e2e/spec_decode/acceptance_rates/mtp_other/test_synthetic.py
+1
-2
@@ -11,8 +11,7 @@ from ...utils import compute_acceptance_len, get_test_prompts
11
@single_gpu_only
12
def test_synthetic_acceptance_rate(vllm_runner):
13
"""Verify that synthetic rejection sampling produces an acceptance
14
- length close to the requested mean acceptance length.
15
- """
14
+ length close to the requested mean acceptance length."""
15
num_spec_tokens = 3
16
expected_acceptance_len = 1.875
17
tolerance = 0.15
tests/v1/e2e/spec_decode/draft_model/test_draft_model.py
+7
-14
@@ -167,8 +167,7 @@ def test_draft_model_tensor_parallelism(vllm_runner):
167
@multi_gpu_only(num_gpus=2)
168
def test_draft_model_engine_args_tensor_parallelism():
169
"""Ensure the vllm_config for the draft model is created correctly,
170
- and independently of the target model (quantization, TP, etc.)
171
- """
170
+ and independently of the target model (quantization, TP, etc.)"""
171
engine_args = EngineArgs(
172
model="Qwen/Qwen3-1.7B-FP8", # <<< tgt quantized
173
tensor_parallel_size=2,
@@ -199,8 +198,7 @@ def test_draft_model_engine_args_tensor_parallelism():
198
199
def _apply_draft_moe_backend(vllm_config: VllmConfig) -> VllmConfig:
200
"""Replicate SpecDecodeBaseProposer._create_draft_vllm_config logic
202
- so we can test it without instantiating a full proposer.
203
- """
201
+ so we can test it without instantiating a full proposer."""
202
spec_cfg = vllm_config.speculative_config
203
if spec_cfg.moe_backend is not None:
204
return replace(
@@ -225,8 +223,7 @@ def _platform_moe_backend(monkeypatch: pytest.MonkeyPatch) -> MoEBackend:
223
224
def test_draft_model_moe_backend_override(monkeypatch: pytest.MonkeyPatch):
225
"""When moe_backend is set in speculative_config, the draft VllmConfig
228
- should use it while the target keeps its own setting.
229
- """
226
+ should use it while the target keeps its own setting."""
227
target_moe_backend = _platform_moe_backend(monkeypatch)
228
engine_args = EngineArgs(
229
model="Qwen/Qwen3-1.7B",
@@ -251,8 +248,7 @@ def test_draft_model_moe_backend_override(monkeypatch: pytest.MonkeyPatch):
248
249
def test_draft_model_moe_backend_inherits_target(monkeypatch: pytest.MonkeyPatch):
250
"""When moe_backend is not set in speculative_config, the draft should
254
- inherit the target's moe_backend.
255
- """
251
+ inherit the target's moe_backend."""
252
target_moe_backend = _platform_moe_backend(monkeypatch)
253
engine_args = EngineArgs(
254
model="Qwen/Qwen3-1.7B",
@@ -275,8 +271,7 @@ def test_draft_model_moe_backend_inherits_target(monkeypatch: pytest.MonkeyPatch
271
272
def test_draft_model_moe_backend_default_auto():
273
"""When neither target nor draft set moe_backend explicitly, both should
278
- default to 'auto'.
279
- """
274
+ default to 'auto'."""
275
engine_args = EngineArgs(
276
model="Qwen/Qwen3-1.7B",
277
tensor_parallel_size=1,
@@ -297,8 +292,7 @@ def test_draft_model_moe_backend_default_auto():
292
293
def test_draft_model_engine_args_rejects_invalid_tp_argname():
294
"""The user should pass "draft_tensor_parallel_size" rather than
300
- "tensor_parallel_size". We enforce this with validation.
301
- """
295
+ "tensor_parallel_size". We enforce this with validation."""
296
engine_args = EngineArgs(
297
model="Qwen/Qwen3-1.7B",
298
tensor_parallel_size=1,
@@ -315,8 +309,7 @@ def test_draft_model_engine_args_rejects_invalid_tp_argname():
309
310
def assert_draft_model_correctness(args: ArgsTest, vllm_runner):
311
"""Compare the outputs using and not using speculative decoding.
318
- In the greedy decoding case, the outputs must match EXACTLY.
319
- """
312
+ In the greedy decoding case, the outputs must match EXACTLY."""
313
test_prompts: list[Messages] = get_messages(
314
dataset=args.dataset, n=args.num_prompts
315
)
tests/v1/e2e/spec_decode/test_sharded_sampling.py
+1
-2
@@ -28,8 +28,7 @@ def test_mtp_sharded_sampling_equivalence(monkeypatch: pytest.MonkeyPatch):
28
sampling under MTP spec decoding: the collectives move the same logits
29
bytes, Gumbel keys derive from (request slot, position, seed), and slot
30
assignment is rank-deterministic. Both runs here are spec decode with
31
- identical math, so outputs must match exactly.
32
- """
31
+ identical math, so outputs must match exactly."""
32
tp_size = 2
33
_skip_if_insufficient_gpus_for_tp(tp_size)
34
model_name = "Qwen/Qwen3.5-0.8B-Base"
tests/v1/e2e/test_hybrid_chunked_prefill.py
+1
-2
@@ -67,8 +67,7 @@ def test_mtp_speculative_mixed_batch_short_prefill(
67
vllm_runner, model_name, enable_prefix_caching
68
):
69
"""Test to ensure MTP speculative decoding correctly handles
70
- short prefill chunks that fall below the reorder_batch_threshold.
71
- """
70
+ short prefill chunks that fall below the reorder_batch_threshold."""
71
# Set so large that both prefills will be classified as decodes in a mixed batch
72
# note, with prefix caching we require chunk_size >= mamba_block_size
73
chunk_size = 256 if not enable_prefix_caching else 2048
tests/v1/ec_connector/unit/cpu/scheduler/test_embedding_cache.py
+1
-2
@@ -381,8 +381,7 @@ def test_pin_if_ready_none_when_absent():
381
382
def test_pin_if_ready_returns_unpinned_entry_when_not_ready():
383
"""The producer needs "present but not ready" told apart from "absent":
384
- the first is NACKed as retryable, the second as a miss.
385
- """
384
+ the first is NACKed as retryable, the second as a miss."""
385
cache = EmbeddingCache(num_blocks=4)
386
cache.alloc("h", 1) # not-ready
387
entry = cache.pin_if_ready("h")
tests/v1/ec_connector/unit/cpu/scheduler/test_scheduler.py
+12
-24
@@ -131,8 +131,7 @@ def test_has_cache_item_false_when_not_consumer(monkeypatch):
131
132
def test_connector_keys_on_identifier_not_mm_hash(monkeypatch):
133
"""The connector must key the encoder cache on feature.identifier (what
134
- has_cache_item is called with), NOT feature.mm_hash.
135
- """
134
+ has_cache_item is called with), NOT feature.mm_hash."""
135
s = _make_scheduler(monkeypatch)
136
req = _Request([_Feature("PROC_KEY", length=1, identifier="ENC_KEY")])
137
s.update_state_after_alloc(req, 0)
@@ -202,8 +201,7 @@ def test_loads_only_serves_hashes_touched_this_step(monkeypatch):
201
202
def test_repeated_reload_same_step_loads_once(monkeypatch):
203
"""The same mm_hash requested twice in one step must appear in
205
- meta.loads exactly once.
206
- """
204
+ meta.loads exactly once."""
205
s = _make_scheduler(monkeypatch)
206
_seed_cached(s, "a", n_blocks=2)
207
@@ -226,8 +224,7 @@ def test_load_not_emitted_for_uncached_entry(monkeypatch):
224
def test_load_pin_protects_blocks_until_completion(monkeypatch):
225
"""Loaded blocks stay pinned until the worker reports the load memcpy
226
complete. Observable: a save that needs eviction cannot reclaim a
229
- still-pinned loaded entry, but can once the completion report arrives.
230
- """
227
+ still-pinned loaded entry, but can once the completion report arrives."""
228
# 2 blocks, both occupied by "a" (ready).
229
s = _make_scheduler(monkeypatch, num_blocks=2)
230
_seed_cached(s, "a", n_blocks=2)
@@ -254,8 +251,7 @@ def test_load_pin_protects_blocks_until_completion(monkeypatch):
251
252
def _can_evict(s: ECCPUScheduler, mm_hash: str, n_blocks: int) -> bool:
253
"""Whether a new save of `mm_hash` can claim `n_blocks`, i.e. whether the
257
- blocks currently held by other entries are reclaimable.
258
- """
254
+ blocks currently held by other entries are reclaimable."""
255
s.update_state_after_alloc(_Request([_Feature(mm_hash, length=n_blocks)]), 0)
256
meta = s.build_connector_meta(scheduler_output=None)
257
return mm_hash in meta.saves
@@ -315,8 +311,7 @@ def test_late_report_does_not_release_a_later_load_of_same_hash(monkeypatch):
311
312
def test_region_full_skips_save_and_never_blocks(monkeypatch):
313
"""When the region is fully occupied by pinned entries, new saves are
318
- silently skipped and ensure_cache_available never blocks.
319
- """
314
+ silently skipped and ensure_cache_available never blocks."""
315
s = _make_scheduler(monkeypatch, num_blocks=1)
316
_seed_cached(s, "pinned", n_blocks=1)
317
s._cache.pin("pinned")
@@ -335,8 +330,7 @@ def test_region_full_skips_save_and_never_blocks(monkeypatch):
330
331
def test_producer_only_never_emits_loads(monkeypatch):
332
"""A producer-only scheduler must never populate meta.loads, even when
338
- entries are ready.
339
- """
333
+ entries are ready."""
334
s = _make_scheduler(monkeypatch, ec_role="ec_producer")
335
req = _Request([_Feature("h1", length=1)])
336
@@ -378,8 +372,7 @@ def test_consumer_only_has_cache_item(monkeypatch):
372
373
def test_save_not_emitted_for_already_cached_entry(monkeypatch):
374
"""An entry already in the cache (from a prior save) must not trigger
381
- a second allocation or appear in meta.saves again.
382
- """
375
+ a second allocation or appear in meta.saves again."""
376
s = _make_scheduler(monkeypatch)
377
req = _Request([_Feature("h1", length=1)])
378
@@ -400,8 +393,7 @@ def test_save_not_emitted_for_already_cached_entry(monkeypatch):
393
394
def test_update_connector_output_ignores_foreign_meta(monkeypatch):
395
"""A worker output whose payload is not an ECCPUWorkerMetadata is a
403
- no-op — no cache mutation, no crash.
404
- """
396
+ no-op — no cache mutation, no crash."""
397
s = _make_scheduler(monkeypatch)
398
_seed_cached(s, "a", n_blocks=1)
399
@@ -415,8 +407,7 @@ def test_update_connector_output_ignores_foreign_meta(monkeypatch):
407
408
def test_update_connector_output_ignores_unknown_report(monkeypatch):
409
"""Reports for a never-seen save hash or a transfer id this scheduler never
418
- dispatched are dropped rather than mutating unrelated state.
419
- """
410
+ dispatched are dropped rather than mutating unrelated state."""
411
s = _make_scheduler(monkeypatch)
412
s.update_connector_output(_WorkerOutput(saves=["gone"], loads=[4242]))
413
assert s.has_cache_item("gone") is False
@@ -428,8 +419,7 @@ def test_update_connector_output_ignores_unknown_report(monkeypatch):
419
420
def test_has_pending_push_work_tracks_inflight_save(monkeypatch):
421
"""A dispatched-but-unconfirmed save keeps push work pending until the
431
- completion report marks it ready.
432
- """
422
+ completion report marks it ready."""
423
s = _make_scheduler(monkeypatch)
424
assert s.has_pending_push_work() is False
425
@@ -444,8 +434,7 @@ def test_has_pending_push_work_tracks_inflight_save(monkeypatch):
434
435
def test_has_pending_push_work_tracks_inflight_load(monkeypatch):
436
"""A dispatched-but-unconfirmed load keeps push work pending until the
447
- unpin completion report arrives.
448
- """
437
+ unpin completion report arrives."""
438
s = _make_scheduler(monkeypatch)
439
_seed_cached(s, "a", n_blocks=1)
440
assert s.has_pending_push_work() is False # ready + unpinned
@@ -464,8 +453,7 @@ def test_has_pending_push_work_tracks_inflight_load(monkeypatch):
453
454
def test_shutdown_disables_roles_and_cleans_region(monkeypatch):
455
"""After shutdown the scheduler serves no items and the region is
467
- cleaned up.
468
- """
456
+ cleaned up."""
457
s = _make_scheduler(monkeypatch, num_blocks=2)
458
_seed_cached(s, "a", n_blocks=2)
459
assert s.has_cache_item("a") is True
tests/v1/ec_connector/unit/cpu/test_ec_shared_region.py
+4
-8
@@ -98,8 +98,7 @@ def test_second_instance_opens_existing_file_and_shares_memory():
98
def test_only_creator_unlinks_file_on_cleanup():
99
"""Critical contract: if the non-creator unlinks, the creator's mmap path
100
becomes a dangling backing file and a third opener would create a new one
101
- out from under the creator.
102
- """
101
+ out from under the creator."""
102
instance_id = str(uuid.uuid4())
103
r1 = ECSharedRegion(
104
engine_id=instance_id,
@@ -216,8 +215,7 @@ def test_madvise_einval_selects_fallback_for_whole_region(monkeypatch):
215
216
def test_non_creator_does_not_probe_or_populate(monkeypatch):
217
"""Only the creator pre-faults. A second opener must not probe the advice
219
- nor re-touch pages the creator already populated.
220
- """
218
+ nor re-touch pages the creator already populated."""
219
from vllm.distributed.ec_transfer.ec_connector.cpu import ec_shared_region as esr
220
221
instance_id = str(uuid.uuid4())
@@ -314,8 +312,7 @@ def test_madvise_unexpected_oserror_propagates(monkeypatch):
312
313
def test_pin_memory_success_sets_flag(region):
314
"""When cudaHostRegister returns 0, _is_pinned flips to True
317
- and cleanup will correspondingly call cudaHostUnregister.
318
- """
315
+ and cleanup will correspondingly call cudaHostUnregister."""
316
fake_cudart = MagicMock()
317
success = MagicMock()
318
success.value = 0
@@ -335,8 +332,7 @@ def test_pin_memory_success_sets_flag(region):
332
333
def test_pin_memory_failure_leaves_flag_false():
334
"""If cudaHostRegister fails (non-zero), don't pretend it succeeded —
338
- cleanup must NOT call cudaHostUnregister on memory we never registered.
339
- """
335
+ cleanup must NOT call cudaHostUnregister on memory we never registered."""
336
r = _make_region()
337
try:
338
fake_cudart = MagicMock()
tests/v1/ec_connector/unit/cpu/worker/test_worker.py
+6
-12
@@ -363,8 +363,7 @@ def test_save_caches_coalesces_only_adjacent_blocks(
363
364
def test_save_caches_noop_when_mm_hash_not_in_saves(make_worker):
365
"""When the scheduler hasn't pre-allocated blocks for ``mm_hash``,
366
- ``save_caches`` + ``flush_saves`` is a pure no-op.
367
- """
366
+ ``save_caches`` + ``flush_saves`` is a pure no-op."""
367
worker = make_worker()
368
sentinel = 0x42
369
worker._region.blocks.fill_(sentinel)
@@ -382,8 +381,7 @@ def test_save_caches_noop_when_mm_hash_not_in_saves(make_worker):
381
)
382
def test_save_caches_noop_for_non_save_rank(make_worker, tp_rank, pcp_rank):
383
"""Only TP rank 0 + PCP rank 0 writes to mmap. All other combinations
385
- must skip the save entirely.
386
- """
384
+ must skip the save entirely."""
385
worker = make_worker(tp_rank=tp_rank, pcp_rank=pcp_rank)
386
sentinel = 0x42
387
worker._region.blocks.fill_(sentinel)
@@ -398,8 +396,7 @@ def test_save_caches_noop_for_non_save_rank(make_worker, tp_rank, pcp_rank):
396
397
def test_save_caches_raises_when_allocated_blocks_too_small(make_worker):
398
"""``save_caches`` must raise ``AssertionError`` when the encoder output
401
- is larger than the allocated block space.
402
- """
399
+ is larger than the allocated block space."""
400
worker = make_worker()
401
src = torch.zeros(3 * _HIDDEN_DIM, dtype=_DTYPE)
402
with pytest.raises(AssertionError, match="exceeds allocated blocks"):
@@ -552,8 +549,7 @@ def test_start_load_caches_noop_when_loads_is_empty(make_worker):
549
def test_start_load_caches_skips_cached_and_loads_new_in_same_step(make_worker):
550
"""Every hash in ``meta.loads`` is copied from mmap, including one whose
551
key is already resident in ``encoder_cache`` — there is no worker-side
555
- skip.
556
- """
552
+ skip."""
553
worker = make_worker()
554
n_blocks = 3
555
src_orig = torch.arange(n_blocks * _HIDDEN_DIM, dtype=_DTYPE).reshape(
@@ -782,8 +778,7 @@ def test_buffer_pool_is_reused_across_save_steps(make_worker):
778
@_requires_accelerator
779
def test_buffer_pool_is_reused_across_load_steps(make_worker):
780
"""Once a load copy completes its descriptor buffers return to the pool and
785
- are reused by the next call — no reallocation.
786
- """
781
+ are reused by the next call — no reallocation."""
782
worker = make_worker()
783
worker._region.blocks[0].fill_(0x01)
784
worker._region.blocks[1].fill_(0x02)
@@ -854,8 +849,7 @@ def test_init_pins_memory_when_available(pin_available, expected_pinned):
849
850
def test_shutdown_calls_region_cleanup_and_swallows_errors(caplog_vllm):
851
"""``shutdown`` must always call ``region.cleanup`` — and must never
857
- raise.
858
- """
852
+ raise."""
853
worker = object.__new__(ECCPUWorker)
854
mock_region = Mock(spec=ECSharedRegion)
855
worker._region = mock_region
tests/v1/ec_connector/unit/test_epd_proxy_round_robin.py
+1
-2
@@ -43,8 +43,7 @@ def assign(proxy):
43
44
def _drive(assign, e_urls, counts):
45
"""Feed a sequence of request item-counts through the cursor, as
46
- fanout_encoder_primer does one request at a time.
47
- """
46
+ fanout_encoder_primer does one request at a time."""
47
cursor = 0
48
all_urls = []
49
for count in counts:
tests/v1/ec_connector/unit/test_metadata.py
+1
-2
@@ -40,8 +40,7 @@ def test_metadata_saves_dict_operations():
40
41
def test_metadata_loads_carry_a_transfer_id_and_blocks():
42
"""Each load entry is a (transfer_id, block_ids) pair, so the worker can
43
- report the transfer rather than the mm_hash.
44
- """
43
+ report the transfer rather than the mm_hash."""
44
meta = ECCPUConnectorMetadata()
45
46
meta.loads["mm_hash_1"] = (0, [5, 6, 7])
tests/v1/ec_connector/unit/test_scheduler_nixl_producer.py
+1
-2
@@ -79,8 +79,7 @@ def test_request_finished_announces_not_ready_entry(monkeypatch):
79
"""A save whose GPU->mmap copy hasn't been confirmed complete yet is
80
still announced: the entry can't be evicted before it's ready, and a read
81
arriving too early is NACKed NACK_NOT_READY for the consumer to retry —
82
- protecting it is not this method's job.
83
- """
82
+ protecting it is not this method's job."""
83
s = _sched_gate_off(monkeypatch)
84
s._nixl_enabled = True
85
s._peer_host, s._peer_port = "1.2.3.4", 5601
tests/v1/ec_connector/unit/test_session.py
+2
-4
@@ -129,8 +129,7 @@ def test_producer_session_grant_nacks_missing_entry():
129
130
def test_producer_session_grant_nacks_not_ready_entry_as_retryable():
131
"""An announced entry whose save is still in flight is distinguished from a
132
- miss, so the consumer retries instead of falling back to local compute.
133
- """
132
+ miss, so the consumer retries instead of falling back to local compute."""
133
cache = EmbeddingCache(num_blocks=8)
134
cache.alloc("h1", 2) # not ready
135
s = _make_producer_session(cache)
@@ -438,8 +437,7 @@ def test_consumer_session_poll_nack_goes_to_tombstoned():
437
438
def test_consumer_session_poll_not_ready_nack_goes_to_retryable():
439
"""A not-ready NACK must not tombstone: tombstoning admits the request with
441
- no embedding, which is fatal once the media has been rewritten away.
442
- """
440
+ no embedding, which is fatal once the media has been rewritten away."""
441
import msgspec
442
443
s = _make_consumer_session()
tests/v1/engine/test_core_engine_actor_manager.py
+1
-2
@@ -68,8 +68,7 @@ class _StubEngineCoreActor(EngineCoreActorMixin):
68
# in ``tests/entrypoints/test_api_server_process_manager.py``.
69
def _bind_and_report_worker(listen_address, sock, args, client_config):
70
"""Bind ROUTER/PULL with a kernel-assigned port, report the actual
71
- endpoints back via ``actual_address_pipe``, then exit.
72
- """
71
+ endpoints back via ``actual_address_pipe``, then exit."""
72
ctx = zmq.Context()
73
try:
74
in_sock = make_zmq_socket(
tests/v1/engine/test_engine_core.py
+4
-8
@@ -607,8 +607,7 @@ def _cadenced_dp_engine_core(
607
monkeypatch, results: list[tuple[bool, bool]], dp_sync_interval: int = 32
608
):
609
"""A bare DPEngineCoreProc whose all-reduce is scripted by `results`;
610
- returns the core and the step numbers at which the all-reduce ran.
611
- """
610
+ returns the core and the step numbers at which the all-reduce ran."""
611
core = object.__new__(DPEngineCoreProc)
612
core.dp_group = object()
613
core.dp_sync_interval = dp_sync_interval
@@ -627,8 +626,7 @@ def _cadenced_dp_engine_core(
626
627
def test_dp_sync_interval_default_is_16():
628
"""Regression pin: lowering the default narrows the mid-wave pause tail
630
- for async RL, where the engine is rarely idle when pause lands.
631
- """
629
+ for async RL, where the engine is rarely idle when pause lands."""
630
assert ParallelConfig.dp_sync_interval == 16
631
632
@@ -646,8 +644,7 @@ def test_dp_sync_interval_normal_wave(monkeypatch, dp_sync_interval: int):
644
def test_dp_sync_interval_idle_pause_consensus_on_first_step(monkeypatch):
645
"""A pause of an idle engine arms every rank before its kick-started
646
first step, so the step-1 sync reaches consensus after one dummy batch
649
- regardless of the configured cadence.
650
- """
647
+ regardless of the configured cadence."""
648
core, synced = _cadenced_dp_engine_core(
649
monkeypatch, [(False, True)], dp_sync_interval=32
650
)
@@ -673,8 +670,7 @@ def _pausable_engine_core_proc() -> EngineCoreProc:
670
@pytest.mark.parametrize("deferred", [False, True])
671
def test_pause_synchronizes_device_before_cache_reset(deferred: bool):
672
"""A resolved pause promises an idle device: the barrier must run before
676
- caches are cleared and before the caller is unblocked.
677
- """
673
+ caches are cleared and before the caller is unblocked."""
674
core = _pausable_engine_core_proc()
675
core.engines_running = deferred
676
order: list[str] = []
tests/v1/engine/test_engine_core_client.py
+3
-6
@@ -249,8 +249,7 @@ def test_dplb_non_late_interaction_still_uses_lb():
249
250
def test_dplb_burst_round_robins_despite_snapshot_rebinds():
251
"""A stats snapshot rebind wipes the optimistic lb_engines increments;
252
- the exact in-flight floor must keep a burst spreading round-robin.
253
- """
252
+ the exact in-flight floor must keep a burst spreading round-robin."""
253
client = _make_dplb_client(num_engines=4)
254
255
for _ in range(4):
@@ -325,8 +324,7 @@ async def test_dplb_scale_down_routes_after_stale_stats_snapshot():
324
325
def test_dplb_snapshot_backpressure_overrides_inflight():
326
"""An engine reported heavily loaded by the coordinator is avoided even
328
- when this client has routed nothing to it.
329
- """
327
+ when this client has routed nothing to it."""
328
client = _make_dplb_client(num_engines=2)
329
client.lb_engines = [[5, 10, 0.0], [0, 0, 0.0]]
330
@@ -339,8 +337,7 @@ def test_dplb_snapshot_backpressure_overrides_inflight():
337
338
def test_dplb_kv_pressure_amplifies_waiting_penalty():
339
"""A waiting queue on a KV-bound engine (slow drain) is penalized, while
342
- the same queue with low KV usage is not (e.g. transient burst).
343
- """
340
+ the same queue with low KV usage is not (e.g. transient burst)."""
341
client = _make_dplb_client(num_engines=2)
342
# Engine 0 has a smaller total but is KV-bound with a queue.
343
client.lb_engines = [[5, 10, 1.0], [0, 20, 0.2]]
tests/v1/engine/test_logprobs_processor.py
+1
-2
@@ -30,8 +30,7 @@ def _make_processor(num_logprobs: int) -> LogprobsProcessor:
30
31
def test_drops_trailing_sentinel_columns():
32
"""A request that asked for 3 custom token logprobs but ended up in a
33
- batch padded to width 5 must not surface the trailing -inf entries.
34
- """
33
+ batch padded to width 5 must not surface the trailing -inf entries."""
34
processor = _make_processor(num_logprobs=3)
35
36
sampled = 42
tests/v1/engine/test_output_processor.py
+1
-2
@@ -229,8 +229,7 @@ def test_request_stream_interval_raises_but_not_below_engine_default(
229
):
230
"""A per-request stream_interval can raise the interval above the engine
231
default but not below it (values under the default clamp up), without
232
- altering the generated text.
233
- """
232
+ altering the generated text."""
233
engine_stream_interval = 5
234
# Request 0 (below the default) clamps up to 5; request 1 raises it to 10.
235
request_stream_intervals = [1, 10]
tests/v1/kv_connector/unit/offloading_connector/test_canonical_mapping.py
+1
-2
@@ -80,8 +80,7 @@ def _split_hnd_cache(spec) -> torch.Tensor:
80
81
def _packed_nhd_cache(spec) -> torch.Tensor:
82
"""Logical (num_blocks, heads, block_size, 2 * head_size) over an NHD
83
- physical layout — the FlashAttention/FlashInfer/Triton/Flex form.
84
- """
83
+ physical layout — the FlashAttention/FlashInfer/Triton/Flex form."""
84
return torch.zeros(
85
NUM_BLOCKS,
86
spec.block_size,
tests/v1/kv_connector/unit/offloading_connector/test_config.py
+2
-4
@@ -863,8 +863,7 @@ def test_parallelism_agnostic_excluded(kv_cache_groups: list[KVCacheGroupSpec]):
863
)
864
def test_canonical_layout_gate(kv_cache_groups, certified):
865
"""The canonical layout certifies portability group by group; none of
866
- these shapes are portable in the direct layout.
867
- """
866
+ these shapes are portable in the direct layout."""
867
assert not _parallelism_agnostic(kv_cache_groups)
868
assert _parallelism_agnostic(kv_cache_groups, canonical=True) is certified
869
@@ -872,8 +871,7 @@ def test_canonical_layout_gate(kv_cache_groups, certified):
871
def test_canonical_layout_certifies_v2_model_runner():
872
"""Canonical bytes are certified per layer against live tensor strides at
873
registration, so the static gate must not depend on the model-runner
875
- version — the v2 runner is the case the canonical layout exists for.
876
- """
874
+ version — the v2 runner is the case the canonical layout exists for."""
875
groups = _groups(_full_attention_spec())
876
assert _parallelism_agnostic(groups, canonical=True, v2=True)
877
tests/v1/kv_connector/unit/offloading_connector/test_metrics.py
+2
-4
@@ -117,8 +117,7 @@ def _spec_cls_with_metric_definitions(
117
metric_definitions: dict[str, Any],
118
) -> type:
119
"""Build a fake offloading spec class reporting the given metric
120
- definitions, so tests don't need to patch the real CPU spec.
121
- """
120
+ definitions, so tests don't need to patch the real CPU spec."""
121
122
class _FakeOffloadingSpec:
123
@staticmethod
@@ -188,8 +187,7 @@ def test_build_kv_connector_stats_with_empty_dict():
187
188
def test_build_kv_connector_stats_reconstructs_offload_stats():
189
"""Test that OffloadingConnector stats are properly reconstructed with
191
- correct data.
192
- """
190
+ correct data."""
191
serialized_data = {
192
_StatsKey.TYPES: {
193
LOAD_BYTES: _MetricType.COUNTER,
tests/v1/kv_connector/unit/offloading_connector/test_scheduler.py
+16
-32
@@ -1583,8 +1583,7 @@ _SCAN_BEHAVIOR = {
1583
@pytest.mark.parametrize("result", list(LookupResult))
1584
def test_scan_behavior_declared_for_every_lookup_result(result: LookupResult):
1585
"""Whether a result keeps a sliding-window streak alive decides how wide
1586
- the demanded chunk set gets, so every member needs deliberate behavior.
1587
- """
1586
+ the demanded chunk set gets, so every member needs deliberate behavior."""
1587
assert result in _SCAN_BEHAVIOR, f"{result} has no declared scan behavior"
1588
expected_lookups, expected_end = _SCAN_BEHAVIOR[result]
1589
@@ -2035,8 +2034,7 @@ def test_request_level_policy_stores_all_blocks(request_runner, async_scheduling
2034
2035
def test_loads_do_not_populate_fence_index(request_runner):
2036
"""Loads don't populate _block_id_to_pending_jobs (protected by
2038
- delay_free_blocks while in flight).
2039
- """
2037
+ delay_free_blocks while in flight)."""
2038
runner = request_runner(
2039
blocks_per_chunk=3,
2040
block_size=4,
@@ -2106,8 +2104,7 @@ def test_fence_at_update_state_after_alloc(request_runner):
2104
def test_fence_at_build_store_jobs(request_runner):
2105
"""A new prefill (no load -> update_state_after_alloc returns early)
2106
reusing a finished request's pending-store block is flushed by
2109
- _build_store_jobs's fence.
2110
- """
2107
+ _build_store_jobs's fence."""
2108
runner = request_runner(
2109
blocks_per_chunk=1,
2110
block_size=4,
@@ -2157,8 +2154,7 @@ def test_fence_at_build_store_jobs(request_runner):
2154
@pytest.mark.parametrize("async_scheduling", [True, False])
2155
def test_complete_store_called_per_job(request_runner, async_scheduling: bool):
2156
"""complete_store fires per-job, not deferred to request finish.
2160
- Each call carries only that store's keys.
2161
- """
2157
+ Each call carries only that store's keys."""
2158
tokens_per_block = 4
2159
blocks_per_chunk = 3
2160
tokens_per_chunk = tokens_per_block * blocks_per_chunk
@@ -2387,8 +2383,7 @@ def test_offload_prompt_only(request_runner, async_scheduling: bool):
2383
@pytest.mark.parametrize("async_scheduling", [True, False])
2384
def test_reset_cache(request_runner, async_scheduling: bool):
2385
"""reset_cache flushes in-flight loads, calls manager.reset_cache(), resets
2390
- next_stored_chunk_idx for active requests and clears job tracking.
2391
- """
2386
+ next_stored_chunk_idx for active requests and clears job tracking."""
2387
block_size = 4
2388
blocks_per_chunk = 3
2389
tokens_per_chunk = block_size * blocks_per_chunk
@@ -2934,8 +2929,7 @@ def test_stale_sliding_window_block_after_prepare_store_failure(
2929
@pytest.mark.parametrize("async_scheduling", [True, False])
2930
def test_skip_reading_prefix_cache(request_runner, async_scheduling: bool):
2931
"""When skip_reading_prefix_cache=True, the offloading connector must not
2937
- load any blocks from CPU even if a matching prefix is cached there.
2938
- """
2932
+ load any blocks from CPU even if a matching prefix is cached there."""
2933
block_size = 4
2934
blocks_per_chunk = 3
2935
tokens_per_chunk = block_size * blocks_per_chunk
@@ -3029,8 +3023,7 @@ def test_max_load_tokens_limits_external_load(request_runner, async_scheduling:
3023
3024
class TestEagle:
3025
"""Tests for Eagle/MTP speculative decoding support in the offloading
3032
- connector scheduler — both _lookup() unit tests and integration tests.
3033
- """
3026
+ connector scheduler — both _lookup() unit tests and integration tests."""
3027
3028
# -------------------------------------------------------------------
3029
# Helpers
@@ -3572,8 +3565,7 @@ class TestEagle:
3565
self, request_runner, async_scheduling: bool
3566
):
3567
"""Eagle sliding-window group stores all prompt blocks but excludes
3575
- the trailing chunk while decoding.
3576
- """
3568
+ the trailing chunk while decoding."""
3569
block_size = 4
3570
sliding_window = 8
3571
num_gpu_blocks = 100
@@ -3625,8 +3617,7 @@ class TestEagle:
3617
self, request_runner, async_scheduling: bool
3618
):
3619
"""An eagle group with a single-block prompt stores it at the end of
3628
- prefill: prompt blocks are stable, so no tail is held back.
3629
- """
3620
+ prefill: prompt blocks are stable, so no tail is held back."""
3621
block_size = 4
3622
blocks_per_chunk = 1
3623
tokens_per_chunk = block_size * blocks_per_chunk
@@ -4263,8 +4254,7 @@ def test_request_finished_mixed_full_attn_and_sliding_window(
4254
4255
def test_chunked_local_attention_reports_its_chunk_window():
4256
"""Llama 4 uses chunked local attention, which used to trip the
4266
- FullAttentionSpec assert and kill the engine at startup.
4267
- """
4257
+ FullAttentionSpec assert and kill the engine at startup."""
4258
spec = ChunkedLocalAttentionSpec(
4259
block_size=16,
4260
num_kv_heads=2,
@@ -4503,8 +4493,7 @@ def test_retention_interval_zero_stores_only_replay_boundary(
4493
def _shared_kv_mtp_config():
4494
"""Speculative config for a shared-group MTP model: eagle-family method
4495
whose drafter layer merges into a target KV-cache group, so no group
4506
- self-identifies as a drafter group (issue #52735).
4507
- """
4496
+ self-identifies as a drafter group (issue #52735)."""
4497
spec = MagicMock(name="shared_kv_mtp_spec")
4498
spec.use_eagle.return_value = True
4499
spec.use_eagle_block_drop.return_value = True
@@ -4518,14 +4507,12 @@ def _shared_kv_mtp_config():
4507
class TestSharedGroupMTPOffload:
4508
"""Regression tests for issue #52735: OffloadingConnector must keep
4509
serving when speculative decoding is enabled but no KV-cache group is
4521
- annotated as a drafter group (shared-group MTP models).
4522
- """
4510
+ annotated as a drafter group (shared-group MTP models)."""
4511
4512
def test_no_annotation_marks_no_groups(self, request_runner):
4513
"""Spec decode on + zero annotated groups must NOT mark every group
4514
as a drafter group; the full store->load roundtrip must match the
4527
- non-speculative behavior of test_two_groups_full_and_sliding_window.
4528
- """
4515
+ non-speculative behavior of test_two_groups_full_and_sliding_window."""
4516
block_size = 4
4517
kv_cache_groups = [
4518
KVCacheGroupSpec(
@@ -4582,8 +4569,7 @@ class TestSharedGroupMTPOffload:
4569
class TestMambaHybridOffloadServing:
4570
"""Store->finish->lookup flows on a full-attention + mamba-align hybrid,
4571
with a manager that only HITs keys that were actually stored. Guards the
4585
- two collapse routes of issue #52735.
4586
- """
4572
+ two collapse routes of issue #52735."""
4573
4574
BLOCK = 4
4575
MAMBA_BLOCK = 16
@@ -4712,8 +4698,7 @@ class TestMambaHybridOffloadServing:
4698
"""Route 1 of #52735: with spec decode on and no drafter annotation,
4699
serving must equal the non-speculative baseline (was 0 before the
4700
fix: the all-groups fallback marked the mamba group as a drafter and
4715
- the volatile-tail pop consumed its only servable chunk).
4716
- """
4701
+ the volatile-tail pop consumed its only servable chunk)."""
4702
baseline = self._roundtrip_served_tokens(self._make_scheduler(None))
4703
assert baseline == 16
4704
served = self._roundtrip_served_tokens(
@@ -4726,8 +4711,7 @@ class TestMambaHybridOffloadServing:
4711
group must not drag the confirmed boundary below a coarser sibling's
4712
chunk granularity. The widened query makes the volatile-tail pop
4713
land on an extra queried chunk, holding the boundary at 16 tokens
4729
- (was 0 before the fix: 4 hits -> pop -> 12 tokens < mamba chunk).
4730
- """
4714
+ (was 0 before the fix: 4 hits -> pop -> 12 tokens < mamba chunk)."""
4715
scheduler = self._make_scheduler(None, mamba_eagle=True)
4716
assert [c.is_eagle_group for c in scheduler.config.kv_group_configs] == [
4717
True,
tests/v1/kv_connector/unit/offloading_connector/test_worker.py
+1
-2
@@ -80,8 +80,7 @@ def _allocate_kv_caches(
80
81
def _single_rank_vllm_config(total_kv_heads: int):
82
"""A one-rank (TP=1) parallel config, as canonical mappings are derived
83
- from it.
84
- """
83
+ from it."""
84
vllm_config = MagicMock()
85
parallel_config = vllm_config.parallel_config
86
parallel_config.tensor_parallel_size = 1
tests/v1/kv_connector/unit/test_bidirectional_kv_transfer.py
+19
-38
@@ -148,8 +148,7 @@ def test_multiturn_lifecycle():
148
(do_remote_decode=True). Finishes LENGTH_CAPPED with remote_block_ids.
149
Turn 2: P receives remote_block_ids from D. P pulls KV from D because
150
remote_block_ids is not None and external tokens > 0. Computes only
151
- new tokens, finishes LENGTH_CAPPED.
152
- """
151
+ new tokens, finishes LENGTH_CAPPED."""
152
vllm_config = create_vllm_config(
153
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
154
)
@@ -195,8 +194,7 @@ def test_multiturn_lifecycle():
194
195
def test_first_turn_no_remote_blocks():
196
"""First turn: P has no remote_block_ids from D yet.
198
- Standard local prefill, returns kv_transfer_params for future turns.
199
- """
197
+ Standard local prefill, returns kv_transfer_params for future turns."""
198
vllm_config = create_vllm_config(
199
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
200
)
@@ -276,8 +274,7 @@ def test_abort_p_side_non_length_capped():
274
275
def test_remote_blocks_exceed_prompt_tokens():
276
"""D provides more remote tokens than P's prompt needs.
279
- P caps external tokens to prompt length.
280
- """
277
+ P caps external tokens to prompt length."""
278
vllm_config = create_vllm_config(
279
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
280
)
@@ -313,8 +310,7 @@ def test_remote_blocks_exceed_prompt_tokens():
310
def test_p_node_pulls_partial_last_block_from_d():
311
"""D sends remote_block_ids with partially filled last block.
312
remote_num_tokens < len(remote_block_ids) * block_size.
316
- P pulls only remote_num_tokens worth of external tokens.
317
- """
313
+ P pulls only remote_num_tokens worth of external tokens."""
314
vllm_config = create_vllm_config(
315
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
316
)
@@ -359,8 +355,7 @@ def test_p_node_pulls_partial_last_block_from_d():
355
356
def test_add_new_req_to_recv_populates_remote_meta():
357
"""add_new_req_to_recv correctly populates RemoteMeta for P-node
362
- bi-directional KV pull from D.
363
- """
358
+ bi-directional KV pull from D."""
359
meta = NixlConnectorMetadata()
360
kv_params = {
361
"remote_block_ids": [[0, 1, 2]],
@@ -388,8 +383,7 @@ def test_add_new_req_to_recv_populates_remote_meta():
383
384
def test_build_connector_meta_recv_entries():
385
"""P-node scheduler: do_remote_decode=True + remote_block_ids →
391
- _reqs_need_recv populated, build_connector_meta produces reqs_to_recv.
392
- """
386
+ _reqs_need_recv populated, build_connector_meta produces reqs_to_recv."""
387
vllm_config = create_vllm_config(
388
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
389
)
@@ -463,8 +457,7 @@ def test_p_node_pull_kv_from_d(dist_init):
457
)
458
def test_p_node_pull_then_send_kv(dist_init):
459
"""Full P-node bi-directional: pull KV from D → prefill →
466
- send KV back to D via notification.
467
- """
460
+ send KV back to D via notification."""
461
connector, worker = _make_connector_with_fake_worker()
462
meta = _make_p_node_recv_metadata("req-p2", [10, 11], [20, 21])
463
_do_load_kv(connector, meta)
@@ -511,8 +504,7 @@ def test_p_node_deferred_pull_on_no_handshake(dist_init):
504
def test_d_node_request_finished_returns_kv_params():
505
"""D-node request_finished returns kv_transfer_params with
506
do_remote_decode=True, remote_block_ids, remote_num_tokens
514
- for P to pull. These params go directly to P node.
515
- """
507
+ for P to pull. These params go directly to P node."""
508
vllm_config = create_vllm_config(
509
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
510
)
@@ -593,8 +585,7 @@ def test_d_node_request_finished_remote_num_tokens():
585
586
def test_d_node_partial_last_block_remote_num_tokens():
587
"""D-node: remote_num_tokens < len(remote_block_ids) * block_size
596
- when last block is partially filled.
597
- """
588
+ when last block is partially filled."""
589
vllm_config = create_vllm_config(
590
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
591
)
@@ -628,8 +619,7 @@ def test_no_double_read_blocks_after_reschedule():
619
bidirectional request (once on initial schedule, once after
620
WAITING_FOR_REMOTE_KVS → reschedule). The _remote_blocks_processed
621
flag must prevent the request from being added to _reqs_need_recv
631
- twice, which would cause P to read D's blocks twice.
632
- """
622
+ twice, which would cause P to read D's blocks twice."""
623
vllm_config = create_vllm_config(
624
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
625
)
@@ -682,8 +672,7 @@ def test_remote_num_tokens_bounded_by_blocks():
672
"""Edge case 2: D-node request_finished must return
673
remote_num_tokens <= len(remote_block_ids) * block_size.
674
request.num_tokens includes the last sampled token which has no KV
685
- in the cache, so remote_num_tokens must use num_computed_tokens.
686
- """
675
+ in the cache, so remote_num_tokens must use num_computed_tokens."""
676
vllm_config = create_vllm_config(
677
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
678
)
@@ -719,8 +708,7 @@ def test_remote_num_tokens_bounded_by_blocks():
708
def test_kv_recompute_threshold_skips_small_transfer():
709
"""Edge case 3: When remote tokens are below kv_recompute_threshold,
710
P should skip the remote pull and compute locally instead of
722
- entering WAITING_FOR_REMOTE_KVS.
723
- """
711
+ entering WAITING_FOR_REMOTE_KVS."""
712
threshold = 256
713
vllm_config = create_vllm_config(
714
kv_connector_extra_config={
@@ -762,8 +750,7 @@ def test_p_node_finished_holds_blocks_for_d():
750
"""Edge case 4: P-node finishes with FINISHED_LENGTH_CAPPED and
751
do_remote_decode=True. P must hold blocks (delay_free=True) and
752
return kv_transfer_params with do_remote_prefill=True so D can
765
- read P's blocks.
766
- """
753
+ read P's blocks."""
754
vllm_config = create_vllm_config(
755
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
756
)
@@ -804,8 +791,7 @@ def test_p_node_finished_holds_blocks_for_d():
791
def test_cache_miss_first_turn_no_remote_pull():
792
"""Edge case 5: First turn with do_remote_decode=True but no
793
remote_block_ids (cache MISS). P should prefill locally with
807
- num_external_tokens=0 and not enter WAITING_FOR_REMOTE_KVS.
808
- """
794
+ num_external_tokens=0 and not enter WAITING_FOR_REMOTE_KVS."""
795
vllm_config = create_vllm_config(
796
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
797
)
@@ -840,8 +826,7 @@ def test_cache_miss_first_turn_no_remote_pull():
826
def test_partial_remote_tokens_less_than_prompt():
827
"""Edge case 6: D's remote_num_tokens covers only part of P's
828
prompt. P should pull remote_num_tokens worth of external tokens
843
- and compute the rest locally.
844
- """
829
+ and compute the rest locally."""
830
vllm_config = create_vllm_config(
831
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
832
)
@@ -886,8 +871,7 @@ def test_partial_remote_tokens_less_than_prompt():
871
def test_remote_blocks_processed_flag_persists():
872
"""Edge case 7: After recv completes and request is rescheduled,
873
the _remote_blocks_processed flag in kv_transfer_params prevents
889
- the bidirectional path from re-entering _reqs_need_recv.
890
- """
874
+ the bidirectional path from re-entering _reqs_need_recv."""
875
vllm_config = create_vllm_config(
876
kv_connector_extra_config=BIDIR_KV_EXTRA_CONFIG,
877
)
@@ -959,8 +943,7 @@ _REMOTE = FakeNixlConnectorWorker.REMOTE_ENGINE_ID
943
)
944
def test_turn2_deadline_gate(dist_init, offset, expiry_delta, expect_declined):
945
"""P declines on the turn-2 readback if the deadline is known,
962
- near-expiry and a handshake clock offset is known
963
- """
946
+ near-expiry and a handshake clock offset is known"""
947
connector, worker = _make_connector_with_fake_worker()
948
worker._engine_clock_offset[_REMOTE] = offset
949
expiry_time = None if expiry_delta is None else time.perf_counter() + expiry_delta
@@ -996,8 +979,7 @@ def test_turn2_deadline_gate(dist_init, offset, expiry_delta, expect_declined):
979
)
980
def test_turn2_full_prefix_hit_with_expired_deadline_skips_gate(dist_init):
981
"""A full local prefix hit issues no READ. The expiry gate must be skipped
999
- even when D's deadline is expired.
1000
- """
982
+ even when D's deadline is expired."""
983
connector, worker = _make_connector_with_fake_worker()
984
worker._engine_clock_offset[_REMOTE] = 0.0
985
@@ -1050,8 +1032,7 @@ def test_d_node_request_finished_exports_blocks_expiry_time():
1032
1033
def test_handshake_listener_appends_perf_counter_frame():
1034
"""The handshake reply carries a 2nd frame with the listener's live
1053
- perf_counter.
1054
- """
1035
+ perf_counter."""
1036
import threading
1037
1038
import msgspec
tests/v1/kv_connector/unit/test_config.py
+6
-12
@@ -19,15 +19,13 @@ class _StubLMCacheMPConnector:
19
test only asserts on the connector *name* and the ``extra_config`` dict
20
produced by ``VllmConfig``, never instantiates the connector, so a bare
21
placeholder class is sufficient. Not subclassing ``SupportsHMA`` mirrors
22
- the real connector's HMA support (it does not support HMA either).
23
- """
22
+ the real connector's HMA support (it does not support HMA either)."""
23
24
25
@pytest.fixture
26
def stub_lmcache_mp_connector(monkeypatch):
27
"""Replace the lazy loader so VllmConfig.__post_init__ does not import
29
- ``lmcache_mp_connector`` (and thus ``lmcache``) during config tests.
30
- """
28
+ ``lmcache_mp_connector`` (and thus ``lmcache``) during config tests."""
29
monkeypatch.setitem(
30
KVConnectorFactory._registry,
31
"LMCacheMPConnector",
@@ -107,8 +105,7 @@ def _build_config(
105
enable_cumem_allocator: bool = False,
106
) -> VllmConfig:
107
"""Build a VllmConfig that exercises _verify_kv_transfer_compat without
110
- requiring a real model (avoids HF downloads in CI).
111
- """
108
+ requiring a real model (avoids HF downloads in CI)."""
109
from types import SimpleNamespace
110
111
kv_transfer_config = (
@@ -134,8 +131,7 @@ def test_kv_connector_rejects_expandable_segments(monkeypatch, kv_connector):
131
invalidated when expandable_segments lets the CUDA VMM allocator remap
132
the underlying physical pages. We can't enumerate every connector that
133
does this (especially OOT ones), so reject the combination whenever any
137
- connector is configured.
138
- """
134
+ connector is configured."""
135
monkeypatch.setenv("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True")
136
with pytest.raises(ValueError, match="expandable_segments"):
137
_build_config(kv_connector=kv_connector)
@@ -143,8 +139,7 @@ def test_kv_connector_rejects_expandable_segments(monkeypatch, kv_connector):
139
140
def test_kv_connector_allows_expandable_segments_with_sleep_mode(monkeypatch):
141
"""Sleep mode routes KV allocations through CuMemAllocator's pool, which
146
- auto-disables expandable_segments (see #40812).
147
- """
142
+ auto-disables expandable_segments (see #40812)."""
143
monkeypatch.setenv("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True")
144
_build_config(kv_connector="NixlConnector", enable_sleep_mode=True)
145
@@ -167,8 +162,7 @@ def test_kv_connector_allows_other_alloc_conf(monkeypatch):
162
163
def test_no_kv_connector_ignores_expandable_segments(monkeypatch):
164
"""The expandable_segments check only applies when a KV connector is
170
- configured.
171
- """
165
+ configured."""
166
monkeypatch.setenv("PYTORCH_CUDA_ALLOC_CONF", "expandable_segments:True")
167
_build_config(kv_connector=None)
168
tests/v1/kv_connector/unit/test_flexkv_connector.py
+3
-6
@@ -50,8 +50,7 @@ def _make_flexkv_module(
50
impl_mock: MagicMock,
51
) -> tuple[types.ModuleType, types.ModuleType]:
52
"""Build a fake ``flexkv`` package hierarchy that returns *impl_mock*
53
- when ``FlexKVConnectorV1Impl`` is instantiated.
54
- """
53
+ when ``FlexKVConnectorV1Impl`` is instantiated."""
54
flexkv_mod = types.ModuleType("flexkv")
55
integration_mod = types.ModuleType("flexkv.integration")
56
vllm_mod = types.ModuleType("flexkv.integration.vllm")
@@ -72,8 +71,7 @@ def _make_flexkv_module(
71
72
def _install_flexkv_mock(impl_mock: MagicMock):
73
"""Insert fake flexkv modules into sys.modules and return a context that
75
- cleans them up afterwards.
76
- """
74
+ cleans them up afterwards."""
75
flexkv_mod, adapter_mod = _make_flexkv_module(impl_mock)
76
mods = {
77
"flexkv": flexkv_mod,
@@ -106,8 +104,7 @@ def _build_connector(vllm_config: VllmConfig, impl_mock: MagicMock):
104
105
class TestFlexKVConnectorImportError:
106
"""FlexKVConnectorV1 should fail with a helpful message when flexkv is
109
- absent.
110
- """
107
+ absent."""
108
109
def test_import_error_message(self):
110
from vllm.distributed.kv_transfer.kv_connector.v1.flexkv_connector import (
tests/v1/kv_connector/unit/test_handshake_pp_aggregation.py
+3
-6
@@ -176,8 +176,7 @@ def test_engine_unwraps_handshake_metadata_for_legacy_connector(
176
) -> None:
177
"""Engine core always asks workers for `(pp_rank, tp_rank)`-keyed metadata,
178
then unwraps to `{tp_rank: metadata}` for a connector that has not opted
179
- into PP-aware handshake (single-PP producer, all `pp_rank == 0`).
180
- """
179
+ into PP-aware handshake (single-PP producer, all `pp_rank == 0`)."""
180
metadata_0 = _Metadata()
181
metadata_1 = _Metadata()
182
connector = _LegacyConnector()
@@ -200,8 +199,7 @@ def test_engine_rejects_pp_producer_for_legacy_connector(
199
monkeypatch: pytest.MonkeyPatch,
200
) -> None:
201
"""A connector that has not opted into PP-aware handshake must not silently
203
- drop metadata from `pp_rank > 0`; engine core init raises instead.
204
- """
202
+ drop metadata from `pp_rank > 0`; engine core init raises instead."""
203
connector = _LegacyConnector()
204
205
with pytest.raises(ValueError, match="does not support PP-disaggregated"):
@@ -216,8 +214,7 @@ def test_engine_passes_handshake_metadata_through_for_pp_aware_connector(
214
monkeypatch: pytest.MonkeyPatch,
215
) -> None:
216
"""A PP-aware connector receives the full `(pp_rank, tp_rank)`-keyed dict
219
- unchanged.
220
- """
217
+ unchanged."""
218
metadata_0 = _Metadata()
219
metadata_1 = _Metadata()
220
connector = _PPAwareConnector()
tests/v1/kv_connector/unit/test_hf3fs_client.py
+2
-4
@@ -131,8 +131,7 @@ class TestHf3fsClientResourceManagement:
131
132
def test_close_idempotent_and_handles_cleared(self, tmp_path):
133
"""Multiple close() calls must not raise; deregister_fd called exactly
134
- once, all handles set to None, shm.close() invoked.
135
- """
134
+ once, all handles set to None, shm.close() invoked."""
135
client, shm_r, shm_w = self._make_client(tmp_path)
136
137
with (
@@ -238,8 +237,7 @@ class TestHf3fsClientResourceManagement:
237
238
def test_constructor_failure_does_not_close_unallocated_shm(self, tmp_path):
239
"""Failure before SharedMemory is created must not raise AttributeError
241
- or TypeError from cleanup.
242
- """
240
+ or TypeError from cleanup."""
241
with (
242
patch(f"{self._MOD}.HF3FS_AVAILABLE", True),
243
patch(f"{self._MOD}.register_fd"),
tests/v1/kv_connector/unit/test_lmcache_connector.py
+1
-2
@@ -212,8 +212,7 @@ class TestUpdateConnectorOutput:
212
self, mock_connector
213
):
214
"""Test that method returns early when kv_cache_events is not
215
- LMCacheKVEvents.
216
- """
215
+ LMCacheKVEvents."""
216
# Create a mock object that is not LMCacheKVEvents
217
fake_events = MagicMock()
218
connector_output = KVConnectorOutput(kv_cache_events=fake_events)
tests/v1/kv_connector/unit/test_mooncake_stats.py
+1
-2
@@ -199,8 +199,7 @@ def _bare_worker() -> MooncakeConnectorWorker:
199
"""Construct a MooncakeConnectorWorker skipping __init__ (full init requires
200
a live TransferEngine). Only the attributes touched by the methods under
201
test are populated; role flags and async_zmq_ctx keep __del__'s shutdown
202
- path a no-op.
203
- """
202
+ path a no-op."""
203
worker = MooncakeConnectorWorker.__new__(MooncakeConnectorWorker)
204
worker.xfer_stats = MooncakeKVConnectorStats()
205
worker.engine = MagicMock()
tests/v1/kv_connector/unit/test_mooncake_store_connector.py
+3
-6
@@ -77,8 +77,7 @@ def test_store_tp_does_not_override_backend_kv_cache_layout(extra_config):
77
78
def _make_kv_cache_config() -> KVCacheConfig:
79
"""Single-group full-attention KVCacheConfig — enough for the connector
80
- constructor's validate() pass.
81
- """
80
+ constructor's validate() pass."""
81
spec = FullAttentionSpec(block_size=16, num_kv_heads=8, head_size=64, dtype=None)
82
return KVCacheConfig(
83
num_blocks=4,
@@ -693,8 +692,7 @@ def _poll_lookup(client, req_id, num_tokens=128, block_hashes=(), timeout=5.0):
692
693
def _gated_recv(gate: threading.Event, value: int):
694
"""Mock recv side-effect that blocks until ``gate`` is set, so the
696
- executor's lookup can be held pending deterministically.
697
- """
695
+ executor's lookup can be held pending deterministically."""
696
697
def recv():
698
gate.wait()
@@ -705,8 +703,7 @@ def _gated_recv(gate: threading.Event, value: int):
703
704
def test_lookup_key_client_non_block_lookup_async():
705
"""Non-blocking lookup defers to the executor: None first, hit once the
708
- Future resolves.
709
- """
706
+ Future resolves."""
707
vllm_config = _make_vllm_config()
708
709
with patch(
tests/v1/kv_connector/unit/test_mooncake_store_coordinator.py
+18
-36
@@ -33,8 +33,7 @@ def _mamba_align(block_size=32):
33
def _make_coord(groups, hash_block_size, use_eagle=False, retention_interval=None):
34
"""Construct a coordinator using the natural LCM of group block sizes as
35
the scheduler block size — mirrors ``resolve_kv_cache_block_sizes`` for
36
- the test fixtures.
37
- """
36
+ the test fixtures."""
37
block_sizes = [g.kv_cache_spec.block_size for g in groups]
38
scheduler_block_size = lcm(*block_sizes)
39
return MooncakeStoreCoordinator(
@@ -144,8 +143,7 @@ def test_coordinator_single_full_attention_no_hits():
143
144
def test_coordinator_single_swa_tautological_pool_masks_pre_window():
145
"""SWA tautological-pool: hit_length spans full prefix, mask is
147
- tail-window only.
148
- """
146
+ tail-window only."""
147
groups = [KVCacheGroupSpec(["L0"], _swa(block_size=16, sliding_window=32))]
148
coord = _make_coord(groups, hash_block_size=16)
149
hs = _hashes(4) # 4 chunks * 16 tokens
@@ -192,8 +190,7 @@ def test_coordinator_hybrid_hole_in_full_clips_both():
190
191
def test_coordinator_group_block_size_double_hash():
192
"""Group block_size=32 over hash_block_size=16 hashes: adjacent
195
- hashes merge before pool lookup.
196
- """
193
+ hashes merge before pool lookup."""
194
groups = [
195
KVCacheGroupSpec(["L0"], _full(16)),
196
KVCacheGroupSpec(["L1"], _full(32)),
@@ -217,8 +214,7 @@ def test_coordinator_group_block_size_double_hash():
214
def test_coordinator_fine_grained_partial_tail_hit():
215
"""K3 shape: FA + mamba-align, block_size=32 over hash_block_size=16. When
216
both groups have the sub-block boundary hash, the reconciled hit lands on
220
- the hash boundary (48), not the block boundary (32).
221
- """
217
+ the hash boundary (48), not the block boundary (32)."""
218
groups = [
219
KVCacheGroupSpec(["L0"], _full(32)),
220
KVCacheGroupSpec(["L1"], _mamba_align(32)),
@@ -238,8 +234,7 @@ def test_coordinator_fine_grained_partial_tail_hit():
234
235
def test_coordinator_fine_grained_clips_when_one_group_missing_tail():
236
"""If only one group has the sub-block boundary, min-convergence clips the
241
- reconciled hit back to the block boundary (32).
242
- """
237
+ reconciled hit back to the block boundary (32)."""
238
groups = [
239
KVCacheGroupSpec(["L0"], _full(32)),
240
KVCacheGroupSpec(["L1"], _mamba_align(32)),
@@ -280,8 +275,7 @@ def test_store_mask_swa_only_window_around_each_lcm_boundary():
275
"""Hybrid full-attn(block=32) + SWA(block=8, sw=8). lcm=32. With
276
aligned=64 the SWA group should mark exactly the blocks ending at 32
277
and 64 (i.e. blocks 3 and 7 at block_size=8); the rest can never
283
- participate in any future hit.
284
- """
278
+ participate in any future hit."""
279
full = _full(32)
280
swa = _swa(block_size=8, sliding_window=8)
281
groups = [KVCacheGroupSpec(["L0"], full), KVCacheGroupSpec(["L1"], swa)]
@@ -327,8 +321,7 @@ def test_store_mask_swa_does_not_double_scale_under_dcp():
321
322
def test_store_mask_swa_wider_window_covers_more_blocks_per_lcm():
323
"""Same hybrid layout but sliding_window=16 (= 2 SWA blocks). Each lcm
330
- boundary should now span two SWA tail blocks.
331
- """
324
+ boundary should now span two SWA tail blocks."""
325
full = _full(32)
326
swa = _swa(block_size=8, sliding_window=16)
327
groups = [KVCacheGroupSpec(["L0"], full), KVCacheGroupSpec(["L1"], swa)]
@@ -358,8 +351,7 @@ def test_store_mask_dsv4_5_groups_full_mla_plus_4_swa():
351
"""DSV4-shaped: full-MLA(B=256) + 4 SWA groups with B in {64, 64, 4, 8}
352
and varied sliding windows. lcm=256, hash_block_size=4. Two lcm segments
353
(aligned_len=512). Validates that the tile-once strategy produces the
361
- expected per-segment tail-window pattern, repeated.
362
- """
354
+ expected per-segment tail-window pattern, repeated."""
355
full_mla = _full(block_size=256)
356
swa_64_sw128 = _swa(block_size=64, sliding_window=128)
357
swa_64_sw512 = _swa(block_size=64, sliding_window=512)
@@ -393,8 +385,7 @@ def test_store_mask_dsv4_5_groups_full_mla_plus_4_swa():
385
386
def test_store_mask_fast_path_all_block_sizes_equal_lcm():
387
"""When every non-full-attn group already aligns to lcm_block_size, the
396
- fast path returns all-True without invoking find_longest_cache_hit.
397
- """
388
+ fast path returns all-True without invoking find_longest_cache_hit."""
389
full = _full(block_size=64)
390
swa = _swa(block_size=64, sliding_window=128)
391
groups = [KVCacheGroupSpec(["L0"], full), KVCacheGroupSpec(["L1"], swa)]
@@ -407,8 +398,7 @@ def test_store_mask_fast_path_all_block_sizes_equal_lcm():
398
399
def test_store_mask_fast_path_single_attention_group():
400
"""Two groups sharing the same SWA spec collapse to one attention group;
410
- no lcm filter applies, every chunk is True.
411
- """
401
+ no lcm filter applies, every chunk is True."""
402
swa = _swa(block_size=16, sliding_window=32)
403
groups = [KVCacheGroupSpec(["L0"], swa), KVCacheGroupSpec(["L1"], swa)]
404
coord = _make_coord(groups, hash_block_size=16)
@@ -422,8 +412,7 @@ def test_store_mask_fast_path_single_attention_group():
412
413
def _retention_groups():
414
"""Hybrid full-attn(block=32) + SWA(block=8, sw=8); lcm=32. The SWA group
425
- densely keeps one tail block per 32-token boundary.
426
- """
415
+ densely keeps one tail block per 32-token boundary."""
416
full = _full(32)
417
swa = _swa(block_size=8, sliding_window=8)
418
return [KVCacheGroupSpec(["L0"], full), KVCacheGroupSpec(["L1"], swa)]
@@ -431,8 +420,7 @@ def _retention_groups():
420
421
def test_store_mask_dense_default_matches_every_lcm_boundary():
422
"""retention_interval=None (default) keeps the SWA tail at every lcm
434
- boundary: tokens 32/64/96/128 -> chunks 3/7/11/15.
435
- """
423
+ boundary: tokens 32/64/96/128 -> chunks 3/7/11/15."""
424
coord = _make_coord(_retention_groups(), hash_block_size=8)
425
masks = coord.store_mask(128)
426
assert masks[0] is None
@@ -442,8 +430,7 @@ def test_store_mask_dense_default_matches_every_lcm_boundary():
430
def test_store_mask_retention_interval_sparsifies_swa_tails():
431
"""retention_interval=64 keeps an SWA tail once per 64-token segment
432
(chunks 7 and 15) instead of every 32 tokens, dropping the mid-segment
445
- boundaries at 32 and 96.
446
- """
433
+ boundaries at 32 and 96."""
434
coord = _make_coord(_retention_groups(), hash_block_size=8, retention_interval=64)
435
masks = coord.store_mask(128)
436
assert masks[0] is None # full attn unaffected
@@ -452,8 +439,7 @@ def test_store_mask_retention_interval_sparsifies_swa_tails():
439
440
def test_store_mask_retention_interval_zero_keeps_only_replay_boundary():
441
"""retention_interval=0 drops all segment tails; only the latest replay
455
- boundary (capped at num_prompt-1, aligned down to lcm) is retained.
456
- """
442
+ boundary (capped at num_prompt-1, aligned down to lcm) is retained."""
443
coord = _make_coord(_retention_groups(), hash_block_size=8, retention_interval=0)
444
# No replay info -> nothing reachable for the SWA group.
445
assert coord.store_mask(128)[1] == [False] * 16
@@ -464,8 +450,7 @@ def test_store_mask_retention_interval_zero_keeps_only_replay_boundary():
450
451
def test_store_mask_retention_interval_keeps_segment_and_replay_tails():
452
"""Sparse segment tails (interval=64 -> chunks 7,15) plus the replay
467
- boundary tail (num_prompt=100 -> chunk 11) coexist.
468
- """
453
+ boundary tail (num_prompt=100 -> chunk 11) coexist."""
454
coord = _make_coord(_retention_groups(), hash_block_size=8, retention_interval=64)
455
masks = coord.store_mask(128, num_prompt_tokens=100)
456
assert masks[1] == [i in (7, 11, 15) for i in range(16)]
@@ -503,8 +488,7 @@ def test_store_mask_excludes_mamba_groups_lookup_unaffected():
488
nulled/freed; speculative blocks relocate), so the positional normal save
489
must never cover mamba chunks — regardless of retention. Lookups still
490
probe mamba boundaries: their keys come from the pinned snapshot/CoW
506
- hand-off path instead.
507
- """
491
+ hand-off path instead."""
492
groups = [
493
KVCacheGroupSpec(["L0"], _full(16)),
494
KVCacheGroupSpec(["L1"], _mamba_align(16)),
@@ -525,8 +509,7 @@ def test_store_mask_excludes_mamba_groups_lookup_unaffected():
509
510
def test_lookup_with_eagle_pops_last_full_attention_block():
511
"""Sanity: with use_eagle, find_longest_cache_hit drops the last block.
528
- Pairs with the load_mask test below to lock the round-trip contract.
529
- """
512
+ Pairs with the load_mask test below to lock the round-trip contract."""
513
groups = [KVCacheGroupSpec(["L0"], _full(16))]
514
coord = _make_coord(groups, hash_block_size=16, use_eagle=True)
515
hs = _hashes(4)
@@ -567,8 +550,7 @@ def test_load_mask_with_eagle_does_not_double_prune_full_attention():
550
def test_load_mask_with_eagle_hybrid_full_plus_swa():
551
"""Hybrid (FullAttn + SWA) with eagle: load_mask must cover every chunk
552
in [0, token_len) for the FullAttn group; SWA group keeps its
570
- tail-window mask.
571
- """
553
+ tail-window mask."""
554
groups = [
555
KVCacheGroupSpec(["L0"], _full(16)),
556
KVCacheGroupSpec(["L1"], _swa(16, 32)),
tests/v1/kv_connector/unit/test_mooncake_store_hma_e2e.py
+7
-14
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""End-to-end save->lookup test for MooncakeStoreConnector on a hybrid
4
-(SWA + Full) attention config, using a dict-backed mock store.
5
-"""
4
+(SWA + Full) attention config, using a dict-backed mock store."""
5
6
import sys
7
import threading
@@ -283,8 +282,7 @@ def test_e2e_swa_plus_full_save_then_lookup_hits():
282
283
def test_recv_skips_swa_blocks_before_window():
284
"""Producer stored every block for both groups; consumer must only fetch
286
- SWA blocks within the sliding window, not the head.
287
- """
285
+ SWA blocks within the sliding window, not the head."""
286
full = FullAttentionSpec(block_size=16, num_kv_heads=8, head_size=64, dtype=None)
287
# sliding_window=32, block_size=16 → 2 contiguous blocks within window.
288
swa = SlidingWindowSpec(
@@ -352,8 +350,7 @@ def test_recv_skips_swa_blocks_before_window():
350
351
def test_chunked_token_database_hash_block_size_smaller_than_block_size():
352
"""DSv4-style: hash_block_size=4, group block_size=16 — process_tokens
355
- keys each chunk by its ending fine hash, including a partial tail.
356
- """
353
+ keys each chunk by its ending fine hash, including a partial tail."""
354
md = KeyMetadata("m", 0, 0, 0, 0, group_id=3)
355
db = ChunkedTokenDatabase(md, block_size=16, hash_block_size=4)
356
db.set_kv_caches_base_addr([0])
@@ -386,8 +383,7 @@ def test_sub_block_partial_tail_offload_reads_cow_block():
383
"""Sub-block prompt (the 900/128/1536 shape, scaled to 12/4/16): the
384
partial tail is offloaded for both groups under the boundary sub-hash. The
385
full-attention block is read from the request block table; the mamba block
389
- is the core-provided CoW target, not block_ids.
390
- """
386
+ is the core-provided CoW target, not block_ids."""
387
full = FullAttentionSpec(block_size=16, num_kv_heads=8, head_size=64, dtype=None)
388
mamba = MambaSpec(
389
block_size=16,
@@ -466,8 +462,7 @@ def test_sub_block_partial_tail_offload_reads_cow_block():
462
def test_offload_syncs_event_before_put():
463
"""An offload-carrying meta synchronizes its CoW-fence event before the
464
store put reads the blocks, then completes in one pass and drains the
469
- completion counter.
470
- """
465
+ completion counter."""
466
full = FullAttentionSpec(block_size=16, num_kv_heads=8, head_size=64, dtype=None)
467
mamba = MambaSpec(
468
block_size=16,
@@ -538,8 +533,7 @@ def test_sub_block_partial_tail_offload_covers_smaller_group_blocks():
533
offload must persist every FA block up to the boundary — the normal save
534
floors to the lcm, so those blocks are otherwise never written and the
535
consumer's per-group lookup would miss. The mamba boundary block still
541
- reads the core-provided CoW target.
542
- """
536
+ reads the core-provided CoW target."""
537
full = FullAttentionSpec(block_size=4, num_kv_heads=8, head_size=64, dtype=None)
538
mamba = MambaSpec(
539
block_size=16,
@@ -810,8 +804,7 @@ def test_ring_scratch_group_is_never_stored_and_does_not_block_hits():
804
"""A per-request ring group (CircularBufferSpec, capacity as block_size)
805
sits beside the paged group: worker setup tolerates its block size (the
806
DeepSeek-V4.1 compressor ring is 8 rows), saving a request stores paged
813
- blocks only, and lookup hits on the paged group alone.
814
- """
807
+ blocks only, and lookup hits on the paged group alone."""
808
full = FullAttentionSpec(block_size=16, num_kv_heads=8, head_size=64, dtype=None)
809
ring = CircularBufferSpec(
810
block_size=8, num_kv_heads=1, head_size=64, head_size_v=0, dtype=torch.uint8
tests/v1/kv_connector/unit/test_mooncake_store_scheduler.py
+2
-4
@@ -536,8 +536,7 @@ def _make_pending_load_unfinished_request(
536
537
def _make_pending_load_scheduler_output() -> SimpleNamespace:
538
"""scheduler_output for a step where req-0 is parked on a pending load
539
- (not in scheduled_new_reqs or scheduled_cached_reqs).
540
- """
539
+ (not in scheduled_new_reqs or scheduled_cached_reqs)."""
540
return SimpleNamespace(
541
finished_req_ids=set(),
542
preempted_req_ids=set(),
@@ -713,8 +712,7 @@ def test_running_request_not_in_resumed_req_ids_appends_blocks():
712
def test_resumed_request_in_resumed_req_ids_replaces_blocks():
713
"""A request the scheduler marks resumed gets the FULL block table in
714
new_block_ids and must REPLACE the tracker's blocks (not append), even if
716
- a stale tracker from before preemption is still present.
717
- """
715
+ a stale tracker from before preemption is still present."""
716
scheduler = _make_bare_scheduler()
717
_make_resumed_unfinished_request(
718
scheduler,
tests/v1/kv_connector/unit/test_mooncake_store_worker.py
+20
-40
@@ -432,8 +432,7 @@ def _patch_worker_runtime(
432
433
def test_pool_key_to_string_without_prefix_is_unchanged():
434
"""Default (empty) cache_prefix keeps keys byte-identical to the
435
- historical unprefixed format so existing deployments keep their hits.
436
- """
435
+ historical unprefixed format so existing deployments keep their hits."""
436
key = PoolKey(KeyMetadata("test-model", 0, 0, 0, 0), "deadbeef")
437
assert (
438
key.to_string() == "test-model@tp_rank:0@pcp0@dcp0@pp_rank:0@group:0@deadbeef"
@@ -574,8 +573,7 @@ def test_tp_shared_receiving_reads_each_local_store_shard():
573
574
def test_pool_key_cache_prefix_namespaces_and_disambiguates():
575
"""A non-empty cache_prefix is prepended, and two instances with
577
- different prefixes never collide on identical block hashes.
578
- """
576
+ different prefixes never collide on identical block hashes."""
577
md_a = KeyMetadata("test-model", 0, 0, 0, 0, cache_prefix="depA")
578
md_b = KeyMetadata("test-model", 0, 0, 0, 0, cache_prefix="depB")
579
@@ -591,8 +589,7 @@ def test_pool_key_cache_prefix_namespaces_and_disambiguates():
589
590
def test_default_local_buffer_size_matches_pr40900():
591
"""PR-40900 shipped a 4 GiB default for local_buffer_size; the dual-mode
594
- patch preserves it (and the JSON key) so unchanged PR-40900 configs work.
595
- """
592
+ patch preserves it (and the JSON key) so unchanged PR-40900 configs work."""
593
assert worker.DEFAULT_LOCAL_BUFFER_SIZE == 4 * 1024**3
594
595
@@ -1014,8 +1011,7 @@ def test_store_sending_thread_skips_null_sparse_group_blocks():
1011
1012
def test_partial_tail_offload_skips_cap_omitted_mamba_group():
1013
"""A Mamba group omitted by the handoff cap must not fall back to the
1017
- connector's positional block table.
1018
- """
1014
+ connector's positional block table."""
1015
from vllm.v1.kv_cache_interface import (
1016
FullAttentionSpec,
1017
KVCacheGroupSpec,
@@ -1143,8 +1139,7 @@ def test_partial_tail_put_failure_activates_pressure_gate():
1139
def test_normal_save_excludes_mamba_group_and_null_blocks():
1140
"""The positional normal save must never cover mamba chunks (align-mode
1141
block tables are not append-only) and must skip chunks whose block is the
1146
- reserved null block, for any group.
1147
- """
1142
+ reserved null block, for any group."""
1143
from vllm.v1.kv_cache_interface import (
1144
FullAttentionSpec,
1145
KVCacheGroupSpec,
@@ -1205,8 +1200,7 @@ def test_normal_save_excludes_mamba_group_and_null_blocks():
1200
def test_block_aligned_snapshot_offload_uses_provided_block():
1201
"""A block-aligned hand-off (sparse-retention mamba checkpoint) uploads
1202
exactly the core-pinned block under the boundary-end hash key; the
1208
- positional block table entry for that chunk must be ignored.
1209
- """
1203
+ positional block table entry for that chunk must be ignored."""
1204
store = MagicMock()
1205
store.batch_is_exist.side_effect = lambda keys: [0] * len(keys)
1206
store.batch_put_from_multi_buffers.side_effect = lambda keys, *a: [256] * len(keys)
@@ -1234,8 +1228,7 @@ def test_block_aligned_snapshot_offload_uses_provided_block():
1228
def test_mixed_snapshot_and_sub_block_offloads():
1229
"""A retention snapshot and the prompt-end sub-block CoW tail can arrive
1230
in one hand-off; the sub-block path covers FA gap blocks but reads the
1237
- mamba boundary only from the CoW block, never positionally.
1238
- """
1231
+ mamba boundary only from the CoW block, never positionally."""
1232
store = MagicMock()
1233
store.batch_is_exist.side_effect = lambda keys: [0] * len(keys)
1234
store.batch_put_from_multi_buffers.side_effect = lambda keys, *a: [256] * len(keys)
@@ -1275,8 +1268,7 @@ def test_mixed_snapshot_and_sub_block_offloads():
1268
1269
def test_snapshot_offload_skips_null_handoff_block():
1270
"""A hand-off the core could not materialize (null block) carries no
1278
- committed state; persisting it would poison the boundary key.
1279
- """
1271
+ committed state; persisting it would poison the boundary key."""
1272
store = MagicMock()
1273
thread = _make_partial_tail_send_thread(store)
1274
@@ -1604,8 +1596,7 @@ def test_store_sending_thread_passes_replicate_config_when_preferred_segment_set
1596
def test_store_sending_thread_passes_default_replicate_config_when_no_preferred_segment(): # noqa: E501
1597
"""Without a preferred_segment the SendingThread still forwards a
1598
(default-constructed) ReplicateConfig so the C++ side always sees a
1607
- well-defined config object.
1608
- """
1599
+ well-defined config object."""
1600
store = MagicMock()
1601
store.batch_is_exist.side_effect = lambda keys: [0] * len(keys)
1602
store.batch_put_from_multi_buffers.return_value = [256, 256]
@@ -2115,8 +2106,7 @@ def test_recv_thread_stops_after_first_failing_disk_offload_sub_batch():
2106
2107
def test_recv_thread_skips_split_when_budget_holds_all_keys():
2108
"""PR-36 removed the count-based split trigger; with budget for 3 keys,
2118
- all three should be requested in a single call.
2119
- """
2109
+ all three should be requested in a single call."""
2110
store = MagicMock()
2111
store.batch_get_into_multi_buffers.return_value = [256, 256, 256]
2112
thread = _make_store_recving_thread(
@@ -2330,8 +2320,7 @@ def test_requester_worker_init_skips_disk_budget_when_offload_disabled(
2320
monkeypatch,
2321
):
2322
"""enable_offload=False zeroes out the disk budget so we don't generate
2333
- redundant owner GET-RPCs.
2334
- """
2323
+ redundant owner GET-RPCs."""
2324
store = MagicMock()
2325
store.setup.return_value = 0
2326
_install_fake_mooncake(monkeypatch, store)
@@ -3006,8 +2995,7 @@ def test_requester_worker_group_semantics_string_true_enables(
2995
2996
def test_store_sending_thread_clamps_token_len_to_lcm():
2997
"""Partial chunks past the last lcm boundary aren't stored — cache hits
3009
- are always lcm-aligned (mirrors HybridKVCacheCoordinator).
3010
- """
2998
+ are always lcm-aligned (mirrors HybridKVCacheCoordinator)."""
2999
store = MagicMock()
3000
store.batch_is_exist.return_value = [0, 0]
3001
store.batch_put_from_multi_buffers.return_value = [256, 256]
@@ -3032,8 +3020,7 @@ def test_store_sending_thread_clamps_token_len_to_lcm():
3020
3021
def test_store_sending_thread_skips_when_token_len_below_lcm():
3022
"""Requests shorter than lcm_block_size cannot produce any aligned chunk,
3035
- so neither the existence check nor the put should be issued.
3036
- """
3023
+ so neither the existence check nor the put should be issued."""
3024
from vllm.v1.kv_cache_interface import FullAttentionSpec, KVCacheGroupSpec
3025
3026
store = MagicMock()
@@ -3823,8 +3810,7 @@ def test_lookup_full_hit_with_eagle_pops_once_not_twice():
3810
"""Eagle already leaves the last block for the drafter, so a
3811
full-prompt re-derivation must never fire for eagle-governed hits:
3812
firing would anchor the search one block lower and pop a second
3826
- block, regressing the hit by an extra producer boundary.
3827
- """
3813
+ block, regressing the hit by an extra producer boundary."""
3814
worker = _make_bare_worker(block_size=16)
3815
worker.coord = mooncake_store_worker.MooncakeStoreCoordinator(
3816
worker._kv_cache_groups,
@@ -3981,8 +3967,7 @@ def test_lookup_full_hit_swa_degrades_when_no_stored_boundary_is_usable():
3967
the full hit into 48, whose SWA window needs the never-written block 1,
3968
so every load failed and the recompute re-entered the same lookup. The
3969
re-derivation must report that no stored boundary below the request end
3984
- is usable.
3985
- """
3970
+ is usable."""
3971
from vllm.v1.kv_cache_interface import KVCacheGroupSpec, SlidingWindowSpec
3972
3973
worker = _make_bare_worker(block_size=16)
@@ -4004,8 +3989,7 @@ def test_lookup_full_hit_swa_degrades_when_no_stored_boundary_is_usable():
3989
def test_lookup_swa_single_group_returns_full_when_tail_window_present():
3990
"""Single-SWA, sliding_window=32 (= 2 blocks): producer stored only the
3991
tail. Coordinator-driven lookup returns full prefix even though the
4007
- pre-window blocks are absent.
4008
- """
3992
+ pre-window blocks are absent."""
3993
from vllm.v1.kv_cache_interface import KVCacheGroupSpec, SlidingWindowSpec
3994
3995
worker = _make_bare_worker(block_size=16)
@@ -4401,8 +4385,7 @@ def test_config_defaults_to_embedded():
4385
4386
def test_config_pr40900_unchanged(tmp_path):
4387
"""A literal PR-40900 config (no mode, no enable_offload, no preferred_segment)
4404
- parses without raising and resolves to embedded mode.
4405
- """
4388
+ parses without raising and resolves to embedded mode."""
4389
config_path = _write_mooncake_config(
4390
tmp_path,
4391
{
@@ -4510,8 +4493,7 @@ def test_config_zero_local_buffer():
4493
def test_topology_standalone_store_with_disk_offload(tmp_path, monkeypatch):
4494
"""standalone-store + disk: global_segment_size=0, enable_offload=True,
4495
preferred_segment set. Assert setup() positional args, ReplicateConfig
4513
- wiring, and that the disk-offload buffer budget is allocated.
4514
- """
4496
+ wiring, and that the disk-offload buffer budget is allocated."""
4497
store = MagicMock()
4498
store.setup.return_value = 0
4499
fake_replicate_config_cls = _install_fake_mooncake(monkeypatch, store)
@@ -4560,8 +4542,7 @@ def test_topology_standalone_store_with_disk_offload(tmp_path, monkeypatch):
4542
def test_topology_embedded_cpu_only(tmp_path, monkeypatch):
4543
"""Embedded + CPU-only: no mode key (defaults to embedded),
4544
global_segment_size>0, enable_offload absent, no preferred_segment.
4563
- This is the PR-40900 baseline recipe.
4564
- """
4545
+ This is the PR-40900 baseline recipe."""
4546
store = MagicMock()
4547
store.setup.return_value = 0
4548
fake_replicate_config_cls = _install_fake_mooncake(monkeypatch, store)
@@ -4750,8 +4731,7 @@ def test_store_worker_close_swallows_store_errors():
4731
def test_blob_block_hashes_wire_roundtrip():
4732
"""The lookup wire format sends a ``hash_len`` frame plus the raw hashes
4733
concatenated back-to-back; the server rebuilds them through a zero-copy
4753
- ``BlobBlockHashes`` view over the frame buffer.
4754
- """
4734
+ ``BlobBlockHashes`` view over the frame buffer."""
4735
hashes = [BlockHash(bytes([i]) * 16) for i in range(5)]
4736
hash_len = len(hashes[0])
4737
tests/v1/kv_connector/unit/test_moriio_connector.py
+7
-14
@@ -692,8 +692,7 @@ def test_moriio_handshake_returns_metadata(mock_parallel_groups):
692
def test_resolve_host_ip_prefers_extra_config():
693
"""An explicit ``host_ip`` in kv_connector_extra_config overrides get_ip()
694
(so an external router can advertise a routable/internal address); an
695
- absent or empty value falls back to get_ip().
696
- """
695
+ absent or empty value falls back to get_ip()."""
696
assert resolve_host_ip({"host_ip": "10.0.0.7"}) == "10.0.0.7"
697
698
fallback = get_ip()
@@ -747,8 +746,7 @@ def _read_scheduler(
746
747
def test_hma_blocks_per_sw_two_groups():
748
"""A Full + SlidingWindow config runs with HMA and computes block budgets
750
- correctly
751
- """
749
+ correctly"""
750
scheduler = _read_scheduler(_make_hybrid_kv_cache_config())
751
assert scheduler._is_hma_required is True
752
# cdiv(32, 16) + 1 == 3 for the sliding-window group, 0 for full attention.
@@ -766,8 +764,7 @@ def test_hma_blocks_per_sw_two_groups():
764
def test_is_hma_required(swa_enabled, disable_hma, expected_is_hma):
765
"""_is_hma_required tracks both the KV cache groups and the
766
--disable-hybrid-kv-cache-manager flag. When HMA is off,
769
- get_exchange_clipped_blocks must be a no-op.
770
- """
767
+ get_exchange_clipped_blocks must be a no-op."""
768
config = (
769
_make_hybrid_kv_cache_config() if swa_enabled else _make_test_kv_cache_config()
770
)
@@ -780,8 +777,7 @@ def test_is_hma_required(swa_enabled, disable_hma, expected_is_hma):
777
778
def test_non_sliding_window_hybrid_is_rejected():
779
"""A hybrid group that is not sliding-window (e.g. chunked-local
783
- attention) must fail closed rather than be silently mistransferred.
784
- """
780
+ attention) must fail closed rather than be silently mistransferred."""
781
full_spec = FullAttentionSpec(
782
block_size=16, num_kv_heads=4, head_size=64, dtype=torch.float16
783
)
@@ -815,8 +811,7 @@ def test_non_sliding_window_hybrid_is_rejected():
811
812
def test_token_count_basis_uses_full_attention_group():
813
"""Chunked-prefill token counting must use an unclipped full-attention
818
- group (blocks_per_sw == 0), not a clipped sliding-window group.
819
- """
814
+ group (blocks_per_sw == 0), not a clipped sliding-window group."""
815
scheduler = _read_scheduler(_make_hybrid_kv_cache_config())
816
# Group 0 is the full-attention group
817
assert scheduler._full_attn_group_idx == 0
@@ -825,8 +820,7 @@ def test_token_count_basis_uses_full_attention_group():
820
821
def test_get_exchange_clipped_blocks_clips_only_sw_group():
822
"""get_exchange_clipped_blocks keeps the full attn group intact and clips the
828
- sliding-window group to its window tail.
829
- """
823
+ sliding-window group to its window tail."""
824
scheduler = _read_scheduler(_make_hybrid_kv_cache_config())
825
full = [10, 11, 12, 13, 14]
826
sw = [20, 21, 22, 23, 24]
@@ -837,8 +831,7 @@ def test_get_exchange_clipped_blocks_clips_only_sw_group():
831
832
def test_metadata_hma_block_ids_preserved_per_group():
833
"""add_new_req stores per-group (BlockIds) block lists unchanged for both
840
- read and write, so the hybrid group structure is retained.
841
- """
834
+ read and write, so the hybrid group structure is retained."""
835
metadata = MoRIIOConnectorMetadata()
836
837
# Assume:
tests/v1/kv_connector/unit/test_moriio_routing_fairness.py
+2
-4
@@ -110,8 +110,7 @@ def make_meta(*, p_tp: int, p_dp: int, remote_dp_rank: int, host: str = "phost0"
110
def build_decode_workers(cfg: PDConfig) -> list:
111
"""Decode workers that issue reads for one prefill instance. A TP decode
112
instance reads from every tp rank; a DP decode instance from each dp-rank
113
- worker. Reused across requests so per-worker round-robin state advances.
114
- """
113
+ worker. Reused across requests so per-worker round-robin state advances."""
114
if cfg.d_tp > 1:
115
return [
116
make_decode_worker(world_size=cfg.d_tp, tp_rank=r, dp_rank=0)
@@ -126,8 +125,7 @@ def prefill_target_multiset(cfg: PDConfig, rounds: int) -> Counter:
125
"""Drive the REAL _resolve_read_source over a fair input stream; tally which
126
prefill GPU each read targets. The only modelled assumption is the proxy
127
contract -- each owner dp-rank delivered equally (``for owner_dp in
129
- range(p_dp)``); no proxy algorithm is reproduced.
130
- """
128
+ range(p_dp)``); no proxy algorithm is reproduced."""
129
workers = build_decode_workers(cfg)
130
hits: Counter = Counter()
131
for _ in range(rounds):
tests/v1/kv_connector/unit/test_multi_connector.py
+1
-2
@@ -555,8 +555,7 @@ class TestMultiConnectorStats:
555
556
def test_build_kv_connector_stats_reconstructs_nixl_stats(self):
557
"""Test that NixlConnector stats are properly reconstructed with
558
- correct data.
559
- """
558
+ correct data."""
559
serialized_data = {
560
"NixlConnector": {
561
"transfer_duration": [1.5, 2.3],
tests/v1/kv_connector/unit/test_nixl_connector.py
+2
-4
@@ -318,8 +318,7 @@ def test_abort_immediately_remote_prefill_enqueues_empty_recv():
318
"""A remote-prefill request added with abort_immediately=True should
319
be added to the scheduler's waiting queue then immediately aborted, so the
320
NIXL connector's request_finished hook enqueues an empty recv to notify
321
- the prefill instance to free its blocks.
322
- """
321
+ the prefill instance to free its blocks."""
322
from vllm.v1.request import RequestStatus
323
324
scheduler = create_scheduler(create_vllm_config())
@@ -3146,8 +3145,7 @@ def test_split_read_failure_defers_report_until_last_handle(
3145
request — nor invalidate its blocks — while the sibling xfer is still in
3146
flight: a posted READ cannot be aborted and would DMA into blocks the
3147
scheduler could free and reuse. The report happens exactly once, when the
3149
- last handle is terminal.
3150
- """
3148
+ last handle is terminal."""
3149
request_id = "split_read_partial_failure"
3150
err_handle, live_handle = 11, 22
3151
connector, worker, wrapper = _make_split_read_connector(
tests/v1/kv_connector/unit/test_nixl_connector_hma.py
+17
-34
@@ -281,8 +281,7 @@ def test_update_state_after_alloc_tracks_cached_blocks_per_group():
281
"""Hybrid SWA+FA requests can have different prefix-cache-hit counts per
282
KV cache group. Each group's count must be tracked independently rather
283
than collapsed to a single scalar, or DCP read-phase alignment
284
- (local_num_computed_blocks) would misalign one of the groups.
285
- """
284
+ (local_num_computed_blocks) would misalign one of the groups."""
285
from vllm.distributed.kv_transfer.kv_connector.v1.nixl.pull_scheduler import (
286
NixlPullConnectorScheduler,
287
)
@@ -336,8 +335,7 @@ def test_full_local_hit_is_not_awaited_by_the_scheduler():
335
owed to the producer -- so the worker must not report it in
336
finished_recving. Doing so trips `assert RequestStatus.is_finished` in
337
_update_from_kv_xfer_finished, which only tolerates a finished recv for a
339
- request that is parked or already done.
340
- """
338
+ request that is parked or already done."""
339
from vllm.distributed.kv_transfer.kv_connector.v1.nixl.pull_scheduler import (
340
NixlPullConnectorScheduler,
341
)
@@ -442,8 +440,7 @@ def test_apply_dcp_prefix_caching_matches_global_logical_positions(
440
"""_apply_dcp_prefix_caching must operate on logical block IDs (DCP
441
interleaves at logical-block granularity) and always return equal-length
442
local/remote slices, so a later, unconditional _apply_prefix_caching
445
- trim is a guaranteed no-op rather than double-processing the read.
446
- """
443
+ trim is a guaranteed no-op rather than double-processing the read."""
444
from vllm.distributed.kv_transfer.kv_connector.v1.nixl.worker import (
445
NixlConnectorWorker,
446
)
@@ -842,8 +839,7 @@ def test_apply_prefix_caching_ssm_prefix_cache_hit(
839
def test_apply_prefix_caching_ssm_unpairable_slots_rejected():
840
"""Local SSM slots can only exceed the remote ones by the position D
841
recomputes itself. A larger excess means the lists aren't
845
- position-aligned: fail loudly rather than transfer into wrong slots.
846
- """
842
+ position-aligned: fail loudly rather than transfer into wrong slots."""
843
from vllm.distributed.kv_transfer.kv_connector.v1.nixl.worker import (
844
NixlConnectorWorker,
845
)
@@ -1159,8 +1155,7 @@ def test_nixl_region_sort_preserves_pipeline_layer_order():
1155
@pytest.mark.cpu_test
1156
def test_get_block_descs_ids_hybrid_ssm():
1157
"""Test _compute_desc_ids uses per-group strides for hybrid
1162
- FA+SSM when ratio=1 (no kernel block size mismatch).
1163
- """
1158
+ FA+SSM when ratio=1 (no kernel block size mismatch)."""
1159
from vllm.v1.kv_cache_interface import FullAttentionSpec, MambaSpec
1160
1161
worker = _make_mock_worker_for_desc_ids(
@@ -1244,8 +1239,7 @@ def test_get_block_descs_ids_uses_per_region_pool_capacity():
1239
@pytest.mark.cpu_test
1240
def test_get_block_descs_ids_kernel_block_mismatch():
1241
"""Test _compute_desc_ids uses different strides for FA
1247
- (kernel blocks) vs SSM (logical blocks) when ratio > 1.
1248
- """
1242
+ (kernel blocks) vs SSM (logical blocks) when ratio > 1."""
1243
from vllm.v1.kv_cache_interface import FullAttentionSpec, MambaSpec
1244
1245
ratio = 4
@@ -1276,8 +1270,7 @@ def test_get_block_descs_ids_kernel_block_mismatch():
1270
def test_get_block_descs_ids_hetero_block_size_hybrid():
1271
"""With a block-size ratio, FA desc ids are ratio-expanded while SSM
1272
desc ids keep the unexpanded logical stride (state blocks are never
1279
- sub-split).
1280
- """
1273
+ sub-split)."""
1274
from vllm.v1.kv_cache_interface import FullAttentionSpec, MambaSpec
1275
1276
worker = _make_mock_worker_for_desc_ids(
@@ -1316,8 +1309,7 @@ def _bind_worker_method(worker, name):
1309
@pytest.mark.cpu_test
1310
def test_map_block_ids_for_block_size_ratio_hybrid():
1311
"""Attention groups expand to remote granularity and clip to the remote
1319
- coverage; mamba state blocks pass through 1:1.
1320
- """
1312
+ coverage; mamba state blocks pass through 1:1."""
1313
from unittest.mock import MagicMock
1314
1315
from vllm.distributed.kv_transfer.kv_connector.v1.nixl.worker import (
@@ -1348,8 +1340,7 @@ def test_map_block_ids_for_block_size_ratio_hybrid():
1340
@pytest.mark.cpu_test
1341
def test_post_process_zeroes_untransferred_tail():
1342
"""The untransferred sub-blocks of the last local block are zeroed on
1351
- receive; mamba state caches are untouched by the attention permute.
1352
- """
1343
+ receive; mamba state caches are untouched by the attention permute."""
1344
from unittest.mock import MagicMock
1345
1346
from vllm.distributed.kv_transfer.kv_connector.v1.nixl.worker import (
@@ -1392,8 +1383,7 @@ def test_post_process_zeroes_untransferred_tail():
1383
@pytest.mark.cpu_test
1384
def test_nixl_metadata_hybrid_ssm_block_ids():
1385
"""Test NixlConnectorMetadata correctly stores block IDs for FA + SSM
1395
- groups with different block counts (kernel mismatch active).
1396
- """
1386
+ groups with different block counts (kernel mismatch active)."""
1387
from vllm.distributed.kv_transfer.kv_connector.v1.nixl.metadata import (
1388
NixlConnectorMetadata,
1389
)
@@ -1474,8 +1464,7 @@ def _make_fake_kv_cache_manager():
1464
@pytest.mark.cpu_test
1465
def test_zeroing_block_ids_cover_only_loaded_attention_blocks():
1466
"""Only zero-recorded (attention) groups contribute, sliced to the
1477
- externally-loaded token range; Mamba state blocks are never zeroed.
1478
- """
1467
+ externally-loaded token range; Mamba state blocks are never zeroed."""
1468
manager = _make_fake_kv_cache_manager()
1469
1470
# Tokens [0, 16) are locally cached; the load covers tokens [16, 56).
@@ -1503,8 +1492,7 @@ def test_scheduler_filters_connector_loaded_blocks_from_zeroing():
1492
@pytest.mark.cpu_test
1493
def test_failed_load_rezeroes_unwritten_skipped_blocks():
1494
"""A failed async load leaves zeroing-skipped blocks unwritten beyond
1506
- the valid prefix; they must be zeroed before local recompute.
1507
- """
1495
+ the valid prefix; they must be zeroed before local recompute."""
1496
from unittest.mock import MagicMock
1497
1498
from vllm.v1.core.sched.scheduler import Scheduler
@@ -1964,8 +1952,7 @@ def test_logical_to_kernel_block_ids_with_remote_ratio(
1952
def test_exchange_clipped_blocks_ssm_single_state():
1953
"""In single-state cache modes, SSM lists are reduced to the running
1954
state slot: speculative scratch slots, null placeholders and the previous
1967
- step's state carry nothing. Attention groups pass through untouched.
1968
- """
1955
+ step's state carry nothing. Attention groups pass through untouched."""
1956
sched = make_nixl_scheduler(has_mamba=True, is_hma_required=True)
1957
sched.blocks_per_sw = [0, 0]
1958
sched._ssm_spec_blocks = [None, 2]
@@ -1992,8 +1979,7 @@ def test_exchange_clipped_blocks_ssm_single_state():
1979
@pytest.mark.cpu_test
1980
def test_exchange_clipped_blocks_ssm_positional_states():
1981
"""In "all" mode every position holds a state, so only the speculative
1995
- slots go; placeholders stay to keep the list position-indexed.
1996
- """
1982
+ slots go; placeholders stay to keep the list position-indexed."""
1983
sched = make_nixl_scheduler(has_mamba=True, is_hma_required=True)
1984
sched.blocks_per_sw = [0, 0]
1985
sched._ssm_spec_blocks = [None, 2]
@@ -2010,8 +1996,7 @@ def _make_hybrid_mla_kv_cache_config(num_blocks: int = 4):
1996
"""KimiLinear-shaped config: one MLA group and two KDA (GDN-typed
1997
MambaSpec) groups whose layers share the same HMA tensors, with a
1998
mamba-aligned unified page and an MLA kernel block smaller than the
2013
- logical block.
2014
- """
1999
+ logical block."""
2000
from vllm.v1.attention.backends.registry import MambaAttentionBackendEnum
2001
from vllm.v1.kv_cache_interface import (
2002
KVCacheConfig,
@@ -2151,8 +2136,7 @@ def test_register_kv_caches_hybrid_mla_dual_purpose_regions():
2136
"""Hybrid MLA+KDA registration: HMA tensors shared by both layer types
2137
must be flagged as MLA regions even when a KDA layer registers them
2138
first, expose TP-independent kernel-granularity block lens, and build
2154
- FA + mamba descriptors for every region.
2155
- """
2139
+ FA + mamba descriptors for every region."""
2140
from unittest.mock import MagicMock
2141
2142
from vllm.config import set_current_vllm_config
@@ -2253,8 +2237,7 @@ def test_register_kv_caches_hybrid_mla_dual_purpose_regions():
2237
def test_push_write_hybrid_mla_replicates_attention():
2238
"""Hybrid MLA+SSM push with P_TP < D_TP: attention blocks must be
2239
written to every covered D rank (replicated MLA latent) while SSM state
2256
- is written per-rank through the split handles.
2257
- """
2240
+ is written per-rank through the split handles."""
2241
import threading
2242
from collections import defaultdict
2243
from unittest.mock import MagicMock
tests/v1/kv_connector/unit/test_nixl_desc_geometry.py
+10
-20
@@ -24,8 +24,7 @@ from .utils import create_vllm_config
24
25
class _RecordingNixl:
26
"""Minimal NIXL wrapper stand-in that records descriptor lists and
27
- prepared transfers so tests can resolve desc ids to byte ranges.
28
- """
27
+ prepared transfers so tests can resolve desc ids to byte ranges."""
28
29
def __init__(self, *args, **kwargs):
30
self.dlists: dict[int, np.ndarray] = {}
@@ -594,8 +593,7 @@ def _register_remote_agents(worker, metadata, tp_size):
593
594
def _owned_byte_ranges(worker, group_logical_ids):
595
"""Byte ranges owned by a request: for each HMA region tensor, every
597
- logical block id of every group maps to one unified page.
598
- """
596
+ logical block id of every group maps to one unified page."""
597
unified_page = worker._test_unified_page
598
bases = [t.data_ptr() for t in worker._test_tensors]
599
owned = []
@@ -633,8 +631,7 @@ def test_hetero_ppl_multi_read_writes_stay_within_request_blocks():
631
(kernel 4, ppl=3) vs remote (P, TP2) logical blocks of 8 tokens (ppl=2),
632
equal kernel pages, tp_ratio=-2 multi-read with replicated MLA and
633
TP-sharded KDA state. Every local descriptor of the request's reads must
636
- stay within its own blocks.
637
- """
634
+ stay within its own blocks."""
635
from vllm.distributed.kv_transfer.kv_connector.v1.nixl.metadata import (
636
NixlConnectorMetadata,
637
)
@@ -701,8 +698,7 @@ def _resolve(
698
"""Resolve a desc id to (region, kind, token_start) where kind is 'attn'
699
(desc-page sized, sub-block-aligned, in the request's attention blocks)
700
or 'mamba'. token_start is the request-relative token offset, so local
704
- and remote are comparable even when their kernel blocks differ in size.
705
- """
701
+ and remote are comparable even when their kernel blocks differ in size."""
702
addr, length, _ = (int(x) for x in desc_arr[int(idx)])
703
for region, base in enumerate(bases):
704
off = addr - base
@@ -896,8 +892,7 @@ def _run_hetero_case(
892
def test_hetero_ppl_token_alignment_sweep(local_block, remote_block, num_tokens):
893
"""Sweep prompt lengths across block-boundary residues for several
894
hetero-ppl geometries; assert neighbor-safety, token alignment, and
899
- coverage of every transferred kernel block.
900
- """
895
+ coverage of every transferred kernel block."""
896
_run_hetero_case(
897
local_block, kernel=4, remote_block=remote_block, num_tokens=num_tokens
898
)
@@ -916,8 +911,7 @@ def test_hetero_ppl_with_block_size_ratio(num_tokens):
911
2). The transfer is clipped at remote sub-block granularity by the
912
pairing and front-trimmed by _apply_prefix_caching, so the
913
untransferred tail can span both a partial block and whole blocks —
919
- the case each of the two former zeroing paths handled only half of.
920
- """
914
+ the case each of the two former zeroing paths handled only half of."""
915
_run_hetero_case(
916
local_block=24,
917
kernel=8,
@@ -966,8 +960,7 @@ def test_mla_hybrid_large_ppl_geometry(num_tokens):
960
"""KimiLinear-scale MLA-hybrid geometry (TP8 prefill -> TP1 decode):
961
decode (local) logical block 5760 / kernel 64 (ppl=90), prefill
962
(remote) logical block 768 (ppl=12), tp_ratio=-8 multi-read with
969
- replicated MLA and 8-way TP-sharded KDA state.
970
- """
963
+ replicated MLA and 8-way TP-sharded KDA state."""
964
_run_hetero_case(
965
local_block=5760,
966
kernel=64,
@@ -981,8 +974,7 @@ def test_mla_hybrid_large_ppl_geometry(num_tokens):
974
def test_mismatched_mla_kernel_page_rejected_for_mla_hybrid():
975
"""The MLA per-token page is TP-independent, so kernel block lengths
976
differing by anything other than the block-size ratio must fail the
984
- handshake loudly rather than transfer at mismatched geometry.
985
- """
977
+ handshake loudly rather than transfer at mismatched geometry."""
978
worker = _make_mla_hybrid_worker(
979
local_block_size=12, kernel_block_size=4, num_logical_blocks=8
980
)
@@ -1166,8 +1158,7 @@ def test_csa_linear_registration_discovers_shared_regions():
1158
def test_csa_linear_scratch_descs_follow_the_pages_they_overlay():
1159
"""The scratch ring is addressed by the regions it actually registered in,
1160
not by inferring that it must sit on the MLA pages: overlaying the main KV
1169
- pages instead moves its descriptors with it.
1170
- """
1161
+ pages instead moves its descriptors with it."""
1162
worker = _make_csa_linear_ple_worker(scratch_aliases="main_kv")
1163
1164
# Same MLA regions as before, but the ring now lives in the non-MLA ones.
@@ -1301,8 +1292,7 @@ def test_csa_linear_remote_ple_is_copied_whole():
1292
1293
def _make_ring_worker():
1294
"""Paged MLA group plus a per-layer ring group, no Mamba: the shape of a
1304
- model whose sliding-window KV lives in per-request rings.
1305
- """
1295
+ model whose sliding-window KV lives in per-request rings."""
1296
from unittest.mock import MagicMock
1297
1298
from vllm.config import set_current_vllm_config
tests/v1/kv_connector/unit/test_nixl_push_connector.py
+35
-70
@@ -115,8 +115,7 @@ class _BlocksMock:
115
116
def _stub_sw_clipping(scheduler) -> None:
117
"""Make ``get_exchange_clipped_blocks`` a passthrough so tests don't
118
- need the full sliding-window machinery.
119
- """
118
+ need the full sliding-window machinery."""
119
scheduler.get_exchange_clipped_blocks = lambda block_ids, clip_ssm=True: block_ids
120
121
@@ -174,8 +173,7 @@ class TestPushScheduler:
173
174
def test_p_side_request_finished_stages_blocks(self):
175
"""P scheduler pushes blocks into both _finished_request_blocks (lease)
177
- and _newly_finished_push_blocks (metadata for next step).
178
- """
176
+ and _newly_finished_push_blocks (metadata for next step)."""
177
sched = make_nixl_push_scheduler()
178
_stub_sw_clipping(sched)
179
@@ -194,8 +192,7 @@ class TestPushScheduler:
192
193
def test_build_connector_meta_drains_both_sides(self):
194
"""meta.push_registrations and meta.push_finished_blocks are filled
197
- from the staging dicts and the staging dicts are cleared.
198
- """
195
+ from the staging dicts and the staging dicts are cleared."""
196
sched = make_nixl_push_scheduler()
197
_stub_sw_clipping(sched)
198
@@ -290,8 +287,7 @@ class TestPushScheduler:
287
288
def test_registration_watchdog_expires(self, caplog):
289
"""Stale D registrations whose deadline has passed are dropped at
293
- ``build_connector_meta`` time.
294
- """
290
+ ``build_connector_meta`` time."""
291
# Watchdog logs a WARNING when it drops the stale entry; that's
292
# what this test is verifying, so silence it in the test report.
293
caplog.set_level(
@@ -332,8 +328,7 @@ class TestPushScheduler:
328
329
class _StubWriterWorker(NixlPushConnectorWorker):
330
"""Construct a worker without invoking ``__init__`` so we can drive
335
- the matching/notif logic without bringing up NIXL or torch.
336
- """
331
+ the matching/notif logic without bringing up NIXL or torch."""
332
333
@classmethod
334
def fresh(cls) -> _StubWriterWorker:
@@ -439,8 +434,7 @@ class TestPushWriterRegSend:
434
"""``_do_send_reg_notif``: the PUSH_REG goes to every handshaked agent of
435
the P engine, and the agent map is read under ``_handshake_lock`` so the
436
send can't race the handshake done-callback's insert or a concurrent
442
- stale-engine eviction (X1).
443
- """
437
+ stale-engine eviction (X1)."""
438
439
def _reg_send_worker(self) -> tuple[_StubWriterWorker, list]:
440
w = _StubWriterWorker.fresh()
@@ -485,8 +479,7 @@ class TestPushWriterRegSend:
479
def test_agent_read_is_serialized_with_handshake_lock(self):
480
"""While another thread holds ``_handshake_lock`` (as the handshake
481
done-callback does while writing ``_remote_agents``), the writer's
488
- check-then-send must not run ahead of the critical section.
489
- """
482
+ check-then-send must not run ahead of the critical section."""
483
w, failures = self._reg_send_worker()
484
w._remote_agents["prefill-engine"] = {(0, 0): "agent-0"}
485
rd = _registration_data("req-1")
@@ -596,8 +589,7 @@ class TestPushWriterMatching:
589
class TestPushWriterStartLoadKv:
590
def test_finished_blocks_inbox_matches_stashed_registration(self):
591
"""Run the writer-loop's finished-blocks drain against a
599
- pre-populated _pending_d_registrations entry.
600
- """
592
+ pre-populated _pending_d_registrations entry."""
593
w = _StubWriterWorker.fresh()
594
w._pending_d_registrations["req-C"] = _registration_data("req-C")
595
@@ -622,8 +614,7 @@ class TestPushWriterStartLoadKv:
614
615
def test_start_load_kv_enqueues_to_writer(self):
616
"""``start_load_kv`` should hand registrations + finished blocks
625
- to the writer queues without doing matching itself.
626
- """
617
+ to the writer queues without doing matching itself."""
618
w = _StubWriterWorker.fresh()
619
# Stub heartbeats to a no-op; tests don't exercise the heartbeat
620
# path here.
@@ -681,8 +672,7 @@ def test_do_start_push_kv_defers_then_writes_when_handshake_ready():
672
NIXL op from the writer or the executor callback); once it resolves the
673
request is re-queued on ``_deferred_push_inbox`` with the wake set; and on
674
re-drive with the handshake ready the WRITE is issued with a correct
684
- ReqMeta.
685
- """
675
+ ReqMeta."""
676
w = _StubWriterWorker.fresh()
677
w._logical_to_kernel_block_ids = lambda x, ratio: x
678
xfer_calls: list[dict[str, Any]] = []
@@ -722,8 +712,7 @@ def test_do_start_push_kv_defers_then_writes_when_handshake_ready():
712
def test_do_start_push_kv_drops_request_on_handshake_failure():
713
"""Handshake raises: the request is dropped (not re-queued, no WRITE) and
714
the failure is logged. Blocks are reclaimed by the lease/watchdog, matching
725
- the old blocking behaviour.
726
- """
715
+ the old blocking behaviour."""
716
w = _StubWriterWorker.fresh()
717
w._logical_to_kernel_block_ids = lambda x, ratio: x
718
xfer_calls: list[dict[str, Any]] = []
@@ -745,8 +734,7 @@ def test_do_start_push_kv_drops_request_on_handshake_failure():
734
735
def test_writer_loop_drains_deferred_push_inbox():
736
"""The writer loop drains ``_deferred_push_inbox`` and re-drives
748
- ``_do_start_push_kv`` for each entry (event-driven, no polling).
749
- """
737
+ ``_do_start_push_kv`` for each entry (event-driven, no polling)."""
738
w = _StubWriterWorker.fresh()
739
w.nixl_wrapper = MagicMock()
740
w.nixl_wrapper.get_new_notifs.return_value = {}
@@ -779,8 +767,7 @@ def test_writer_loop_drains_deferred_push_inbox():
767
768
def _eviction_worker(engine_ttl: float) -> NixlPushConnectorWorker:
769
"""A push worker wired to drive the base ``_ensure_handshake`` eviction
782
- path (``_evict_stale_engines`` + ``_cleanup_remote_engine``).
783
- """
770
+ path (``_evict_stale_engines`` + ``_cleanup_remote_engine``)."""
771
w = _StubWriterWorker.fresh()
772
w._engine_ttl = engine_ttl
773
w._engine_last_active = {}
@@ -802,8 +789,7 @@ def _eviction_worker(engine_ttl: float) -> NixlPushConnectorWorker:
789
def test_active_push_refreshes_engine_last_active():
790
"""The base ``_ensure_handshake`` refreshes liveness only on a new
791
handshake, so an active push to an already-connected engine must refresh
805
- ``_engine_last_active`` itself or it is reaped mid-stream (S1).
806
- """
792
+ ``_engine_last_active`` itself or it is reaped mid-stream (S1)."""
793
w = _eviction_worker(engine_ttl=3600.0)
794
# Already-connected D -> _ensure_handshake returns None, WRITE runs inline.
795
w._remote_agents["decode-engine"] = {(0, 0): "agent-decode"}
@@ -819,8 +805,7 @@ def test_active_push_refreshes_engine_last_active():
805
def test_stale_engine_evicted_on_push():
806
"""A push drives ``_ensure_handshake`` -> ``_evict_stale_engines``, so a D
807
engine silent past its TTL is reaped -- no _remote_agents / NIXL agent leak
822
- across D scale up/down (S1).
823
- """
808
+ across D scale up/down (S1)."""
809
w = _eviction_worker(engine_ttl=30.0)
810
w._remote_agents["D-old"] = {(0, 0): "agent-D-old"}
811
w._engine_last_active["D-old"] = time.perf_counter() - 10_000.0
@@ -837,8 +822,7 @@ def test_stale_engine_evicted_on_push():
822
def test_cleanup_remote_engine_pops_under_handshake_lock():
823
"""Regression (X1): eviction must not remove ``_remote_agents`` entries
824
while another thread is inside the lock's critical section (e.g. the
840
- push writer reading the map to send a registration).
841
- """
825
+ push writer reading the map to send a registration)."""
826
w = _eviction_worker(engine_ttl=30.0)
827
w._remote_agents["D-old"] = {(0, 0): "agent-D-old"}
828
@@ -863,8 +847,7 @@ def test_cleanup_remote_engine_pops_under_handshake_lock():
847
class TestPushWriterNotifs:
848
def test_get_new_notifs_processes_forwarded_completion_notif(self):
849
"""Non-PUSH_REG notifs forwarded by the writer thread are drained
866
- on the engine main thread inside ``_get_new_notifs``.
867
- """
850
+ on the engine main thread inside ``_get_new_notifs``."""
851
w = _StubWriterWorker.fresh()
852
# Pretend the writer thread already forwarded a completion notif
853
# for a request whose KV is being received.
@@ -910,8 +893,7 @@ class TestPushWriterNotifs:
893
@staticmethod
894
def _pollable_worker() -> _StubWriterWorker:
895
"""Stub worker with the extra base-worker state the real
913
- ``get_transfer_results`` needs to poll ``_sending_transfers``.
914
- """
896
+ ``get_transfer_results`` needs to poll ``_sending_transfers``."""
897
w = _StubWriterWorker.fresh()
898
w.transfer_topo = MagicMock()
899
w.nixl_wrapper = MagicMock()
@@ -953,8 +935,7 @@ class TestPushWriterNotifs:
935
@pytest.mark.parametrize(("pp_size", "is_hma"), [(1, False), (2, True)])
936
def test_completed_push_send_waits_for_consumer_notif(self, pp_size, is_hma):
937
"""P-side sends are completed by consumer notifs / lease expiry,
956
- not by local WRITE-handle completion.
957
- """
938
+ not by local WRITE-handle completion."""
939
w = self._pollable_worker()
940
w.pp_size = pp_size
941
w._is_hma_required = is_hma
@@ -1025,8 +1006,7 @@ class TestPushSchedulerNegative:
1006
1007
def test_request_finished_unfinished_status_does_not_stage(self):
1008
"""If a request is still RUNNING, request_finished must not stash
1028
- blocks for the worker (no push needed).
1029
- """
1009
+ blocks for the worker (no push needed)."""
1010
sched = make_nixl_push_scheduler()
1011
_stub_sw_clipping(sched)
1012
@@ -1043,8 +1023,7 @@ class TestPushSchedulerNegative:
1023
1024
def test_request_finished_empty_blocks_does_not_arm_lease(self):
1025
"""Empty block-id groups should still complete cleanly without
1046
- arming the lease/finished maps.
1047
- """
1026
+ arming the lease/finished maps."""
1027
sched = make_nixl_push_scheduler()
1028
_stub_sw_clipping(sched)
1029
@@ -1059,8 +1038,7 @@ class TestPushSchedulerNegative:
1038
1039
def test_update_connector_output_unknown_request_is_noop(self):
1040
"""Idempotent cleanup: clearing a request that was never staged
1062
- must not raise or mutate other state.
1063
- """
1041
+ must not raise or mutate other state."""
1042
sched = make_nixl_push_scheduler()
1043
_stub_sw_clipping(sched)
1044
@@ -1093,8 +1071,7 @@ class TestPushWriterNegative:
1071
1072
def test_pop_matching_registration_no_match_when_base_ids_differ(self):
1073
"""A registration whose base id (after stripping the random suffix)
1096
- does NOT match the lookup request_id must not be popped.
1097
- """
1074
+ does NOT match the lookup request_id must not be popped."""
1075
w = _StubWriterWorker.fresh()
1076
# Two unrelated requests: different base UUIDs, so stripping the
1077
# trailing ``-<8 hex>`` suffix still yields different base ids.
@@ -1110,8 +1087,7 @@ class TestPushWriterNegative:
1087
1088
def test_handle_push_reg_with_non_dict_payload_is_dropped(self, caplog):
1089
"""msgpack-encoded non-dict payload (e.g. a list) should be
1113
- dropped without raising.
1114
- """
1090
+ dropped without raising."""
1091
caplog.set_level(
1092
logging.CRITICAL,
1093
logger=("vllm.distributed.kv_transfer.kv_connector.v1.nixl.push_worker"),
@@ -1139,8 +1115,7 @@ class TestPushWriterNegative:
1115
1116
def test_handle_push_reg_idempotent_for_same_request_id(self):
1117
"""Receiving the same PUSH_REG twice (e.g. P retries after a
1142
- flake) keeps the entry staged exactly once and never fires.
1143
- """
1118
+ flake) keeps the entry staged exactly once and never fires."""
1119
w = _StubWriterWorker.fresh()
1120
notif = PUSH_REG_NOTIF_PREFIX + msgspec.msgpack.encode(
1121
_registration_data("req-dup")
@@ -1155,8 +1130,7 @@ class TestPushWriterNegative:
1130
"""``get_transfer_results`` must enqueue every completed request
1131
in ``done_sending`` so the writer can drop stale matching state.
1132
Unlike the happy-path test, this verifies the *cardinality*: N
1158
- completed requests -> N evictions, in order.
1159
- """
1133
+ completed requests -> N evictions, in order."""
1134
w = _StubWriterWorker.fresh()
1135
with patch.object(
1136
NixlPushConnectorWorker.__mro__[1],
@@ -1179,8 +1153,7 @@ class TestPushWriterNegative:
1153
def test_empty_transfer_results_do_not_enqueue_eviction(self):
1154
"""If there's nothing newly done, no eviction should be enqueued.
1155
The wake event IS still set because ``get_finished`` always wakes
1182
- the writer to drain notifs.
1183
- """
1156
+ the writer to drain notifs."""
1157
w = _StubWriterWorker.fresh()
1158
with patch.object(
1159
NixlPushConnectorWorker.__mro__[1],
@@ -1221,8 +1194,7 @@ class TestPushWriterNegative:
1194
1195
def test_get_new_notifs_unknown_request_is_logged_and_skipped(self, caplog):
1196
"""A completion notif for a request the worker doesn't know
1224
- about should be logged but not crash.
1225
- """
1197
+ about should be logged but not crash."""
1198
caplog.set_level(
1199
logging.CRITICAL,
1200
logger=("vllm.distributed.kv_transfer.kv_connector.v1.nixl.push_worker"),
@@ -1254,8 +1226,7 @@ class TestPushWriterNegative:
1226
def test_get_new_notifs_extends_lease_on_heartbeat(self):
1227
"""``HB:`` notifs forwarded by the writer thread must extend the
1228
leases of tracked P-side requests on the engine main thread, and
1257
- ignore request IDs that aren't being tracked.
1258
- """
1229
+ ignore request IDs that aren't being tracked."""
1230
w = _StubWriterWorker.fresh()
1231
w.transfer_topo = MagicMock()
1232
# _handle_heartbeat reads ``self._lease_extension`` (set in the
@@ -1291,13 +1262,11 @@ class TestPushWriterNegative:
1262
1263
class TestPushPipelineParallel:
1264
"""PP-sharded producer: per-stage completion counting, pp_size plumbing,
1294
- and remote-region slicing.
1295
- """
1265
+ and remote-region slicing."""
1266
1267
def test_completion_waits_for_one_notif_per_pp_stage(self):
1268
"""Each PP stage WRITEs its own layers and sends one notif; D must
1299
- collect pp_size notifs before reporting the recv done.
1300
- """
1269
+ collect pp_size notifs before reporting the recv done."""
1270
w = _StubWriterWorker.fresh()
1271
w.transfer_topo = MagicMock()
1272
request_id = "req-pp-2"
@@ -1318,8 +1287,7 @@ class TestPushPipelineParallel:
1287
1288
def test_req_meta_reads_pp_size_from_kv_transfer_params(self):
1289
"""D learns the producer's pp_size from kv_transfer_params (forwarded
1321
- by the proxy) and defaults to 1 when absent.
1322
- """
1290
+ by the proxy) and defaults to 1 when absent."""
1291
metadata = NixlConnectorMetadata()
1292
params = {
1293
"remote_block_ids": ([0],),
@@ -1342,8 +1310,7 @@ class TestPushPipelineParallel:
1310
this worker holds only a contiguous layer slice; add_remote_agent
1311
trims the remote region list to [offset : offset + num_local_regions]
1312
before building descriptors. We stop right after the slice via a
1345
- sentinel on the next collaborator call.
1346
- """
1313
+ sentinel on the next collaborator call."""
1314
block_len = 4096 * 16
1315
w = _StubWriterWorker.fresh() # seeds writer-thread state for teardown
1316
w.pp_size = 2
@@ -1385,8 +1352,7 @@ class TestPushWriterMlaReplication:
1352
"""MLA latent KV is replicated across D's TP ranks, so when D_TP > P_TP
1353
(``tp_ratio < 0``) the producer must *WRITE* the latent into every D rank
1354
it handshook -- not write one and merely notify the rest, which would
1388
- leave the un-written ranks decoding against stale KV.
1389
- """
1355
+ leave the un-written ranks decoding against stale KV."""
1356
1357
@staticmethod
1358
def _mla_worker_writing_to(d_ranks):
@@ -1611,8 +1577,7 @@ class TestPushPrefixCaching:
1577
1578
def test_partial_prefix_hit_end_trims_producer_blocks(self):
1579
"""D registered only its 2 uncomputed suffix blocks; P finished the
1614
- full 5-block sequence. P must WRITE its LAST 2 blocks into D's slots.
1615
- """
1580
+ full 5-block sequence. P must WRITE its LAST 2 blocks into D's slots."""
1581
w, _ = self._worker_driving_xfer()
1582
reg = _registration_data("req-pc", local_block_ids=([500, 501],))
1583
tests/v1/kv_connector/unit/test_nixl_rocm_gpu_mem_diag.py
+1
-2
@@ -171,8 +171,7 @@ def test_gpu_memory_nixl_hma(model_name, sw_size):
171
@pytest.mark.parametrize("model_name", ["google/gemma-3-1b-it"])
172
def test_gpu_memory_no_nixl_baseline(model_name):
173
"""Same workload without NixlConnector. Comparing driver-level memory
174
- between this and test_gpu_memory_nixl_hma isolates UCX/NIXL impact.
175
- """
174
+ between this and test_gpu_memory_nixl_hma isolates UCX/NIXL impact."""
175
from vllm import LLM, SamplingParams
176
from vllm.distributed.parallel_state import cleanup_dist_env_and_memory
177
tests/v1/kv_connector/unit/test_nixl_simple_cpu_offload.py
+3
-6
@@ -213,8 +213,7 @@ def _multi_connector_config(swa_enabled: bool = False):
213
def test_nixl_wins_load_over_cpu_offload():
214
"""When NixlConnector (index 0) has matched tokens from a remote prefill, it should
215
win the load: Nixl metadata tracks the recv while CPU offload metadata has no load
216
- scheduled.
217
- """
216
+ scheduled."""
217
vllm_config, kv_cache_config = _multi_connector_config()
218
scheduler = create_scheduler(vllm_config, kv_cache_config=kv_cache_config)
219
mc = scheduler.connector
@@ -251,8 +250,7 @@ def test_nixl_wins_load_over_cpu_offload():
250
@patch(NIXL_WRAPPER_PATCH, FakeNixlWrapper)
251
def test_cpu_offload_wins_when_nixl_has_no_match():
252
"""When NixlConnector returns 0 matched tokens and SimpleCPUOffloadConnector has a
254
- CPU cache hit, the CPU offload connector (index 1) wins the load.
255
- """
253
+ CPU cache hit, the CPU offload connector (index 1) wins the load."""
254
vllm_config, kv_cache_config = _multi_connector_config()
255
scheduler = create_scheduler(vllm_config, kv_cache_config=kv_cache_config)
256
mc = scheduler.connector
@@ -311,8 +309,7 @@ def test_cpu_offload_wins_when_nixl_has_no_match():
309
def test_request_finished_no_async_save(swa_enabled: bool):
310
"""A normal request (no P/D) produces no async save from either connector.
311
MultiConnector returns (False, None) via both request_finished and
314
- request_finished_all_groups, and cleans up _requests_to_connector.
315
- """
312
+ request_finished_all_groups, and cleans up _requests_to_connector."""
313
from vllm.v1.request import RequestStatus
314
315
vllm_config, kv_cache_config = _multi_connector_config(swa_enabled=swa_enabled)
tests/v1/kv_connector/unit/test_offloading_connector.py
+2
-4
@@ -321,8 +321,7 @@ def test_cpu_offloading(
321
@pytest.mark.skipif(not current_platform.is_cuda(), reason="Requires CUDA")
322
def test_cpu_offloading_metrics() -> None:
323
"""Verify that offloading Prometheus metrics (new flat and deprecated
324
- labeled) are emitted after stores and loads.
325
- """
324
+ labeled) are emitted after stores and loads."""
325
extra_config: dict = {
326
"cpu_bytes_to_use": 500 << 20,
327
"block_size": CPU_BLOCK_SIZES,
@@ -511,8 +510,7 @@ def test_tiering_offloading() -> None:
510
511
def test_fs_tiering_offloading(tmp_path) -> None:
512
"""Tests OffloadingConnector with TieringOffloadingSpec
514
- + fs secondary tier.
515
- """
513
+ + fs secondary tier."""
514
extra_config: dict = {
515
"cpu_bytes_to_use": 1 << 30,
516
"block_size": CPU_BLOCK_SIZES,
tests/v1/kv_connector/unit/test_remote_prefill_lifecycle.py
+1
-2
@@ -704,8 +704,7 @@ def test_async_load_reserves_blocks_for_inflight():
704
705
def test_async_loads_both_admitted_when_pool_fits():
706
"""Sanity: with a pool large enough, the reservation gate admits both async
707
- loads (it is not over-conservative).
708
- """
707
+ loads (it is not over-conservative)."""
708
vllm_config = create_vllm_config()
709
BLOCK_SIZE = vllm_config.cache_config.block_size
710
scheduler = create_scheduler(vllm_config, num_blocks=64)
tests/v1/kv_connector/unit/test_simple_cpu_offload_connector.py
+1
-2
@@ -129,8 +129,7 @@ def _make_ring_kv_cache_config(num_blocks: int = 16) -> KVCacheConfig:
129
130
def test_ring_scratch_group_is_accepted_and_never_offloaded() -> None:
131
"""The ring group's capacity is not a token granularity, it holds no
132
- hashed blocks, and it never participates in CPU hits.
133
- """
132
+ hashed blocks, and it never participates in CPU hits."""
133
vllm_config = create_vllm_config(
134
kv_connector="SimpleCPUOffloadConnector",
135
kv_role="kv_both",
tests/v1/kv_connector/unit/test_tp_mapping.py
+2
-4
@@ -235,8 +235,7 @@ class TestMambaPlanSplitHandles:
235
236
def test_hetero_block_size_splits(self):
237
"""With a block-size ratio, single-source FA sub-block descs pass
238
- through whole; SSM descs are unexpanded and split per source.
239
- """
238
+ through whole; SSM descs are unexpanded and split per source."""
239
plan = TPMapping(
240
source_ranks_per_group=((0,), (0, 1)),
241
all_source_ranks=(0, 1),
@@ -271,8 +270,7 @@ class TestMambaPlanSplitHandles:
270
271
def test_hetero_block_size_head_sharded_asserts(self):
272
"""Head-sharded FA reads (multiple FA sources) are incompatible with
274
- a block-size mismatch and must fail loudly.
275
- """
273
+ a block-size mismatch and must fail loudly."""
274
plan = TPMapping(
275
source_ranks_per_group=((0, 1), (0, 1)),
276
all_source_ranks=(0, 1),
tests/v1/kv_offload/cpu/policies/test_factory.py
+5
-10
@@ -15,8 +15,7 @@ from vllm.v1.kv_offload.cpu.policies.lru import LRUCachePolicy
15
class _DummyCachePolicy(CachePolicy):
16
"""Minimal CachePolicy for CachePolicyFactory registration tests. Loaded
17
by module path, so it must be importable at module scope (mirrors
18
- tests/v1/kv_offload/test_factory.py's SingleArgExternalOffloadingSpec).
19
- """
18
+ tests/v1/kv_offload/test_factory.py's SingleArgExternalOffloadingSpec)."""
19
20
def __init__(self, cache_capacity: int) -> None:
21
self.cache_capacity = cache_capacity
@@ -55,8 +54,7 @@ class TestCachePolicyFactory:
54
55
def test_pre_registered_policies_can_be_imported(self):
56
"""If someone moves a policy module but forgets to update
58
- factory.py, CI fails.
59
- """
57
+ factory.py, CI fails."""
58
for name in CachePolicyFactory._registry:
59
cls = CachePolicyFactory._registry[name]()
60
assert issubclass(cls, CachePolicy)
@@ -90,8 +88,7 @@ class TestCachePolicyFactory:
88
register_cache_policy() call -- this is how external projects
89
integrate a custom CachePolicy without forking/patching vLLM.
90
Mirrors tests/v1/kv_offload/test_factory.py's
93
- test_dynamic_load_via_spec_module_path.
94
- """
91
+ test_dynamic_load_via_spec_module_path."""
92
policy_cls = CachePolicyFactory.get_cache_policy_cls(
93
"_DummyCachePolicy", "tests.v1.kv_offload.cpu.policies.test_factory"
94
)
@@ -99,8 +96,7 @@ class TestCachePolicyFactory:
96
97
def test_manager_resolves_policy_via_module_path(self):
98
"""End-to-end: CPUOffloadingManager resolves an unregistered policy
102
- purely from cache_policy_module_path.
103
- """
99
+ purely from cache_policy_module_path."""
100
manager = CPUOffloadingManager(
101
num_chunks=4,
102
cache_policy="_DummyCachePolicy",
@@ -110,7 +106,6 @@ class TestCachePolicyFactory:
106
107
def test_unregistered_policy_without_module_path_raises(self):
108
"""eviction_policy not in registry + no cache_policy_module_path ->
113
- ValueError, same shape as the OffloadingSpecFactory error path.
114
- """
109
+ ValueError, same shape as the OffloadingSpecFactory error path."""
110
with pytest.raises(ValueError, match="Unknown cache policy"):
111
CachePolicyFactory.get_cache_policy_cls("nonexistent", None)
tests/v1/kv_offload/cpu/test_canonical_layout.py
+3
-6
@@ -126,8 +126,7 @@ def _canonical_handler(gpu_tensor, cpu_tensor, mapping, gpu_to_cpu):
126
def test_gpu_roundtrip_assembles_canonical_page_across_ranks():
127
"""Two TP2-style rank handlers must scatter into one shared canonical
128
CPU page such that each rank reloads bit-exact and a whole-page (TP1)
129
- reader sees both shards — the cross-topology contract.
130
- """
129
+ reader sees both shards — the cross-topology contract."""
130
torch.manual_seed(0)
131
num_blocks = 4
132
gpu_rank = [
@@ -204,8 +203,7 @@ def _nhd_shard_mapping(tp: int, rank: int) -> CanonicalPageMapping:
203
204
def _head_shard(full_kv: torch.Tensor, tp: int, rank: int) -> torch.Tensor:
205
"""This rank's local page rows out of the (blocks, 2, tokens, heads,
207
- head_bytes) ground truth.
208
- """
206
+ head_bytes) ground truth."""
207
local_heads = _TOTAL_HEADS // tp
208
shard = full_kv[:, :, :, rank * local_heads : (rank + 1) * local_heads, :]
209
return shard.reshape(full_kv.shape[0], -1).contiguous()
@@ -216,8 +214,7 @@ def _head_shard(full_kv: torch.Tensor, tp: int, rank: int) -> torch.Tensor:
214
def test_cross_topology_roundtrip(writer_tp: int, reader_tp: int):
215
"""KV written at one tp must be readable at another: writer ranks scatter
216
head shards into a shared canonical region, reader ranks gather their own
219
- shards, and every reader must see the writers' ground-truth bytes.
220
- """
217
+ shards, and every reader must see the writers' ground-truth bytes."""
218
torch.manual_seed(0)
219
num_blocks = 3
220
full_kv = torch.randint(
tests/v1/kv_offload/cpu/test_shared_offload_region.py
+14
-28
@@ -167,8 +167,7 @@ def _mp_race_construct_and_write(
167
) -> None:
168
"""Race to construct a SharedOffloadRegion, write fill_value, then wait
169
for the parent's cleanup signal before tearing down. The wait gives the
170
- parent a window to read the raw mmap before the creator removes the file.
171
- """
170
+ parent a window to read the raw mmap before the creator removes the file."""
171
try:
172
region = SharedOffloadRegion(
173
engine_id=engine_id,
@@ -197,8 +196,7 @@ def _mp_barrier_construct_and_hold(
196
replicated: bool = False,
197
) -> None:
198
"""Construct with a real cross-process barrier, write, then hold the
200
- mapping (no cleanup) until the parent SIGKILLs this process.
201
- """
199
+ mapping (no cleanup) until the parent SIGKILLs this process."""
200
try:
201
populate_calls = 0
202
get_populate_write_fn = region_module._get_populate_write_fn
@@ -252,8 +250,7 @@ def iid():
250
251
def test_create_next_worker_view_shape_and_stride(iid):
252
"""Returned tensor must have shape (num_chunks, tensor_page_size) and
255
- stride (row_stride, 1) where row_stride = cpu_page_size * num_workers.
256
- """
253
+ stride (row_stride, 1) where row_stride = cpu_page_size * num_workers."""
254
with _region(iid, num_chunks=4, cpu_page_size=2 * PAGE_SIZE) as r:
255
t = r.create_next_worker_view(PAGE_SIZE)
256
assert t.shape == (4, PAGE_SIZE)
@@ -293,8 +290,7 @@ def test_create_next_worker_view_row_stride_with_multiple_workers(iid):
290
291
def test_create_next_worker_view_cursor_advances(iid):
292
"""Each create_next_worker_view call must advance _worker_offset by
296
- tensor_page_size.
297
- """
293
+ tensor_page_size."""
294
with _region(iid, cpu_page_size=3 * PAGE_SIZE) as r:
295
assert r._worker_offset == 0
296
r.create_next_worker_view(PAGE_SIZE)
@@ -351,8 +347,7 @@ def test_create_next_worker_view_overflow_does_not_mutate_cursor(iid):
347
348
def test_create_next_worker_view_write_visible_in_raw_mmap(iid):
349
"""Writes into a create_next_worker_view view must appear at the correct
354
- raw mmap offset
355
- """
350
+ raw mmap offset"""
351
with _region(iid, num_chunks=4) as r:
352
t = r.create_next_worker_view(PAGE_SIZE)
353
t[2, :] = 42 # write to chunk row 2
@@ -385,8 +380,7 @@ def test_create_next_worker_view_multi_tensor_layout(iid):
380
381
def test_create_next_worker_view_multiprocess_slots(iid):
382
"""Each worker process calls create_next_worker_view and writes distinct data;
388
- the parent verifies each slot lands at the correct interleaved offset.
389
- """
383
+ the parent verifies each slot lands at the correct interleaved offset."""
384
num_workers = 2
385
num_chunks = 4
386
@@ -671,8 +665,7 @@ def test_multi_worker_race_shared_memory_visible(iid):
665
666
def test_multiprocess_race_construct_and_write(iid):
667
"""N processes race to construct the same SharedOffloadRegion, each writes
674
- fill_value = rank+1 into their slot; parent verifies interleaved layout.
675
- """
668
+ fill_value = rank+1 into their slot; parent verifies interleaved layout."""
669
num_workers = 4
670
num_chunks = 3
671
@@ -798,8 +791,7 @@ def test_cleanup_unregisters_every_pinned_chunk(iid, monkeypatch):
791
def test_cleanup_after_create_next_worker_view_releases_mmap(iid):
792
"""cleanup() must close the mmap even after create_next_worker_view was called.
793
create_next_worker_view returns a view that shares storage with _base; both must be
801
- released before mmap.close() can succeed.
802
- """
794
+ released before mmap.close() can succeed."""
795
r = _make_region(iid)
796
mmap_obj = r.mmap_obj
797
@@ -978,8 +970,7 @@ def test_ftruncate_failure_cleans_up_creator(monkeypatch):
970
971
def test_backing_file_unlinked_after_barrier(iid):
972
"""The file must exist until the barrier releases (late joiners need the
981
- name) and be gone right after, so no exit path can leak it.
982
- """
973
+ name) and be gone right after, so no exit path can leak it."""
974
path = f"/dev/shm/vllm_offload_{iid}.mmap"
975
seen_at_barrier = []
976
@@ -1001,8 +992,7 @@ def test_backing_file_unlinked_after_barrier(iid):
992
993
def test_barrier_failure_unlinks_creator_and_raises(iid):
994
"""A failed rendezvous must remove the creator's file and re-raise, not
1004
- leave a stub that wedges the next start in _wait_for_file_size.
1005
- """
995
+ leave a stub that wedges the next start in _wait_for_file_size."""
996
path = f"/dev/shm/vllm_offload_{iid}.mmap"
997
with pytest.raises(RuntimeError, match="peer died"):
998
_make_region(iid, barrier=MagicMock(side_effect=RuntimeError("peer died")))
@@ -1012,8 +1002,7 @@ def test_barrier_failure_unlinks_creator_and_raises(iid):
1002
@pytest.mark.parametrize("replicated", [False, True])
1003
def test_mp_barrier_unlinks_file_and_survives_sigkill(iid, replicated):
1004
"""With a real cross-process barrier every worker maps one shared inode,
1015
- the name is gone while they run, and SIGKILL leaks nothing.
1016
- """
1005
+ the name is gone while they run, and SIGKILL leaks nothing."""
1006
num_workers = 2
1007
path = f"/dev/shm/vllm_offload_{iid}.mmap"
1008
ctx = get_mp_context()
@@ -1052,8 +1041,7 @@ def test_mp_barrier_unlinks_file_and_survives_sigkill(iid, replicated):
1041
@pytest.mark.parametrize("failure_phase", ["shm", "memory", "population"])
1042
def test_setup_failure_before_barrier_releases_peers(iid, monkeypatch, failure_phase):
1043
"""A worker that dies before the rendezvous must still arrive at the
1055
- barrier, or its peers block in the collective until it times out.
1056
- """
1044
+ barrier, or its peers block in the collective until it times out."""
1045
failure = MagicMock(side_effect=ValueError("Insufficient space"))
1046
memory_check = failure if failure_phase == "memory" else None
1047
if failure_phase == "shm":
@@ -1084,8 +1072,7 @@ def test_setup_failure_before_barrier_releases_peers(iid, monkeypatch, failure_p
1072
1073
def test_mmap_failure_unlinks_creator_before_releasing_peers(iid, monkeypatch):
1074
"""A creator that fails after sizing the file must drop it before arriving
1087
- at the barrier, so the next start does not land on a stale file.
1088
- """
1075
+ at the barrier, so the next start does not land on a stale file."""
1076
path = f"/dev/shm/vllm_offload_{iid}.mmap"
1077
monkeypatch.setattr("mmap.mmap", MagicMock(side_effect=OSError("mmap")))
1078
seen_at_barrier = []
@@ -1098,8 +1085,7 @@ def test_mmap_failure_unlinks_creator_before_releasing_peers(iid, monkeypatch):
1085
1086
def test_barrier_release_failure_keeps_original_error(iid, monkeypatch):
1087
"""When releasing the peers fails too, the setup error that explains the
1101
- failure must be the one that propagates.
1102
- """
1088
+ failure must be the one that propagates."""
1089
import vllm.v1.kv_offload.cpu.shared_offload_region as region
1090
1091
monkeypatch.setattr(
tests/v1/kv_offload/tiering/p2p/test_manager.py
+31
-62
@@ -48,8 +48,7 @@ def _remote_prefiller_kv_params(
48
kv_request_id: str = "req-1",
49
) -> dict:
50
"""Decoder-side kv_transfer_params: ``remote_prefiller`` sub-dict carries
51
- kv_request_id + remote_host + remote_port.
52
- """
51
+ kv_request_id + remote_host + remote_port."""
52
return {
53
"remote_prefiller": {
54
"kv_request_id": kv_request_id,
@@ -65,8 +64,7 @@ def _remote_kv_source_kv_params(
64
kv_request_id: str = "req-1",
65
) -> dict:
66
"""Symmetric-P2P consumer kv_transfer_params: ``remote_kv_source`` sub-dict has
68
- the same shape as ``remote_prefiller`` (kv_request_id + remote_host + port).
69
- """
67
+ the same shape as ``remote_prefiller`` (kv_request_id + remote_host + port)."""
68
return {
69
"remote_kv_source": {
70
"kv_request_id": kv_request_id,
@@ -78,8 +76,7 @@ def _remote_kv_source_kv_params(
76
77
def _remote_decoder_kv_params(kv_request_id: str = "req-1") -> dict:
78
"""Prefiller-side kv_transfer_params: ``remote_decoder`` sub-dict carries
81
- kv_request_id only.
82
- """
79
+ kv_request_id only."""
80
return {"remote_decoder": {"kv_request_id": kv_request_id}}
81
82
@@ -244,8 +241,7 @@ class TestLookup:
241
def test_lookup_returns_miss_without_prefill_key(self):
242
"""No ``remote_prefiller`` sub-dict means the request was not routed for
243
remote prefill — local prefill should run instead, so lookup()
247
- returns MISS even when a stale ``remote_decoder`` block is present.
248
- """
244
+ returns MISS even when a stale ``remote_decoder`` block is present."""
245
mgr = _make_manager()
246
ctx = _req_context(kv_params=_remote_decoder_kv_params())
247
assert mgr.lookup(b"key", ctx) is LookupResult.MISS
@@ -313,8 +309,7 @@ class TestServeExternalRequests:
309
def test_flushes_failed_serve_ctxs_then_serves_each_session(self):
310
"""serve_external_requests releases the failed serves left by
311
reaped sessions via parent.on_request_finished (clearing the
316
- queue), then delegates to every live session with the same parent.
317
- """
312
+ queue), then delegates to every live session with the same parent."""
313
mgr = _make_manager()
314
ctx = ReqContext(req_id="p2p:peer:req-1:lu1")
315
mgr._failed_serve_ctxs = [ctx]
@@ -368,8 +363,7 @@ class TestSubmitStore:
363
def test_no_binding_yet_parks_in_unbound_stores(self):
364
"""submit_store without a bound session buffers the batch keyed
365
by kv_request_id; no session is pre-created (peer_id is unknown
371
- to the producer at store time).
372
- """
366
+ to the producer at store time)."""
367
mgr = _make_manager()
368
job = _job_metadata(
369
job_id=1,
@@ -396,8 +390,7 @@ class TestSubmitStore:
390
def test_routes_to_bound_session(self):
391
"""If a session has already received FetchMsg for this
392
kv_request_id (so _kv_to_session is populated), submit_store
399
- forwards directly to that session rather than re-buffering.
400
- """
393
+ forwards directly to that session rather than re-buffering."""
394
mgr = _make_manager()
395
bound = _FakeSession(peer_id="10.0.0.1:8000", connected=True)
396
mgr._kv_to_session["req-1"] = bound # type: ignore[assignment]
@@ -420,8 +413,7 @@ class TestSubmitStore:
413
def test_extra_top_level_keys_are_ignored(self):
414
"""Producer-side kv_transfer_params should not pre-create a
415
session even when a stale caller still passes a top-level
423
- ``remote_host``/``remote_port`` next to ``remote_decoder``.
424
- """
416
+ ``remote_host``/``remote_port`` next to ``remote_decoder``."""
417
mgr = _make_manager()
418
params = _remote_decoder_kv_params()
419
params["remote_host"] = "stale"
@@ -465,8 +457,7 @@ class TestSubmitLoad:
457
458
def test_happy_path_with_active_session(self):
459
"""When the peer's session exists, submit_load forwards to
468
- session.request_blocks and does NOT add a finished result yet.
469
- """
460
+ session.request_blocks and does NOT add a finished result yet."""
461
mgr = _make_manager()
462
peer_id = "10.0.0.1:8000"
463
existing = _FakeSession(peer_id=peer_id, connected=True)
@@ -486,8 +477,7 @@ class TestSubmitLoad:
477
def test_missing_consumer_flag_fails(self):
478
"""Peer fields present but neither do_remote_prefill nor
479
do_p2p_fetch is set — submit_load fails the job rather than
489
- emit a stray FetchMsg.
490
- """
480
+ emit a stray FetchMsg."""
481
mgr = _make_manager()
482
params = {
483
"remote_host": "10.0.0.1",
@@ -531,8 +521,7 @@ class TestOnRequestFinished:
521
def test_decoder_side_calls_session_finish_request(self):
522
"""Decoder-side finish (``remote_prefiller`` set) still routes via peer_id
523
because the consumer addresses the producer it loaded from. The
534
- session's finish_request cancels the client-role load.
535
- """
524
+ session's finish_request cancels the client-role load."""
525
mgr = _make_manager()
526
peer_id = "10.0.0.1:8000"
527
session = _FakeSession(peer_id=peer_id)
@@ -544,8 +533,7 @@ class TestOnRequestFinished:
533
def test_p2p_consumer_side_calls_session_finish_request(self):
534
"""Symmetric-P2P consumer finish (``remote_kv_source`` set) routes via peer_id
535
so the session drops any pending lookups (cancel_lookups) and
547
- cancels any inbound load.
548
- """
536
+ cancels any inbound load."""
537
mgr = _make_manager()
538
peer_id = "10.0.0.1:8000"
539
session = _FakeSession(peer_id=peer_id)
@@ -556,8 +544,7 @@ class TestOnRequestFinished:
544
545
def test_prefiller_bound_id_routes_via_kv_to_session(self):
546
"""Prefiller-side finish for an id whose session is already bound
559
- (FetchMsg received) routes via _kv_to_session and pops the entry.
560
- """
547
+ (FetchMsg received) routes via _kv_to_session and pops the entry."""
548
mgr = _make_manager()
549
bound = _FakeSession(peer_id="some-peer:1", connected=True)
550
mgr._kv_to_session["req-1"] = bound # type: ignore[assignment]
@@ -571,8 +558,7 @@ class TestOnRequestFinished:
558
and no session binding is a no-op on `_unbound_stores`. The
559
parked batches survive until a peer fetches them or the
560
`_reap_unbound_stores` timeout fires — `on_request_finished`
574
- must not evict them.
575
- """
561
+ must not evict them."""
562
from vllm.v1.kv_offload.tiering.p2p.manager import _UnboundStoreBatch
563
564
mgr = _make_manager()
@@ -742,8 +728,7 @@ class TestGetFinished:
728
729
def test_reap_fails_probes(self):
730
"""A reaped session's in-flight lookups land in _failed_req_ids so
745
- the consumer's lookup() returns MISS instead of RETRY forever.
746
- """
731
+ the consumer's lookup() returns MISS instead of RETRY forever."""
732
733
class FakeData:
734
def remove_remote_peer(self, pid):
@@ -778,8 +763,7 @@ class TestGetFinished:
763
def test_unbound_store_reaped_after_timeout(self):
764
"""Unbound stores past the reap deadline surface as failed and their
765
kv_request_id lands in _reaped_stores so a late FetchMsg is rejected
781
- instead of parking demand nothing can satisfy.
782
- """
766
+ instead of parking demand nothing can satisfy."""
767
from vllm.v1.kv_offload.tiering.p2p.manager import _UnboundStoreBatch
768
769
mgr = self._make()
@@ -801,8 +785,7 @@ class TestGetFinished:
785
786
def test_submit_store_parks_unbound_batch(self):
787
"""submit_store on an unbound id appends a batch with a fresh
804
- submitted_at stamp so the unbound-store sweep can age it out.
805
- """
788
+ submitted_at stamp so the unbound-store sweep can age it out."""
789
mgr = _make_manager()
790
job = _job_metadata(
791
job_id=1, kv_params=_remote_decoder_kv_params(kv_request_id="req-1")
@@ -824,21 +807,18 @@ class TestHasPendingWork:
807
"""has_pending_work() must always return True so the engine keeps
808
ticking the offload pipeline — that's the only thread driving
809
_control.poll() (incoming peer connects) and session.poll()
827
- (incoming fetch messages on existing sessions).
828
- """
810
+ (incoming fetch messages on existing sessions)."""
811
812
def test_returns_true_unconditionally_to_keep_engine_ticking(self):
813
"""Even with no sessions and no jobs, has_pending_work() returns
814
True so the engine keeps calling get_finished_jobs(), which is
833
- what drives _control.poll() for inbound peer connects.
834
- """
815
+ what drives _control.poll() for inbound peer connects."""
816
mgr = _make_manager()
817
assert mgr.has_pending_work() is True
818
819
def test_returns_true_even_when_sessions_present(self):
820
"""The result is the same regardless of session state — there is
840
- no 'idle' branch.
841
- """
821
+ no 'idle' branch."""
822
mgr = _make_manager()
823
mgr._sessions["peer:1"] = _FakeSession(peer_id="peer:1") # type: ignore[assignment]
824
assert mgr.has_pending_work() is True
@@ -851,8 +831,7 @@ class TestHasPendingWork:
831
832
class _ShutdownFakeData:
833
"""Fake DataTransport that records cancel/poll/close calls and
854
- drives the wait-cancel loop with a scriptable `still` queue.
855
- """
834
+ drives the wait-cancel loop with a scriptable `still` queue."""
835
836
def __init__(self, still_queue: list[list[int]] | None = None) -> None:
837
# Each list in still_queue is the set of ids the next
@@ -896,8 +875,7 @@ class _ShutdownFakeControl:
875
class TestShutdownDrain:
876
"""shutdown() drains inflight transfers via cancel(mode='wait')
877
before calling _data.close(), with a 3s deadline fallback to
899
- cancel(mode='immediate').
900
- """
878
+ cancel(mode='immediate')."""
879
880
def _prep(
881
self,
@@ -1316,8 +1294,7 @@ class _RecordingConn:
1294
1295
class TestAcceptNewPeers:
1296
"""A second inbound from an already-connected peer is rejected and the
1319
- new conn is closed; the existing session is left untouched.
1320
- """
1297
+ new conn is closed; the existing session is left untouched."""
1298
1299
def test_duplicate_connection_is_closed_and_existing_session_untouched(self):
1300
mgr = _make_manager()
@@ -1339,8 +1316,7 @@ class TestAcceptNewPeers:
1316
"""An inbound conn from a peer with no existing session creates
1317
a fresh connected session and registers it under conn.peer_id.
1318
The prefiller has no pre-created pending session anymore — the
1342
- first signal of a peer's existence is its inbound connection.
1343
- """
1319
+ first signal of a peer's existence is its inbound connection."""
1320
1321
class FakeData:
1322
block_len = 4096
@@ -1387,8 +1363,7 @@ class TestAcceptNewPeers:
1363
1364
class TestPollOnce:
1365
"""_poll_once must drain control, accept new peers, poll every session,
1390
- surface results, and reap dead sessions — in that order.
1391
- """
1366
+ surface results, and reap dead sessions — in that order."""
1367
1368
def test_orchestrates_accept_poll_and_reap(self):
1369
mgr = _make_manager()
@@ -1444,8 +1419,7 @@ class TestPollOnce:
1419
def test_new_fetch_id_binds_and_replays_unbound_batches(self):
1420
"""When session.poll() reports a kv_request_id whose FetchMsg
1421
arrived this tick, the manager binds it to that session and
1447
- replays every parked submit_store batch via add_stored_blocks.
1448
- """
1422
+ replays every parked submit_store batch via add_stored_blocks."""
1423
from vllm.v1.kv_offload.tiering.p2p.manager import _UnboundStoreBatch
1424
1425
mgr = _make_manager()
@@ -1479,8 +1453,7 @@ class TestPollOnce:
1453
1454
def test_new_fetch_id_with_no_unbound_still_binds(self):
1455
"""A FetchMsg for a kv_request_id with no parked batches still
1482
- records the binding so subsequent submit_stores route fast.
1483
- """
1456
+ records the binding so subsequent submit_stores route fast."""
1457
mgr = _make_manager()
1458
peer = "10.0.0.1:8000"
1459
sess = _FakeSession(
@@ -1503,8 +1476,7 @@ class TestPollOnce:
1476
1477
def test_failed_load_records_kv_request_id(self):
1478
"""A LoadResult(success=False) from session.poll() must add its
1506
- kv_request_id to _failed_req_ids so future lookups return MISS.
1507
- """
1479
+ kv_request_id to _failed_req_ids so future lookups return MISS."""
1480
mgr = _make_manager()
1481
peer = "10.0.0.1:8000"
1482
sess = _FakeSession(
@@ -1568,8 +1540,7 @@ class TestDrainJobs:
1540
1541
def test_logs_warning_after_5s_then_completes(self, monkeypatch):
1542
"""A session that stays inflight past 5s triggers the warning, and
1571
- once it clears the loop returns.
1572
- """
1543
+ once it clears the loop returns."""
1544
mgr = _make_manager()
1545
mgr._control = _DrainCtrl() # type: ignore[assignment]
1546
sess = _FakeSession(peer_id="peer:1")
@@ -1627,8 +1598,7 @@ class TestDrainJobs:
1598
class TestOnScheduleEnd:
1599
def test_is_noop(self):
1600
"""on_schedule_end is a documented no-op; just confirm it doesn't
1630
- raise and doesn't mutate state.
1631
- """
1601
+ raise and doesn't mutate state."""
1602
mgr = _make_manager()
1603
before_sessions = dict(mgr._sessions)
1604
before_jobs = list(mgr._finished_jobs)
@@ -1654,8 +1624,7 @@ class TestConnectionDeathMidTransfer:
1624
prefiller-side store no longer travels through the session at store
1625
time (it's parked in _unbound_stores keyed by kv_request_id), so its
1626
cleanup on connection death is via on_request_finished or the
1657
- unbound-store timeout — covered separately below.
1658
- """
1627
+ unbound-store timeout — covered separately below."""
1628
1629
def test_dead_connection_with_pending_work_surfaces_failures(self):
1630
mgr_a, mgr_b = _build_paired_managers()
tests/v1/kv_offload/tiering/p2p/test_sessions.py
+40
-80
@@ -626,8 +626,7 @@ class TestClientFlows:
626
"""collect_results / has_active_loads use the _active_loads work-list,
627
armed when a fetch is issued and discarded exactly when its load
628
clears — a probe-only request never enters it, and completion empties
629
- it while the entry may briefly linger for GC.
630
- """
629
+ it while the entry may briefly linger for GC."""
630
session, conn, _ = _make_session()
631
_activate(session, conn)
632
client = session._client
@@ -704,8 +703,7 @@ class TestClientFlows:
703
def test_load_abort_ack_clears_request(self):
704
"""After load timeout sends AbortFetch, an arriving AbortAckMsg from
705
the peer surfaces the failure cleanly and removes the request from
707
- _requests — covers the on_abort_ack arrival path.
708
- """
706
+ _requests — covers the on_abort_ack arrival path."""
707
session, conn, _ = _make_session()
708
_activate(session, conn)
709
session.request_blocks(
@@ -742,8 +740,7 @@ class TestLookupFlow:
740
def test_aggregate_flush_resolve_round_trip(self):
741
"""register_lookup → flush sends one LookupMsg → response
742
resolves entries → register_lookup returns the cached bool on
745
- every call, and repeat probes never re-issue a LookupMsg.
746
- """
743
+ every call, and repeat probes never re-issue a LookupMsg."""
744
session, conn, _ = _make_session()
745
_activate(session, conn)
746
@@ -796,8 +793,7 @@ class TestLookupFlow:
793
def test_request_blocks_clears_probe_cache(self):
794
"""A resolved HIT probe is popped when its fetch is issued, so a
795
re-scheduled request re-probes instead of trusting the stale True
799
- (the served block is unpinned and may have been evicted).
800
- """
796
+ (the served block is unpinned and may have been evicted)."""
797
session, conn, _ = _make_session()
798
_activate(session, conn)
799
@@ -883,8 +879,7 @@ class TestLookupFlow:
879
def test_multiple_lookup_msgs_across_steps(self):
880
"""A request's block set may be discovered across scheduler steps:
881
each step that registers new keys flushes its own LookupMsg for
886
- the same kv_request_id, carrying only the newly-probed keys.
887
- """
882
+ the same kv_request_id, carrying only the newly-probed keys."""
883
session, conn, _ = _make_session()
884
_activate(session, conn)
885
@@ -912,8 +907,7 @@ class TestLookupFlow:
907
908
def test_split_response_resolves_across_messages(self):
909
"""Producer may answer one LookupMsg's keys across multiple
915
- LookupRespMsgs — pairs are self-describing so each lands.
916
- """
910
+ LookupRespMsgs — pairs are self-describing so each lands."""
911
session, conn, _ = _make_session()
912
_activate(session, conn)
913
@@ -960,8 +954,7 @@ class TestLookupFlow:
954
def test_finish_after_flushed_lookup_sends_empty_fetch(self):
955
"""LookupMsg flushed but no FetchMsg sent (all-miss case) →
956
finish_request emits an empty FetchMsg so the peer can drop its
963
- lookup state and call parent.on_request_finished.
964
- """
957
+ lookup state and call parent.on_request_finished."""
958
session, conn, _ = _make_session()
959
_activate(session, conn)
960
@@ -979,8 +972,7 @@ class TestLookupFlow:
972
973
def test_finish_without_flushed_lookup_sends_no_fetch(self):
974
"""No LookupMsg was ever sent → finish_request must not emit an
982
- empty FetchMsg (the peer has no state to release).
983
- """
975
+ empty FetchMsg (the peer has no state to release)."""
976
session, conn, _ = _make_session()
977
_activate(session, conn)
978
@@ -995,8 +987,7 @@ class TestLookupFlow:
987
988
def test_finish_after_real_fetch_sends_no_second_fetch(self):
989
"""A real FetchMsg was already sent for the id → finish_request
998
- must not emit a second (empty) FetchMsg.
999
- """
990
+ must not emit a second (empty) FetchMsg."""
991
session, conn, _ = _make_session()
992
_activate(session, conn)
993
@@ -1027,8 +1018,7 @@ class TestLookupFlow:
1018
"""``poll()`` only enqueues an inbound LookupMsg — no response is
1019
sent until ``serve_external_requests``. With an all-miss parent
1020
the aggregated LookupRespMsg carries the same keys and
1030
- ``hits=[False, ...]``.
1031
- """
1021
+ ``hits=[False, ...]``."""
1022
session, conn, _ = _make_session()
1023
_activate(session, conn)
1024
@@ -1088,8 +1078,7 @@ class TestServerLookupHandling:
1078
def test_immediate_hits_create_one_store_job(self):
1079
"""All-HIT batch: one create_store_job call with all keys, one
1080
LookupRespMsg with hits=[True]*N, on_request_finished fires at the
1091
- end of serve, and `available` is populated for the eventual fetch.
1092
- """
1081
+ end of serve, and `available` is populated for the eventual fetch."""
1082
cb = FakeParent(stored={b"hA": 1, b"hB": 2, b"hC": 3})
1083
session, conn, _ = _make_session()
1084
_activate(session, conn)
@@ -1119,8 +1108,7 @@ class TestServerLookupHandling:
1108
1109
def test_all_misses_no_store_job_finish_fires(self):
1110
"""All-MISS batch: no create_store_job call; one LookupRespMsg
1122
- with hits=[False]*N; on_request_finished fires at end of serve.
1123
- """
1111
+ with hits=[False]*N; on_request_finished fires at end of serve."""
1112
cb = FakeParent()
1113
session, conn, _ = _make_session()
1114
_activate(session, conn)
@@ -1140,8 +1128,7 @@ class TestServerLookupHandling:
1128
"""HIT/MISS resolutions do not go out on first sight when any
1129
key is still HIT_PENDING / RETRY. The lookup parks until every
1130
key has settled (or the deadline fires), then one
1143
- LookupRespMsg carries all keys in wire order.
1144
- """
1131
+ LookupRespMsg carries all keys in wire order."""
1132
cb = FakeParent(
1133
stored={b"hA": 1},
1134
pending={b"hB"},
@@ -1170,8 +1157,7 @@ class TestServerLookupHandling:
1157
the deferred aggregate response: one LookupRespMsg carrying
1158
both keys in wire order, and one create_store_job call per
1159
HIT (the second HIT is pinned when it resolves, not when the
1173
- response goes out).
1174
- """
1160
+ response goes out)."""
1161
cb = FakeParent(stored={b"hA": 1}, pending={b"hB"})
1162
session, conn, _ = _make_session()
1163
_activate(session, conn)
@@ -1207,8 +1193,7 @@ class TestServerLookupHandling:
1193
def test_pending_timeout_replies_miss_no_store_job(self):
1194
"""A HIT_PENDING key that stays pending past the batch
1195
``deadline`` is force-MISS and never pinned; the deferred
1210
- aggregate response fires with hits=[False].
1211
- """
1196
+ aggregate response fires with hits=[False]."""
1197
cb = FakeParent(pending={b"hA"})
1198
session, conn, _ = _make_session()
1199
_activate(session, conn)
@@ -1235,8 +1220,7 @@ class TestServerLookupHandling:
1220
1221
def test_finish_request_called_per_lookup_msg_not_per_kv_request_id(self):
1222
"""Two LookupMsgs for the same kv_request_id get distinct ctxs
1238
- and two on_request_finished calls (one per batch).
1239
- """
1223
+ and two on_request_finished calls (one per batch)."""
1224
cb = FakeParent(stored={b"hA": 1, b"hB": 2})
1225
session, conn, _ = _make_session()
1226
_activate(session, conn)
@@ -1260,8 +1244,7 @@ class TestServerLookupHandling:
1244
"""Tearing the session down with a parked batch returns the
1245
synthetic ctx as a failed serve (no parent handle at teardown) so
1246
the manager can release the TieringManager's state on its next
1263
- serve.
1264
- """
1247
+ serve."""
1248
cb = FakeParent(pending={b"hA"})
1249
session, conn, _ = _make_session()
1250
_activate(session, conn)
@@ -1282,8 +1265,7 @@ class TestServerLookupHandling:
1265
def test_wire_finish_drops_pending_batches_for_kv_request_id(self):
1266
"""``ServerRole.finish(kv_request_id)`` drops every parked batch
1267
whose kv_request_id matches and queues its ctx for the next
1285
- serve's on_request_finished.
1286
- """
1268
+ serve's on_request_finished."""
1269
cb = FakeParent(pending={b"hA", b"hB"})
1270
session, conn, _ = _make_session()
1271
_activate(session, conn)
@@ -1314,8 +1296,7 @@ class TestServerLookupHandling:
1296
def test_incoming_fetch_drops_pending_lookups_for_kv_request_id(self):
1297
"""A peer FetchMsg terminates the lookup phase for its id: parked
1298
lookups with matching kv_request_id are dropped and their
1317
- ctx queued for on_request_finished; other kv_request_ids untouched.
1318
- """
1299
+ ctx queued for on_request_finished; other kv_request_ids untouched."""
1300
cb = FakeParent(pending={b"hA", b"hB"})
1301
session, conn, _ = _make_session()
1302
_activate(session, conn)
@@ -1357,8 +1338,7 @@ class TestServerLookupHandling:
1338
def test_lookup_then_fetch_round_trip_emits_store_result(self):
1339
"""End-to-end: lookup pins primary slots → fetch matches them →
1340
NIXL transfer completes → StoreResult surfaces with the
1360
- create_store_job's job_id (the engine releases the pin).
1361
- """
1341
+ create_store_job's job_id (the engine releases the pin)."""
1342
cb = FakeParent(stored={b"hA": 7, b"hB": 8})
1343
session, conn, transport = _make_session()
1344
_activate(session, conn)
@@ -1480,8 +1460,7 @@ class TestServerFlows:
1460
1461
def test_abort_fetch_defers_ack_when_cancel_pending(self):
1462
"""If cancel(mode='wait') reports still-inflight tids, the ack is
1483
- deferred and the abort is parked (abort_started_at set).
1484
- """
1463
+ deferred and the abort is parked (abort_started_at set)."""
1464
session, conn, transport = _make_session()
1465
_activate(session, conn)
1466
# Seed an inflight transfer for req-1 that the transport pretends
@@ -1516,8 +1495,7 @@ class TestServerFlows:
1495
1496
def test_abort_fetch_acks_after_drain(self):
1497
"""Once the transport reports the tid as DONE the parked abort
1519
- completes and AbortAckMsg is sent.
1520
- """
1498
+ completes and AbortAckMsg is sent."""
1499
session, conn, transport = _make_session()
1500
_activate(session, conn)
1501
tid = 42
@@ -1556,8 +1534,7 @@ class TestServerFlows:
1534
1535
def test_abort_fetch_force_cancels_after_timeout(self):
1536
"""If wait-mode never drains, the deadline forces immediate
1559
- cancel and an ack is still sent.
1560
- """
1537
+ cancel and an ack is still sent."""
1538
session, conn, transport = _make_session()
1539
_activate(session, conn)
1540
tid = 42
@@ -1599,8 +1576,7 @@ class TestServerFlows:
1576
1577
def test_abort_fetch_idempotent_while_draining(self):
1578
"""Receiving AbortFetchMsg twice for the same kv_request_id
1602
- keeps a single pending entry and produces a single ack.
1603
- """
1579
+ keeps a single pending entry and produces a single ack."""
1580
session, conn, transport = _make_session()
1581
_activate(session, conn)
1582
tid = 42
@@ -1658,8 +1634,7 @@ class TestServerFlows:
1634
def test_store_timeout_then_late_completion_no_duplicate(self):
1635
"""A job timed out by _timeout_pending_store_jobs must not also
1636
emit a contradictory StoreResult(success=True) when the transport
1661
- later reports the same transfer as done.
1662
- """
1637
+ later reports the same transfer as done."""
1638
session, conn, transport = _make_session()
1639
_activate(session, conn)
1640
session.add_stored_blocks("req-1", [b"k1"], [0], job_id=1)
@@ -1692,8 +1667,7 @@ class TestServerFlows:
1667
def test_store_timeout_then_late_failure_no_duplicate(self):
1668
"""Symmetric guard: a timed-out job must not also emit a second
1669
StoreResult(success=False) when the transport later reports the
1695
- same transfer as failed.
1696
- """
1670
+ same transfer as failed."""
1671
session, conn, transport = _make_session()
1672
_activate(session, conn)
1673
session.add_stored_blocks("req-1", [b"k1"], [0], job_id=1)
@@ -1736,8 +1710,7 @@ class TestFinishRequestServerSide:
1710
1711
def test_no_inflight_unmatched_demand_sends_failure(self):
1712
"""finish_request with unmatched demand and no inflight ->
1739
- immediate TransferDoneMsg(success=False); _outbound cleared.
1740
- """
1713
+ immediate TransferDoneMsg(success=False); _outbound cleared."""
1714
session, conn, _ = _make_session()
1715
_activate(session, conn)
1716
# Decoder demanded a block we never stored.
@@ -1763,8 +1736,7 @@ class TestFinishRequestServerSide:
1736
1737
def test_with_inflight_defers_then_fires_on_last_transfer(self):
1738
"""finish_request with inflight defers; last transfer fires the
1766
- early-fail message and clears _outbound.
1767
- """
1739
+ early-fail message and clears _outbound."""
1740
session, conn, transport = _make_session()
1741
_activate(session, conn)
1742
# Demand 2 blocks; we store 1 (kicks one inflight transfer).
@@ -1801,8 +1773,7 @@ class TestFinishRequestServerSide:
1773
1774
def test_full_demand_satisfied_still_sends_success(self):
1775
"""finish_request must not override a fully-satisfied transfer:
1804
- when remaining hits 0, success=True still fires.
1805
- """
1776
+ when remaining hits 0, success=True still fires."""
1777
session, conn, transport = _make_session()
1778
_activate(session, conn)
1779
conn.enqueue(
@@ -1831,8 +1802,7 @@ class TestFinishRequestServerSide:
1802
"""Prefiller-first: finish_request runs before the decoder's
1803
fetch arrives. State is held until fetch, then
1804
finalized — success=True if all demand was matched against
1834
- available blocks, else success=False.
1835
- """
1805
+ available blocks, else success=False."""
1806
# Case A: all demand satisfied by available blocks.
1807
session, conn, transport = _make_session()
1808
_activate(session, conn)
@@ -1893,8 +1863,7 @@ class TestFinishRequestServerSide:
1863
"""finish_request with a stored-but-unmatched job and no inflight ->
1864
TransferDoneMsg(success=False) AND deferred
1865
StoreResult(success=False) for the submit_store'd job, instead of
1896
- the 30s _STORE_TIMEOUT_S path.
1897
- """
1866
+ the 30s _STORE_TIMEOUT_S path."""
1867
session, conn, _ = _make_session()
1868
_activate(session, conn)
1869
# Decoder demanded b"demand"; we never stored it.
@@ -1930,8 +1899,7 @@ class TestFinishRequestServerSide:
1899
def test_finish_request_remaining_zero_emits_success_via_inflight(self):
1900
"""Deferred-via-inflight path: finish_request with inflight, last
1901
transfer drains remaining to 0 -> TransferDoneMsg(success=True)
1933
- AND StoreResult(success=True).
1934
- """
1902
+ AND StoreResult(success=True)."""
1903
session, conn, transport = _make_session()
1904
_activate(session, conn)
1905
conn.enqueue(
@@ -2279,8 +2247,7 @@ class TestDisconnect:
2247
def test_send_failure_marks_connection_dead(self):
2248
"""A raising send must mark the connection dead, not silently drop
2249
the message — otherwise the session lingers alive, is never reaped,
2282
- and in-flight lookups/loads toward the dead peer hang forever.
2283
- """
2250
+ and in-flight lookups/loads toward the dead peer hang forever."""
2251
session, conn, _ = _make_session()
2252
_activate(session, conn)
2253
assert session.alive
@@ -2293,8 +2260,7 @@ class TestDisconnect:
2260
2261
def test_close_surfaces_inflight_lookups(self):
2262
"""close() reports kv_request_ids whose symmetric-P2P probe is still
2296
- unresolved; resolved probes are not reported (their answer is in).
2297
- """
2263
+ unresolved; resolved probes are not reported (their answer is in)."""
2264
session, conn, _ = _make_session()
2265
_activate(session, conn)
2266
@@ -2402,8 +2368,7 @@ class TestDispatchErrorHandling:
2368
2369
def test_value_error_disconnects_on_first_occurrence(self):
2370
"""A FetchMsg that fails validate() raises ValueError and must
2405
- terminate the session immediately, with a DisconnectMsg sent.
2406
- """
2371
+ terminate the session immediately, with a DisconnectMsg sent."""
2372
session, conn, _ = _make_session()
2373
_activate(session, conn)
2374
# length mismatch → FetchMsg.validate raises ValueError
@@ -2430,8 +2395,7 @@ class TestDispatchErrorHandling:
2395
2396
def test_internal_error_does_not_disconnect_once(self):
2397
"""A non-ValueError raised by a handler is treated as an internal
2433
- bug: counter increments, session stays alive on a single hit.
2434
- """
2398
+ bug: counter increments, session stays alive on a single hit."""
2399
session, conn, _ = _make_session()
2400
_activate(session, conn)
2401
@@ -2454,8 +2418,7 @@ class TestDispatchErrorHandling:
2418
2419
def test_internal_error_threshold_disconnects(self):
2420
"""Once consecutive non-protocol errors hit the threshold, the
2457
- session tears down via _protocol_error.
2458
- """
2421
+ session tears down via _protocol_error."""
2422
session, conn, _ = _make_session()
2423
_activate(session, conn)
2424
@@ -2479,8 +2442,7 @@ class TestDispatchErrorHandling:
2442
2443
def test_internal_error_counter_resets_on_success(self):
2444
"""A successful dispatch between errors prevents the threshold
2482
- from being reached.
2483
- """
2445
+ from being reached."""
2446
session, conn, _ = _make_session()
2447
_activate(session, conn)
2448
@@ -2523,8 +2485,7 @@ class TestInflightPerReqInvariant:
2485
def test_invariant_holds_through_lifecycle(self):
2486
"""Run a full submit→complete sequence for two concurrent
2487
kv_request_ids and assert the counter matches `_inflight` at
2526
- every observable step, including the empty-after-finish case.
2527
- """
2488
+ every observable step, including the empty-after-finish case."""
2489
session, conn, transport = _make_session()
2490
_activate(session, conn)
2491
@@ -2589,8 +2550,7 @@ class TestInflightPerReqInvariant:
2550
"""Populate many inflight xfers across many ids; lookup must
2551
match the actual presence in `_inflight` for both hits and
2552
misses. The whole point of the counter is that this lookup is
2592
- constant-time, but we assert correctness, not timing.
2593
- """
2553
+ constant-time, but we assert correctness, not timing."""
2554
session, _, _ = _make_session()
2555
for kv_id_idx in range(100):
2556
kv_id = f"req-{kv_id_idx}"
tests/v1/kv_offload/tiering/test_async_lookup.py
+2
-4
@@ -264,8 +264,7 @@ class TestAsyncLookupManager:
264
subsequent lookup then returns False (MISS) directly, WITHOUT enqueuing
265
a fresh batch_lookup — that is what makes the request unable to loop.
266
The entry is retained (as False) not dropped, so cleanup()'s reverse
267
- index stays consistent; an unknown key is a no-op.
268
- """
267
+ index stays consistent; an unknown key is a no-op."""
268
mgr = InMemoryLookupManager(existing_keys={_key(1), _key(2)})
269
ctx = _ctx("reqA")
270
assert mgr.lookup(_key(1), ctx) is None
@@ -305,8 +304,7 @@ class TestAsyncLookupManager:
304
receive at most one result per key. Normal operation resolves a key a
305
single time; a second result for an already-decided key trips the assert
306
that guards the invariant (a silent overwrite could flip a corrected
308
- miss back to True and reopen the failed-load livelock).
309
- """
307
+ miss back to True and reopen the failed-load livelock)."""
308
mgr = InMemoryLookupManager(existing_keys={_key(1)})
309
ctx = _ctx("reqA")
310
tests/v1/kv_offload/tiering/test_fs_tier.py
+8
-16
@@ -369,8 +369,7 @@ def test_shutdown_discards_pending_tasks(fs_tier):
369
@pytest.mark.parametrize("use_c_ext", [True, False])
370
def test_store_load_data_integrity(fs_tier, monkeypatch, use_c_ext, batch_size):
371
"""Data written by store must be exactly recovered by load, for batches
372
- of any size -- including the empty batch.
373
- """
372
+ of any size -- including the empty batch."""
373
import vllm.v1.kv_offload.tiering.fs.io as io_mod
374
375
if use_c_ext and not io_mod._HAS_FSIO_C:
@@ -467,8 +466,7 @@ def test_wait_idle_blocks_until_tasks_complete():
466
467
def test_batch_lookup_c_extension(tmp_path):
468
"""Validates batch_lookup_C: empty, single, all-existing, all-missing,
470
- mixed ordering, and input type validation.
471
- """
469
+ mixed ordering, and input type validation."""
470
try:
471
from vllm.fs_io_C import batch_lookup as batch_lookup_C
472
except ImportError:
@@ -532,8 +530,7 @@ def test_batch_lookup_dispatch(fs_tier, monkeypatch, use_c_ext):
530
@pytest.mark.parametrize("use_c_ext", [True, False])
531
def test_out_of_bounds_block_id_smoke(fs_tier, monkeypatch, use_c_ext):
532
"""Smoke test: a block id beyond the primary tensor's block count must
535
- fail the job, for both the C extension and the Python fallback.
536
- """
533
+ fail the job, for both the C extension and the Python fallback."""
534
import vllm.v1.kv_offload.tiering.fs.io as io_mod
535
536
if use_c_ext and not io_mod._HAS_FSIO_C:
@@ -615,8 +612,7 @@ def test_batched_partial_load_failure_keeps_loaded_blocks(
612
loaded before it (#50321). Corrupt the LAST block: the earlier blocks load
613
fine, so the job reports successful_keys for them and marks only the failed
614
tail a miss. The earlier keys stay HIT — including for the same request —
618
- while the corrupt block stays a MISS (its file was removed).
619
- """
615
+ while the corrupt block stays a MISS (its file was removed)."""
616
import vllm.v1.kv_offload.tiering.fs.io as io_mod
617
618
if use_c_ext and not io_mod._HAS_FSIO_C:
@@ -668,8 +664,7 @@ def test_batched_load_first_block_fails_marks_whole_batch(
664
):
665
"""When the FIRST block fails, nothing loaded before it: the job reports no
666
successful_keys (None) and the whole batch is marked a miss for the
671
- request.
672
- """
667
+ request."""
668
import vllm.v1.kv_offload.tiering.fs.io as io_mod
669
670
if use_c_ext and not io_mod._HAS_FSIO_C:
@@ -700,8 +695,7 @@ def test_transient_load_failure_leaves_file(fs_tier, monkeypatch, use_c_ext):
695
"""A transient host error (here ELOOP on open) is NOT a short read: the job
696
fails but the block file must survive untouched, on both the C and Python
697
paths. Deleting on a transient error would turn a passing hiccup into
703
- permanent data loss.
704
- """
698
+ permanent data loss."""
699
import vllm.v1.kv_offload.tiering.fs.io as io_mod
700
701
if use_c_ext and not io_mod._HAS_FSIO_C:
@@ -805,8 +799,7 @@ def test_mixed_job_results_emit_event_only_for_successful_job(
799
fs_tier_with_events, monkeypatch
800
):
801
"""With a failed and a successful store job in flight, exactly one event
808
- is emitted and its keys belong to the successful job.
809
- """
802
+ is emitted and its keys belong to the successful job."""
803
import vllm.v1.kv_offload.tiering.fs.manager as mgr_mod
804
805
tier = fs_tier_with_events
@@ -891,8 +884,7 @@ def test_events_require_global_kv_events_flag(tmp_path):
884
885
def test_cascade_store_emits_fs_event_through_tiering_manager(tmp_path):
886
"""A GPU->CPU->fs cascade surfaces the tier-owned FS stored event via the
894
- TieringOffloadingManager's aggregated take_events().
895
- """
887
+ TieringOffloadingManager's aggregated take_events()."""
888
from vllm.v1.kv_offload.tiering.manager import (
889
CPUPrimaryTierOffloadingManager,
890
TieringOffloadingManager,
tests/v1/kv_offload/tiering/test_obj_tier.py
+2
-4
@@ -346,8 +346,7 @@ class TestMockObjTierBasic:
346
the scheduler would re-issue the same doomed promotion every step for
347
the life of the request. The mark is served from cache with no
348
re-probe, so even though the mock object is still 'present' the SAME
349
- request now resolves to MISS.
350
- """
349
+ request now resolves to MISS."""
350
ctx = ReqContext(req_id="obj-livelock")
351
self.tier.submit_store(make_job(1, [key(1)], [0]))
352
assert all(r.success for r in drain(self.tier))
@@ -651,8 +650,7 @@ class TestObjTierKVEvents:
650
def test_mixed_job_results_emit_event_only_for_successful_job(self):
651
"""With a failed and a successful store job resolving in the same
652
poll, exactly one event is emitted and its keys belong to the
654
- successful job.
655
- """
653
+ successful job."""
654
original = self.agent.check_xfer_state
655
self.agent.check_xfer_state = lambda h: "ERR" if h._id == 0 else original(h)
656
self.tier.submit_store(make_job(1, [key(1)], [0])) # handle 0: fails
tests/v1/kv_offload/tiering/test_tiering_offloading.py
+11
-22
@@ -273,8 +273,7 @@ _CASCADE_SUPPLY_BEHAVIOR = {
273
274
def test_every_lookup_result_has_a_declared_cascade_behavior():
275
"""A new LookupResult must state what the cascade does with it, rather
276
- than falling into whichever branch happens to catch it.
277
- """
276
+ than falling into whichever branch happens to catch it."""
277
assert set(_CASCADE_SUPPLY_BEHAVIOR) == set(LookupResult)
278
279
@@ -321,8 +320,7 @@ class TestTieringOffloadingManager:
320
321
def test_failed_promotion_finalizes_primary_with_failure(self, manager_setup):
322
"""A failed promotion still finalizes the primary slots with
324
- success=False; the tier corrects its own verdict.
325
- """
323
+ success=False; the tier corrects its own verdict."""
324
from unittest.mock import patch
325
326
from vllm.v1.kv_offload.tiering.base import JobResult
@@ -1093,8 +1091,7 @@ class TestTieringOffloadingManager:
1091
1092
def test_on_new_request_lifecycle(self, manager_setup):
1093
"""Policy defaults to CHUNK_LEVEL, escalates when a tier requests it,
1096
- and is cleaned up on on_request_finished.
1097
- """
1094
+ and is cleaned up on on_request_finished."""
1095
# Default: all tiers return CHUNK_LEVEL
1096
ctx = ReqContext(req_id="req_policy_lifecycle")
1097
result = self.manager.on_new_request(ctx)
@@ -1171,8 +1168,7 @@ class TestTieringOffloadingManager:
1168
1169
def _make_request_level_request(self, req_id: str) -> ReqContext:
1170
"""Start a request for which tier1 asks for request-level offloading,
1174
- with tier1's submit_store wrapped so the cascade can be observed.
1175
- """
1171
+ with tier1's submit_store wrapped so the cascade can be observed."""
1172
self.secondary_tier1.on_new_request = lambda req_context: (
1173
RequestOffloadingContext(policy=OffloadPolicy.REQUEST_LEVEL)
1174
)
@@ -1194,8 +1190,7 @@ class TestTieringOffloadingManager:
1190
def test_cascade_rejects_retry_from_primary(self, manager_setup):
1191
"""RETRY would be parked with no guarantee of ever draining, so the
1192
cascade refuses it. No real primary tier returns it, so this is the one
1197
- disposition that has to be forced.
1198
- """
1193
+ disposition that has to be forced."""
1194
keys = to_keys(range(3))
1195
self._start_request()
1196
assert self.manager.prepare_store(keys, _CTX) is not None
@@ -1210,8 +1205,7 @@ class TestTieringOffloadingManager:
1205
1206
def _start_in_flight_primary_write(self, keys: list[OffloadKey]) -> ReqContext:
1207
"""Leave a GPU->primary write for `keys` open, so they look present to
1213
- prepare_store but are not yet readable.
1214
- """
1208
+ prepare_store but are not yet readable."""
1209
writer_ctx = ReqContext(req_id="req_writer")
1210
self._start_request(writer_ctx)
1211
assert self.manager.prepare_store(keys, writer_ctx) is not None
@@ -1220,8 +1214,7 @@ class TestTieringOffloadingManager:
1214
def test_cascade_defers_keys_whose_primary_write_is_in_flight(self, manager_setup):
1215
"""A key another request is still writing must reach the peer once the
1216
write lands, not be dropped: prepare_store already counts it as stored
1223
- and the scheduler advances past its chunk, so nothing re-offers it.
1224
- """
1217
+ and the scheduler advances past its chunk, so nothing re-offers it."""
1218
keys = to_keys(range(3))
1219
writer_ctx = self._start_in_flight_primary_write(keys)
1220
@@ -1238,8 +1231,7 @@ class TestTieringOffloadingManager:
1231
1232
def test_deferred_cascade_holds_request_from_finalization(self, manager_setup):
1233
"""A request that finishes with keys still deferred must stay alive, or
1241
- its tiers are torn down before the peer is ever served.
1242
- """
1234
+ its tiers are torn down before the peer is ever served."""
1235
keys = to_keys(range(3))
1236
writer_ctx = self._start_in_flight_primary_write(keys)
1237
@@ -1262,8 +1254,7 @@ class TestTieringOffloadingManager:
1254
self, manager_setup
1255
):
1256
"""A failed write frees the chunk, so the deferred key resolves to MISS
1265
- and the request finalizes instead of parking forever.
1266
- """
1257
+ and the request finalizes instead of parking forever."""
1258
keys = to_keys(range(3))
1259
writer_ctx = self._start_in_flight_primary_write(keys)
1260
@@ -1283,8 +1274,7 @@ class TestTieringOffloadingManager:
1274
def test_reset_cache_clears_orchestrator_state(self, manager_setup):
1275
"""reset_cache wipes every kind of orchestrator state and resets
1276
primary tier; pending submissions are dropped without being sent
1286
- to the secondary tier. Active request state is retained.
1287
- """
1277
+ to the secondary tier. Active request state is retained."""
1278
# Cascade — populates primary chunks and leaves cascade jobs
1279
# in _jobs (the synchronous example tier has already
1280
# queued completions); reset_cache's drain loop will pick them up.
@@ -1376,8 +1366,7 @@ class TestTieringOffloadingManager:
1366
self, manager_setup, load_tier_filter
1367
):
1368
"""Filter excluding secondary medium returns MISS from secondaries
1379
- even when they hold the chunk; primary is unaffected.
1380
- """
1369
+ even when they hold the chunk; primary is unaffected."""
1370
chunks = to_keys(range(2))
1371
# Put one chunk in primary, one only in secondary
1372
self._start_request()
tests/v1/logits_processors/test_correctness.py
+1
-2
@@ -1344,8 +1344,7 @@ def test_thinking_budget_invalid_budget_rejected(invalid_budget):
1344
1345
def test_thinking_budget_long_thinking_section_end_marker_found_at_correct_index():
1346
"""Test thinking budget enforced for a long thinking run,
1347
- then a natural end marker.
1348
- """
1347
+ then a natural end marker."""
1348
h = ThinkingBudgetStateHolder(
1349
MockReasoningConfig(), 8, 0, torch.device("cpu"), False
1350
)
tests/v1/logits_processors/utils.py
+2
-4
@@ -138,8 +138,7 @@ class EntryPoints(list):
138
139
class DummyPerReqLogitsProcessor:
140
"""The request-level logits processor masks out all logits except the
141
- token id identified by `target_token`
142
- """
141
+ token id identified by `target_token`"""
142
143
def __init__(self, target_token: int) -> None:
144
"""Specify `target_token`."""
@@ -158,8 +157,7 @@ class DummyPerReqLogitsProcessor:
157
158
class WrappedPerReqLogitsProcessor(AdapterLogitsProcessor):
159
"""Example of wrapping a fake request-level logit processor to create a
161
- batch-level logits processor
162
- """
160
+ batch-level logits processor"""
161
162
def is_argmax_invariant(self) -> bool:
163
return False
tests/v1/metrics/test_perf_metrics.py
+1
-2
@@ -1241,8 +1241,7 @@ def test_mla_per_gpu_with_pipeline_parallelism():
1241
1242
def test_mla_model_metrics_excludes_standard_attention():
1243
"""Test that ModelMetrics uses MLAAttentionMetrics, not AttentionMetrics,
1244
- for DeepSeek MLA models.
1245
- """
1244
+ for DeepSeek MLA models."""
1245
hf_config = DeepseekV3Config(
1246
hidden_size=7168,
1247
num_attention_heads=128,
tests/v1/metrics/test_ray_metrics.py
+7
-14
@@ -45,8 +45,7 @@ def test_engine_log_metrics_ray(
45
max_tokens: int,
46
) -> None:
47
"""Simple smoke test, verifying this can be used without exceptions.
48
- Need to start a Ray cluster in order to verify outputs.
49
- """
48
+ Need to start a Ray cluster in order to verify outputs."""
49
50
@ray.remote(num_gpus=1)
51
class EngineTestActor:
@@ -120,8 +119,7 @@ def test_sanitized_opentelemetry_name():
119
def _install_mock_metric(wrapper: RayPrometheusMetric) -> MagicMock:
120
"""Swap the wrapper's underlying Ray metric for a MagicMock while
121
preserving the real metric's ``_tag_keys`` (labels() reads them to
123
- validate arity).
124
- """
122
+ validate arity)."""
123
real_metric = wrapper.metric
124
mock = MagicMock()
125
mock._tag_keys = real_metric._tag_keys
@@ -131,8 +129,7 @@ def _install_mock_metric(wrapper: RayPrometheusMetric) -> MagicMock:
129
130
def test_ray_counter_labels_returns_independent_children():
131
"""RayCounterWrapper.labels() must return distinct labeled children that
134
- each carry their own tag set.
135
- """
132
+ each carry their own tag set."""
133
base = RayCounterWrapper(
134
name="vllm_test_finish_reason",
135
documentation="",
@@ -152,8 +149,7 @@ def test_ray_counter_labels_returns_independent_children():
149
150
def test_ray_counter_inc_forwards_per_child_tags():
151
""".inc() on a labeled counter must forward that child's tags to the
155
- underlying Ray metric (not rely on a shared set_default_tags).
156
- """
152
+ underlying Ray metric (not rely on a shared set_default_tags)."""
153
wrapper = RayCounterWrapper(
154
name="vllm_test_counter_tag_forward",
155
documentation="",
@@ -218,8 +214,7 @@ def test_ray_histogram_labels_returns_independent_children_and_forwards_tags():
214
def test_ray_counter_labels_accepts_non_string_label_values():
215
"""RayPrometheusStatLogger passes ``str(idx)`` for engine indexes; this
216
covers the coercion path for any caller that passes a non-string label
221
- value positionally.
222
- """
217
+ value positionally."""
218
wrapper = RayCounterWrapper(
219
name="vllm_test_nonstr_label",
220
documentation="",
@@ -242,8 +237,7 @@ def test_ray_counter_labels_arity_validation():
237
238
def test_unlabeled_inc_carries_replica_id():
239
"""Recording on an unlabeled metric must still pass ReplicaId — it's a
245
- declared tag_key and Ray rejects updates that omit any declared key.
246
- """
240
+ declared tag_key and Ray rejects updates that omit any declared key."""
241
wrapper = RayCounterWrapper(
242
name="vllm_test_unlabeled_replica_id",
243
documentation="",
@@ -256,8 +250,7 @@ def test_unlabeled_inc_carries_replica_id():
250
251
def test_double_labels_raises():
252
"""labels() on an already-labeled child should raise, mirroring the
259
- prometheus_client contract.
260
- """
253
+ prometheus_client contract."""
254
wrapper = RayCounterWrapper(
255
name="vllm_test_double_labels",
256
documentation="",
tests/v1/sample/test_batched_count_greater_than.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Test that batched_count_greater_than does not trigger 0/1 specialization
4
-recompiles when batch_size varies.
5
-"""
4
+recompiles when batch_size varies."""
5
6
import torch
7
tests/v1/sample/test_logprobs.py
+1
-2
@@ -573,8 +573,7 @@ def test_logprobs_mode(logprobs_mode: LogprobsMode):
573
def test_prompt_logprobs_mode():
574
"""prompt_logprobs must respect logprobs_mode: *_logits and *_logprobs
575
must return different values. Prompt tokens skip sampling processors,
576
- so processed_* == raw_* on the prompt side.
577
- """
576
+ so processed_* == raw_* on the prompt side."""
577
from vllm import LLM
578
579
values: dict[str, float] = {}
tests/v1/sample/test_rejection_sampler.py
+1
-2
@@ -54,8 +54,7 @@ def create_logits_tensor(
54
token_idx_to_override: int | None = None,
55
) -> torch.Tensor:
56
"""Helper function to create logits tensor that
57
- will produce desired token ids on argmax
58
- """
57
+ will produce desired token ids on argmax"""
58
token_ids = [tokens[:-1] for tokens in output_token_ids]
59
num_total_tokens = sum(len(tokens) for tokens in token_ids)
60
logits = torch.full((num_total_tokens, vocab_size), -100.0, device=DEVICE_TYPE)
tests/v1/sample/test_topk_topp_sampler.py
+1
-2
@@ -884,8 +884,7 @@ class TestFlashInferTopkToppRobustness:
884
885
def _make_logits(self, pattern: str) -> torch.Tensor:
886
"""Build (BATCH, VOCAB) logits with `pattern` applied to row 0
887
- (rows 1..B-1 stay clean so we can detect cross-row corruption).
888
- """
887
+ (rows 1..B-1 stay clean so we can detect cross-row corruption)."""
888
logits = (
889
torch.randn(
890
self.BATCH,
tests/v1/sample/utils.py
+1
-2
@@ -204,8 +204,7 @@ def fake_update_logitsprocs_state(
204
batch_update: BatchUpdate | None,
205
) -> None:
206
"""Imitate logits processors persistent batch state update
207
- in engine core
208
- """
207
+ in engine core"""
208
for logitproc in test_fakes.get_logitsprocs():
209
logitproc.update_state(batch_update)
210
holder = test_fakes.sampling_metadata.thinking_budget_state_holder
tests/v1/simple_kv_offload/test_kv_events.py
+3
-6
@@ -67,8 +67,7 @@ def _make_mixed_kv_cache_config(
67
mamba_block_size: int = BLOCK_SIZE,
68
) -> KVCacheConfig:
69
"""Build a KVCacheConfig with a FullAttention group plus optional
70
- SlidingWindow and Mamba groups for per-group metadata tests.
71
- """
70
+ SlidingWindow and Mamba groups for per-group metadata tests."""
71
register_all_kvcache_specs(vllm_config=None)
72
groups = []
73
tensors = []
@@ -239,8 +238,7 @@ def test_events_disabled_no_events() -> None:
238
# ---------------------------------------------------------------------------
239
def test_block_stored_per_group_metadata_full_attention() -> None:
240
"""BlockStored carries medium, group_idx, kind, sliding_window, block_size,
242
- and the correct block hash.
243
- """
241
+ and the correct block hash."""
242
fix = make_events_scheduler()
243
sched = fix.scheduler
244
assert sched.kv_event_medium == MEDIUM_CPU
@@ -640,8 +638,7 @@ def test_mamba_block_size_not_scaled() -> None:
638
def test_multi_group_fa_block_stored_group_idx() -> None:
639
"""Two distinct groups (FA + SW): each BlockStored carries its group_idx
640
and kind. HybridKVCacheCoordinator requires >=2 distinct spec groups, so
643
- we use FA (group 0) + SlidingWindow (group 1).
644
- """
641
+ we use FA (group 0) + SlidingWindow (group 1)."""
642
kv_cfg = _make_mixed_kv_cache_config(num_blocks=16, sliding_window=32)
643
fix = make_events_scheduler(
644
num_cpu_blocks=8,
tests/v1/simple_kv_offload/test_scheduler.py
+6
-12
@@ -1170,8 +1170,7 @@ def test_touched_blocks_survive_eviction() -> None:
1170
# ---------------------------------------------------------------------------
1171
def test_preemption_no_cpu_block_leak() -> None:
1172
"""request_finished during in-flight load defers cleanup;
1173
- completes after load done.
1174
- """
1173
+ completes after load done."""
1174
fix = make_scheduler(num_cpu_blocks=8, num_gpu_blocks=16, lazy=False)
1175
sched = fix.scheduler
1176
@@ -1266,8 +1265,7 @@ def test_eager_store_preemption_cleanup() -> None:
1265
# ---------------------------------------------------------------------------
1266
def test_inflight_finish_deferred_cleanup() -> None:
1267
"""Store, then start a load, request_finished defers,
1269
- load completion fires cleanup.
1270
- """
1268
+ load completion fires cleanup."""
1269
fix = make_scheduler(num_cpu_blocks=8, num_gpu_blocks=16, lazy=False)
1270
sched = fix.scheduler
1271
@@ -1401,8 +1399,7 @@ def test_chunked_prefill_reads_live_block_ids() -> None:
1399
"""With chunked prefill, block IDs accumulate across scheduler steps.
1400
_prepare_eager_store_specs reads block IDs from scheduler_output via
1401
yield_req_data, so the store should reflect the updated (larger) block
1404
- list, not a stale snapshot.
1405
- """
1402
+ list, not a stale snapshot."""
1403
fix = make_scheduler(num_cpu_blocks=8, num_gpu_blocks=16, lazy=False)
1404
sched = fix.scheduler
1405
@@ -1973,8 +1970,7 @@ def test_cp_eager_store_and_load_roundtrip(
1970
) -> None:
1971
"""With CP enabled, store blocks to CPU and reload them for a new request
1972
with matching tokens. Verifies that hash matching and transfer-pair
1976
- construction work with the virtual block size.
1977
- """
1973
+ construction work with the virtual block size."""
1974
fix = _make_cp_scheduler(
1975
dcp_world_size=dcp_world_size,
1976
pcp_world_size=pcp_world_size,
@@ -2118,8 +2114,7 @@ def test_cp_effective_block_size_store_and_load(
2114
@pytest.mark.parametrize("cp_world_size", [1, 2, 4])
2115
def test_cp_lazy_target_blocks_scaling(cp_world_size: int) -> None:
2116
"""_estimate_lazy_target_blocks returns fewer blocks when cp_world_size > 1
2121
- because each virtual block covers more tokens.
2122
- """
2117
+ because each virtual block covers more tokens."""
2118
kv_cache_config = _make_kv_cache_config(num_blocks=16)
2119
max_batched = 64
2120
@@ -2811,8 +2806,7 @@ def test_finished_eager_store_recovers_nulled_window_tail() -> None:
2806
"""A sliding-window group nulls pages that left the window before the
2807
connector sees the finished request's block table, while the GPU keeps
2808
them hashed in its free queue. The eager store must copy those pages, or
2814
- the CPU lookup (which needs the whole window) misses every time.
2815
- """
2809
+ the CPU lookup (which needs the whole window) misses every time."""
2810
fix = make_scheduler(num_cpu_blocks=16, num_gpu_blocks=32, num_groups=2, lazy=False)
2811
sched = fix.scheduler
2812
gpu_pool = fix.gpu_block_pool
tests/v1/spec_decode/test_backup_token_async_spec.py
+1
-2
@@ -131,8 +131,7 @@ class TestBackupTokenAsyncSpec:
131
132
def test_buggy_code_was_always_off_by_one(self):
133
"""The original code used seq_len as index, which is always one past
134
- the end of output_token_ids even without async inflation.
135
- """
134
+ the end of output_token_ids even without async inflation."""
135
req_ids = ["r0"]
136
requests = {"r0": _FakeRequest([0, 1, 2], [1000, 1001])}
137
batch = _FakeInputBatch(req_ids, [5])
tests/v1/spec_decode/test_eagle_draft_attn_metadata.py
+3
-6
@@ -105,8 +105,7 @@ def test_build_draft_attn_metadata_sets_seq_lens_cpu_upper_bound():
105
"""The fix: every per-step ``CommonAttentionMetadata`` carries a non-None
106
``seq_lens_cpu_upper_bound`` derived from the target-side upper bound plus
107
the current draft-step offset. Padded entries are zeroed (matching the
108
- main model runner's convention).
109
- """
108
+ main model runner's convention)."""
109
fake = _make_fake_speculator()
110
base = torch.tensor([100, 200, 300, 0], dtype=torch.int32)
111
@@ -127,8 +126,7 @@ def test_build_draft_attn_metadata_sets_seq_lens_cpu_upper_bound():
126
127
def test_build_draft_attn_metadata_zeroes_padded_upper_bound_tail():
128
"""The padded tail of the upper-bound tensor is zeroed, so it stays a
130
- valid tensor of length ``num_reqs_padded`` regardless of padding.
131
- """
129
+ valid tensor of length ``num_reqs_padded`` regardless of padding."""
130
fake = _make_fake_speculator()
131
base = torch.zeros(2, dtype=torch.int32)
132
@@ -143,8 +141,7 @@ def test_build_draft_attn_metadata_zeroes_padded_upper_bound_tail():
141
142
def test_build_draft_attn_metadata_clamps_to_max_model_len():
143
"""The per-request upper bound (target bound + step) is clamped to the
146
- model length so it never exceeds the allocated KV range.
147
- """
144
+ model length so it never exceeds the allocated KV range."""
145
fake = _make_fake_speculator(max_model_len=1024)
146
base = torch.tensor([1023, 500], dtype=torch.int32)
147
tests/v1/spec_decode/test_eagle_step_kernel.py
+1
-2
@@ -132,8 +132,7 @@ def test_eagle_step_slot_mapping_kernel_exceeds_max():
132
133
def test_eagle_step_slot_mapping_kernel_cudagraph_padding():
134
"""Test that padding threads write PADDING_SLOT_ID when
135
- input_batch_size > batch_size (cudagraph padding).
136
- """
135
+ input_batch_size > batch_size (cudagraph padding)."""
136
device = torch.device(DEVICE_TYPE)
137
batch_size = 4
138
input_batch_size = 8
tests/v1/spec_decode/test_llm_base_proposer.py
+2
-4
@@ -69,8 +69,7 @@ def _make_kv_cache_config(layer_names: set[str]) -> SimpleNamespace:
69
70
def test_block_size_uses_kernel_block_size(monkeypatch: pytest.MonkeyPatch):
71
"""The proposer's slot-mapping math runs against the kernel-granularity
72
- block table, so block_size must come from kernel_block_sizes.
73
- """
72
+ block table, so block_size must come from kernel_block_sizes."""
73
layer_names = {"draft.0.self_attn.attn"}
74
proposer = _make_proposer(monkeypatch, layer_names)
75
@@ -98,8 +97,7 @@ def test_block_size_falls_back_to_kv_cache_spec(monkeypatch: pytest.MonkeyPatch)
97
98
def test_draft_layer_iteration_is_deterministic(monkeypatch: pytest.MonkeyPatch):
99
"""_draft_attn_layer_names is a set; the attention groups built from it
101
- must not depend on its (process-random) iteration order.
102
- """
100
+ must not depend on its (process-random) iteration order."""
101
layer_names = {"draft.c.attn", "draft.a.attn", "draft.b.attn"}
102
expected_order = sorted(layer_names)
103
tests/v1/spec_decode/test_max_len.py
+1
-2
@@ -93,8 +93,7 @@ def test_eagle_max_len(
93
@pytest.mark.parametrize("spec_max_model_len", [80, 150])
94
def test_mtp_speculative_config_max_model_len(spec_max_model_len: int):
95
"""Regression test for #41456: max_model_len in speculative config
96
- should be respected for the draft model.
97
- """
96
+ should be respected for the draft model."""
97
model_config = ModelConfig(
98
model="XiaomiMiMo/MiMo-7B-Base",
99
runner="generate",
tests/v1/structured_output/test_validation.py
+4
-8
@@ -29,8 +29,7 @@ class _StubModelConfig:
29
def test_structured_outputs_rejected_for_diffusion_models():
30
"""Diffusion LLMs denoise the canvas in parallel, which is incompatible
31
with the token-by-token grammar FSM. The request must fail with a clear
32
- validation error instead of an FSM rejection mid-generation (#45436).
33
- """
32
+ validation error instead of an FSM rejection mid-generation (#45436)."""
33
params = SamplingParams(
34
structured_outputs=StructuredOutputsParams(json=JSON_SCHEMA)
35
)
@@ -63,8 +62,7 @@ def test_degenerate_structured_outputs_rejected(structured_outputs, match):
62
"""json_object=False and an empty json schema pass the `is not None`
63
exclusivity check but resolve to no structured-output key, so they must be
64
rejected at request validation (-> 400) instead of reaching and crashing
66
- the engine.
67
- """
65
+ the engine."""
66
params = SamplingParams(structured_outputs=structured_outputs)
67
with pytest.raises(VLLMValidationError, match=match):
68
params._validate_structured_outputs(
@@ -87,8 +85,7 @@ def test_regex_with_nul_byte_rejected(regex):
85
handled by xgrammar's native regex converter. It must be rejected at request
86
validation in every backend mode (a clean 400), instead of reaching that
87
native code or silently falling back to another backend in the default
90
- 'auto' mode.
91
- """
88
+ 'auto' mode."""
89
params = SamplingParams(structured_outputs=StructuredOutputsParams(regex=regex))
90
91
# Rejected before backend selection, so it is a 400 even in 'auto' mode
@@ -127,8 +124,7 @@ INVALID_JSON_SCHEMA = {"type": "object", "properties": {"name": {"type": "str"}}
124
)
125
def test_unsupported_grammar_is_a_client_error(backend, structured_outputs):
126
"""Only `VLLMClientError` survives `AsyncLLM.generate` untouched; anything else
130
- is wrapped in `EngineGenerateError` and served as a 500 instead of a 400.
131
- """
127
+ is wrapped in `EngineGenerateError` and served as a 500 instead of a 400."""
128
params = SamplingParams(structured_outputs=structured_outputs)
129
with pytest.raises(VLLMClientError):
130
params._validate_structured_outputs(
tests/v1/test_outputs.py
+4
-8
@@ -46,8 +46,7 @@ def test_logprobs_tensors_cat():
46
def test_logprobs_tensors_tolists_with_tensor_boundaries():
47
"""Adaptive verification hands over the request boundaries as a tensor
48
(they only exist on device); tolists() must materialize it as a plain
49
- list so slice_request splits requests correctly.
50
- """
49
+ list so slice_request splits requests correctly."""
50
tensors = LogprobsTensors(
51
torch.tensor([[1, 2], [3, 4], [5, 6]]),
52
torch.tensor([[0.1, 0.2], [0.3, 0.4], [0.5, 0.6]]),
@@ -86,8 +85,7 @@ def test_sampling_mask_lists_to_nested_list():
85
def test_sampling_mask_tensors_match_finite_support(max_num_kept):
86
"""Whatever its size (empty, one, around the compact width, beyond the
87
cap, the whole vocab), a sampled row's mask is exactly the ascending set
89
- of its finite logits; rows that sampled nothing are empty.
90
- """
88
+ of its finite logits; rows that sampled nothing are empty."""
89
from vllm.v1.worker.gpu.sample.output import MAX_COMPACT_SUPPORT
90
91
vocab_size = 20_001
@@ -114,8 +112,7 @@ def test_sampling_mask_tensors_match_finite_support(max_num_kept):
112
def test_sampling_mask_matches_processed_top_k_top_p_support():
113
"""The mask must exactly mirror whatever support `apply_top_k_top_p`
114
(the real logits-processing function used by the sampler) actually
117
- produces, whatever backend implements it.
118
- """
115
+ produces, whatever backend implements it."""
116
processed_logits = apply_top_k_top_p(
117
logits=torch.tensor(
118
[[6.0, 5.0, 4.0, 4.0, 4.0, 2.0, 1.0, 0.0]], device=DEVICE_TYPE
@@ -141,8 +138,7 @@ def test_sampling_mask_matches_processed_top_k_top_p_support():
138
def test_sampling_mask_preserves_top_k_boundary_ties():
139
"""When the kept support is wider than `max_num_kept` (e.g. a top-k
140
boundary tie keeps more than k logits), the mask must fall back to the
144
- exact bitmask instead of silently truncating to `max_num_kept` ids.
145
- """
141
+ exact bitmask instead of silently truncating to `max_num_kept` ids."""
142
processed_logits = torch.tensor(
143
[[6.0, 5.0, 4.0, 4.0, 4.0, float("-inf"), float("-inf"), float("-inf")]],
144
device=DEVICE_TYPE,
tests/v1/test_serial_utils.py
+1
-2
@@ -427,8 +427,7 @@ def _logprobs_outputs(num_reqs: int, num_prompt_tokens: int):
427
"""An EngineCoreOutputs carrying prompt logprobs, as the engine core sends
428
it: many requests, each with per-token tensors small enough that pyzmq
429
copies their frames, while the accumulated payload frame is large enough
430
- that pyzmq sends it zero-copy.
431
- """
430
+ that pyzmq sends it zero-copy."""
431
from vllm.v1.engine import EngineCoreOutput, EngineCoreOutputs
432
from vllm.v1.outputs import LogprobsTensors
433
tests/v1/worker/test_dsv4_packed_zeroer_geometry.py
+1
-2
@@ -101,8 +101,7 @@ def test_packed_dsv4_zeroer_zeroes_only_each_layers_page():
101
def test_overlaid_zeroer_dedups_segments_with_max_span():
102
"""Two groups overlay one allocation; the zeroer must emit one segment per distinct
103
byte offset, spanning the widest overlaid page, so a newly allocated block is fully
104
- zeroed no matter which group owns it.
105
- """
104
+ zeroed no matter which group owns it."""
105
from unittest.mock import MagicMock
106
107
from vllm.v1.core.kv_cache_utils import get_kv_cache_config_from_groups
tests/v1/worker/test_encoder_runner.py
+5
-10
@@ -97,8 +97,7 @@ def test_draft_lookahead_uses_boundary_feature_when_cached():
97
"""The drafter's +1 look-ahead can reach the feature at offset ==
98
processed_end (the next chunk). When its encoder output is already cached
99
(the scheduler encoded it ahead), it is used for the look-ahead position
100
- rather than ignored.
101
- """
100
+ rather than ignored."""
101
f0 = _feature("h0", offset=0, length=8)
102
f1 = _feature("h1", offset=8, length=8) # starts exactly at processed_end
103
runner = _make_runner([f0, f1], cached=[f0, f1])
@@ -115,8 +114,7 @@ def test_draft_lookahead_uses_boundary_feature_when_cached():
114
def test_draft_lookahead_tolerates_missing_boundary_feature():
115
"""When the +1 look-ahead feature past the processed boundary is not yet
116
encoded, fall back to the token embedding (the draft token is verified by
118
- the target) instead of raising.
119
- """
117
+ the target) instead of raising."""
118
f0 = _feature("h0", offset=0, length=8)
119
f1 = _feature("h1", offset=8, length=8) # boundary feature, not cached
120
runner = _make_runner([f0, f1], cached=[f0])
@@ -133,8 +131,7 @@ def test_draft_lookahead_tolerates_missing_boundary_feature():
131
def test_draft_lookahead_raises_on_interior_miss():
132
"""A miss for a feature within the processed range (not the look-ahead
133
boundary) is a real invariant violation and must fail loudly, even on the
136
- drafter path.
137
- """
134
+ drafter path."""
135
f0 = _feature("h0", offset=0, length=8) # interior, within processed range
136
runner = _make_runner([f0], cached=[])
137
@@ -144,8 +141,7 @@ def test_draft_lookahead_raises_on_interior_miss():
141
142
def test_target_path_raises_on_encoder_cache_miss():
143
"""On the target path (no look-ahead) a miss is a real invariant
147
- violation and must fail loudly.
148
- """
144
+ violation and must fail loudly."""
145
f0 = _feature("h0", offset=0, length=8)
146
runner = _make_runner([f0], cached=[])
147
@@ -156,8 +152,7 @@ def test_target_path_raises_on_encoder_cache_miss():
152
@pytest.mark.parametrize("draft_lookahead", [0, 1])
153
def test_multi_request_batch_gathers_per_request(draft_lookahead):
154
"""Two prefilling requests in one batch: per-request query bounds must be
159
- indexed by request, not applied as whole arrays.
160
- """
155
+ indexed by request, not applied as whole arrays."""
156
a0 = _feature("a0", offset=0, length=8)
157
b0 = _feature("b0", offset=0, length=8)
158
cache = EncoderCache()
tests/v1/worker/test_gpu_bad_words.py
+3
-6
@@ -73,8 +73,7 @@ def _apply(bad_words_token_ids: list[list[int]]) -> torch.Tensor:
73
74
def test_v2_bad_words_prefix_inside_draft_tokens():
75
"""A prefix matching entirely within the draft tokens must mask the bad
76
- word's last token at the draft position that completes the prefix.
77
- """
76
+ word's last token at the draft position that completes the prefix."""
77
out = _apply([[12, 13, 40]])
78
expected = torch.zeros_like(out)
79
expected[2, 40] = -float("inf")
@@ -83,8 +82,7 @@ def test_v2_bad_words_prefix_inside_draft_tokens():
82
83
def test_v2_bad_words_prefix_spanning_committed_and_draft_tokens():
84
"""A prefix spanning the committed/draft boundary must mask at the row
86
- where the prefix completes, not one draft position later.
87
- """
85
+ where the prefix completes, not one draft position later."""
86
out = _apply([[11, 12, 30]])
87
expected = torch.zeros_like(out)
88
expected[1, 30] = -float("inf")
@@ -93,8 +91,7 @@ def test_v2_bad_words_prefix_spanning_committed_and_draft_tokens():
91
92
def test_v2_bad_words_no_spurious_match_from_last_committed_token():
93
"""The last committed token must not be double-counted as the first draft
96
- token; [11, 11] never occurs in output [10, 11] + drafts [12, 13].
97
- """
94
+ token; [11, 11] never occurs in output [10, 11] + drafts [12, 13]."""
95
out = _apply([[11, 11, 50]])
96
expected = torch.zeros_like(out)
97
torch.testing.assert_close(out, expected)
tests/v1/worker/test_gpu_batch_shard.py
+9
-18
@@ -43,8 +43,7 @@ def _make_batch(
43
slot_pool: np.ndarray | None = None,
44
) -> InputBatch:
45
"""Consistent batch with random unique request slots, 1 + k_i logits
46
- rows per request at the tail of each query segment.
47
- """
46
+ rows per request at the tail of each query segment."""
47
if slot_pool is None:
48
slot_pool = np.arange(max_num_reqs)
49
slots = rng.choice(slot_pool, size=num_reqs, replace=False)
@@ -142,8 +141,7 @@ def _owned_rows(cu: np.ndarray, owned: np.ndarray) -> np.ndarray:
141
def test_local_batch_partition(tp_size: int, seed: int):
142
"""Local sub-batches partition the batch by owner, preserve batch order
143
within an owner, and carry exactly the owned requests' entries of every
145
- per-request and per-row array.
146
- """
144
+ per-request and per-row array."""
145
rng = np.random.default_rng(seed)
146
max_num_reqs = 64
147
batch = _make_batch(rng, num_reqs=23, max_num_reqs=max_num_reqs, max_spec=3)
@@ -225,8 +223,7 @@ def test_local_batch_partition(tp_size: int, seed: int):
223
def test_all_to_all_reassembly_simulated(tp_size: int):
224
"""Vocab shards computed from owner-sorted hidden states and routed
225
through the simulated all-to-all reassemble into exactly the full-vocab
228
- logits of each rank's owned rows.
229
- """
226
+ logits of each rank's owned rows."""
227
rng = np.random.default_rng(7)
228
max_num_reqs = 32
229
batch = _make_batch(rng, num_reqs=11, max_num_reqs=max_num_reqs, max_spec=4)
@@ -264,8 +261,7 @@ def test_all_to_all_reassembly_simulated(tp_size: int):
261
@requires_cuda
262
def test_shard_no_spec():
263
"""Batches without draft tokens (one logits row per request) degenerate
267
- cleanly: rows mirror requests.
268
- """
264
+ cleanly: rows mirror requests."""
265
rng = np.random.default_rng(11)
266
tp_size = 4
267
max_num_reqs = 32
@@ -284,8 +280,7 @@ def test_shard_no_spec():
280
@pytest.mark.parametrize("tp_size", [2, 4])
281
def test_shard_grammar_output(tp_size: int):
282
"""The grammar filter keeps exactly the owned requests' bitmask rows, in
287
- grammar order, and the per-rank pieces partition the global bitmask.
288
- """
283
+ grammar order, and the per-rank pieces partition the global bitmask."""
284
rng = np.random.default_rng(5)
285
max_num_reqs = 32
286
num_reqs = 12
@@ -340,8 +335,7 @@ def test_shard_grammar_output(tp_size: int):
335
@pytest.mark.parametrize("tp_size", [2, 4])
336
def test_gather_src_indices_round_trip(tp_size: int):
337
"""Padded per-rank result blocks indexed by gathered_src_indices restore
343
- batch order, including when some rank owns zero requests.
344
- """
338
+ batch order, including when some rank owns zero requests."""
339
rng = np.random.default_rng(3)
340
max_num_reqs = 40
341
all_slots = np.arange(max_num_reqs)
@@ -376,8 +370,7 @@ def test_gather_src_indices_round_trip(tp_size: int):
370
def test_gather_sampler_output_kernels(tp_size: int):
371
"""The fused pack/unpack kernels round-trip per-rank sampler results
372
into batch order: token ids zero-filled past the local width, counts
379
- cast back to int32, identical on every rank.
380
- """
373
+ cast back to int32, identical on every rank."""
374
from dataclasses import replace as dc_replace
375
376
from vllm.v1.worker.gpu.sample.output import SamplerOutput
@@ -472,8 +465,7 @@ def test_gather_sampler_output_kernels(tp_size: int):
465
def test_gather_sampler_output_logprobs_and_nans():
466
"""num_nans is reduced per request and gathered; LogprobsTensors are
467
packed into fixed per-request blocks, width-aligned across ranks (pad
475
- and truncate paths), and restored to global row order.
476
- """
468
+ and truncate paths), and restored to global row order."""
469
from dataclasses import replace as dc_replace
470
471
from vllm.v1.outputs import LogprobsTensors
@@ -606,8 +598,7 @@ def test_gather_sampler_output_logprobs_and_nans():
598
def test_finish_requests_frees_slots_in_sorted_order():
599
"""Request slots must be freed in the same order on every TP rank:
600
ownership derives from slot indices, and `finished_req_ids` is a set
609
- whose iteration order is per-process hash-randomized.
610
- """
601
+ whose iteration order is per-process hash-randomized."""
602
from vllm.v1.worker.gpu.model_runner import GPUModelRunner
603
604
removed: list[str] = []
tests/v1/worker/test_gpu_block_table.py
+2
-4
@@ -217,8 +217,7 @@ def test_v1_block_table_move_row_clears_vacated_row():
217
not keep stale block ids. Padded dummy-run batches dereference stale rows
218
as mamba state slots (bypassing the NULL_BLOCK_ID fill of real decode
219
padding) and write state in place there — corrupting the blocks' new
220
- owner once they are reallocated, e.g. to an in-flight NIXL load.
221
- """
220
+ owner once they are reallocated, e.g. to an in-flight NIXL load."""
221
from vllm.v1.worker.block_table import BlockTable
222
223
block_table = BlockTable(
@@ -250,8 +249,7 @@ def test_get_dummy_block_tables_returns_zeroed_rows():
249
PAD-filled, state indices are not), so stale rows would direct dummy
250
state writes at freed — possibly reallocated — blocks.
251
get_dummy_block_tables must hand out zeroed (null block) rows while
253
- preserving the persistent storage address for CUDA graphs.
254
- """
252
+ preserving the persistent storage address for CUDA graphs."""
253
device = torch.device("cuda")
254
block_tables = BlockTables(
255
block_sizes=[16],
tests/v1/worker/test_gpu_logit_bias.py
+1
-2
@@ -85,8 +85,7 @@ def test_v2_min_tokens_keeps_masking_when_other_candidates_remain():
85
86
def test_v2_min_tokens_mixed_batch_gates_restore_per_request():
87
"""CHECK_ALL_MASKED_ROWS is a batch-wide constexpr, so a mixed batch must
88
- still consult the per-request flag.
89
- """
88
+ still consult the per-request flag."""
89
out = _apply(_only_stop_token_left(2), structured=[True, False])
90
91
assert out[0, STOP_TOKEN] == 1.0
tests/v1/worker/test_gpu_model_runner.py
+2
-4
@@ -73,8 +73,7 @@ DEVICE_TYPE = current_platform.device_type
73
def _restore_default_dtype():
74
"""Several tests here set the process-wide default dtype to float16 and
75
previously leaked it, corrupting later float-sensitive tests in the same
76
- pytest process (torch.randn silently produced fp16).
77
- """
76
+ pytest process (torch.randn silently produced fp16)."""
77
old = torch.get_default_dtype()
78
yield
79
torch.set_default_dtype(old)
@@ -1454,8 +1453,7 @@ def test_v2_runner_snapshots_late_interleave_adjustment(monkeypatch):
1453
1454
def test_hybrid_block_table_initialization():
1455
"""Test hybrid block table with different kernel and kvcache_manager block
1457
- sizes.
1458
- """
1456
+ sizes."""
1457
from vllm.v1.worker.block_table import BlockTable
1458
1459
# Test configuration: kvcache_manager block size = 32,
tests/v1/worker/test_gpu_model_runner_mm_gather.py
+3
-6
@@ -62,8 +62,7 @@ def _gather(features, cached, *, num_scheduled, shift, num_computed=0):
62
def test_draft_shift_uses_boundary_feature_when_cached():
63
"""The drafter's +1 look-ahead reaches the feature at offset ==
64
processed_end; when it is already cached it is used for the look-ahead
65
- position rather than ignored.
66
- """
65
+ position rather than ignored."""
66
f0 = _feature("h0", offset=0, length=8)
67
f1 = _feature("h1", offset=8, length=8) # starts exactly at processed_end
68
mm_embeds, is_mm_embed = _gather([f0, f1], [f0, f1], num_scheduled=8, shift=1)
@@ -76,8 +75,7 @@ def test_draft_shift_uses_boundary_feature_when_cached():
75
76
def test_draft_shift_tolerates_missing_boundary_feature():
77
"""When the +1 look-ahead feature past the processed boundary is not yet
79
- encoded, fall back to the token embedding instead of raising.
80
- """
78
+ encoded, fall back to the token embedding instead of raising."""
79
f0 = _feature("h0", offset=0, length=8)
80
f1 = _feature("h1", offset=8, length=8) # boundary feature, not cached
81
mm_embeds, is_mm_embed = _gather([f0, f1], [f0], num_scheduled=8, shift=1)
@@ -89,8 +87,7 @@ def test_draft_shift_tolerates_missing_boundary_feature():
87
88
def test_draft_shift_raises_on_interior_miss():
89
"""A miss for a feature within the processed range (not the look-ahead
92
- boundary) is a real invariant violation, even on the drafter path.
93
- """
90
+ boundary) is a real invariant violation, even on the drafter path."""
91
f0 = _feature("h0", offset=0, length=8) # interior, within processed range
92
with pytest.raises(RuntimeError, match="Encoder cache miss"):
93
_gather([f0], [], num_scheduled=8, shift=1)
tests/v1/worker/test_gpu_model_runner_v2.py
+4
-8
@@ -219,8 +219,7 @@ def test_append_block_ids_rejects_write_past_row_capacity():
219
220
def _make_capture_runner(captured: bool) -> GPUModelRunner:
221
"""Minimal V2 runner for capture_model: fakes everything except the
222
- cudagraph_manager's needs_capture decision.
223
- """
222
+ cudagraph_manager's needs_capture decision."""
223
runner = GPUModelRunner.__new__(GPUModelRunner)
224
runner.model_state = SimpleNamespace(supports_mm_inputs=False)
225
runner.cudagraph_manager = SimpleNamespace(
@@ -246,8 +245,7 @@ def _make_capture_runner(captured: bool) -> GPUModelRunner:
245
def test_capture_model_locks_workspace_after_capture(monkeypatch):
246
"""A workspace resize after capture frees the buffer the captured graphs
247
baked in, so capture_model must lock the workspace before returning
249
- (https://github.com/vllm-project/vllm/issues/55336).
250
- """
248
+ (https://github.com/vllm-project/vllm/issues/55336)."""
249
runner = _make_capture_runner(captured=True)
250
monkeypatch.setattr(
251
model_runner_module, "freeze_gc_for_cudagraph_capture", contextlib.nullcontext
@@ -268,8 +266,7 @@ def test_capture_model_locks_workspace_after_capture(monkeypatch):
266
267
def test_capture_model_skips_lock_when_nothing_captured(monkeypatch):
268
"""With no graphs to capture (e.g. enforce_eager) there is nothing baked
271
- into the workspace, so the early return must not lock it.
272
- """
269
+ into the workspace, so the early return must not lock it."""
270
runner = _make_capture_runner(captured=False)
271
lock_calls = []
272
monkeypatch.setattr(
@@ -283,8 +280,7 @@ def test_capture_model_skips_lock_when_nothing_captured(monkeypatch):
280
def test_capture_model_profile_only_skips_lock(monkeypatch):
281
"""The memory-profiling capture pass runs before kernel warmup and the
282
real capture; locking there would stop the warmup from growing the
286
- workspace to its scheduler-realistic size.
287
- """
283
+ workspace to its scheduler-realistic size."""
284
runner = _make_capture_runner(captured=True)
285
monkeypatch.setattr(
286
model_runner_module, "freeze_gc_for_cudagraph_capture", contextlib.nullcontext
tests/v1/worker/test_gpu_model_runner_v2_cudagraph_profiling.py
+1
-2
@@ -82,8 +82,7 @@ def _make_profiling_runner(
82
83
class _FakePlatform:
84
"""Stands in for current_platform; the global graph pool is a class attr,
85
- matching vllm.platforms.Platform's lazy singleton.
86
- """
85
+ matching vllm.platforms.Platform's lazy singleton."""
86
87
_global_graph_pool: Any = GLOBAL_POOL
88
tests/v1/worker/test_gpu_profiler.py
+2
-4
@@ -120,8 +120,7 @@ def test_max_iterations(default_profiler_config):
120
def test_restart_after_max_iterations(default_profiler_config):
121
"""A start_profile after an auto-stop must actually restart, not be
122
silently ignored (regression test: auto-stop used to leave _active
123
- True forever, so start() always bailed out early).
124
- """
123
+ True forever, so start() always bailed out early)."""
124
default_profiler_config.max_iterations = 2
125
profiler = ConcreteWorkerProfiler(default_profiler_config)
126
@@ -332,8 +331,7 @@ class TestAnnotateProfile:
331
332
def test_profiler_entered_during_capture():
333
"""Profiler is used as a context manager in _warmup_and_capture,
335
- confirming it is active during the actual graph capture run.
336
- """
334
+ confirming it is active during the actual graph capture run."""
335
runner = MagicMock()
336
runner.compilation_config.cudagraph_num_of_warmups = 0
337
mock_profiler = MagicMock()
tests/v1/worker/test_gpu_rejection_sampler_i64.py
+1
-2
@@ -34,8 +34,7 @@ def _run(
34
) -> tuple[torch.Tensor, torch.Tensor]:
35
"""Run rejection_sample on a batch of uniform k=2 requests, with the
36
request under test at request index `roi_req` and draft-logits row
37
- `req_state_idx`. Returns that request's (sampled, num_sampled).
38
- """
37
+ `req_state_idx`. Returns that request's (sampled, num_sampled)."""
38
num_logits = num_reqs * LOGITS_PER_REQ
39
roi_row = roi_req * LOGITS_PER_REQ
40
tests/v1/worker/test_gpu_thinking_budget.py
+1
-2
@@ -288,8 +288,7 @@ def test_v2_thinking_budget_clamps_oversized_budget():
288
289
def test_v2_thinking_budget_continues_end_prefix_from_prompt():
290
"""A resumed prompt ending with a partial forced-end marker must not
291
- restart the marker sequence and duplicate its first token.
292
- """
291
+ restart the marker sequence and duplicate its first token."""
292
req_states = _make_req_states([1, START, 10, 11, END_A], prompt_len=5)
293
state = ThinkingBudgetState(req_states, MockMultiTokenEndReasoningConfig())
294
state.add_request(3, SamplingParams(thinking_token_budget=3))
tests/v1/worker/test_gpu_ubatch_slicing.py
+1
-2
@@ -701,8 +701,7 @@ def test_microbatches_recompute_dcp_lens_from_truncated_seq_lens(dcp_rank: int):
701
@pytest.mark.skipif(not torch.cuda.is_available(), reason="triton kernel needs CUDA")
702
def test_each_microbatch_owns_its_dcp_buffer():
703
"""Microbatch DCP lengths live in per-microbatch persistent buffers so
704
- CPU-visible shapes stay valid under CUDA graph capture and replay.
705
- """
704
+ CPU-visible shapes stay valid under CUDA graph capture and replay."""
705
input_batch, _ = _make_cuda_input_batch([4, 4, 4, 4], [8, 9, 10, 11])
706
707
ubatches, dcp_buffers = _slice_with_dcp(input_batch, dcp_rank=0)
tests/v1/worker/test_gpu_worker.py
+5
-10
@@ -49,8 +49,7 @@ def plan_env(monkeypatch: pytest.MonkeyPatch, tmp_path):
49
50
def test_startup_plan_fingerprint_sensitivity(plan_env):
51
"""The fingerprint is the OOM-safety key: stable for identical inputs,
52
- different for anything the profiled value depends on.
53
- """
52
+ different for anything the profiled value depends on."""
53
fp = startup_plan.compute_plan_fingerprint
54
base = fp(_plan_worker().vllm_config, 0, 1)
55
assert base == fp(_plan_worker().vllm_config, 0, 1)
@@ -98,8 +97,7 @@ def _snapshot(free_memory, torch_memory=0):
97
98
def _profile_result(consumed, reserved_before=0, reserved_after=0):
99
"""A result whose free-memory readings agree with `consumed`, which
101
- `memory_profiling` derives as the drop in free memory, negative when it grew.
102
- """
100
+ `memory_profiling` derives as the drop in free memory, negative when it grew."""
101
return SimpleNamespace(
102
total_consumed=consumed,
103
transient_peak_headroom=0,
@@ -127,8 +125,7 @@ def test_profiling_fallback_declines_when_free_memory_dropped(rocm):
125
@pytest.mark.parametrize("rocm", [True], indirect=True)
126
def test_profiling_fallback_replaces_a_released_measurement(rocm):
127
"""A negative measurement describes the rest of the device, so it is replaced
130
- by this process's reservation, which the rest of the device cannot move.
131
- """
128
+ by this process's reservation, which the rest of the device cannot move."""
129
result = _profile_result(
130
consumed=-RELEASED_BY_OTHERS,
131
reserved_after=TORCH_RESERVED,
@@ -152,8 +149,7 @@ def test_profiling_fallback_never_returns_a_negative_amount(rocm):
149
@pytest.mark.parametrize("rocm", [False], indirect=True)
150
def test_profiling_fallback_declines_off_rocm(rocm):
151
"""Platforms that account frees eagerly keep reporting the error, so the
155
- caller's assertion stays reachable there.
156
- """
152
+ caller's assertion stays reachable there."""
153
result = _profile_result(consumed=-RELEASED_BY_OTHERS)
154
155
assert maybe_rocm_profiling_fallback(result) is None
@@ -177,8 +173,7 @@ def test_execute_model_waits_previous_pp_send_before_forward(
173
monkeypatch: pytest.MonkeyPatch,
174
):
175
"""Previous device handles are waited before the forward pass; the
180
- metadata handle is left to the GroupCoordinator's reaper.
181
- """
176
+ metadata handle is left to the GroupCoordinator's reaper."""
177
import torch
178
179
from vllm.sequence import IntermediateTensors
tests/v1/worker/test_kv_block_zeroer.py
+1
-2
@@ -358,8 +358,7 @@ def test_warmup_respects_available_block_count():
358
def test_zeroes_exactly_one_block_per_layer(layout: KVCacheLayout):
359
"""The zeroer must zero every byte of the target block in every layer and nothing
360
outside it — per head-group region under LHBNC, and never past the target block's
361
- tile under block-major layouts (no out-of-bounds writes, no clobbering).
362
- """
361
+ tile under block-major layouts (no out-of-bounds writes, no clobbering)."""
362
device = torch.device("cuda")
363
num_blocks, num_layers = 4, 2
364
spec = FullAttentionSpec(
tests/v1/worker/test_mamba_utils.py
+4
-8
@@ -645,8 +645,7 @@ def test_mamba_groups_support_mixed_specs_in_uniform_group():
645
646
def _make_staging_ctx(max_num_reqs: int, device: torch.device) -> MagicMock:
647
"""Build a MambaSpecDecodeGPUContext stand-in exposing only the four
648
- per-request staging buffers touched by stage_postprocess_inputs_to_gpu.
649
- """
648
+ per-request staging buffers touched by stage_postprocess_inputs_to_gpu."""
649
ctx = MagicMock()
650
ctx.mamba_state_idx_buf = _MockCpuGpuBuffer(max_num_reqs, torch.int32, device)
651
ctx.num_scheduled_tokens_buf = _MockCpuGpuBuffer(max_num_reqs, torch.int32, device)
@@ -658,8 +657,7 @@ def _make_staging_ctx(max_num_reqs: int, device: torch.device) -> MagicMock:
657
def test_stage_postprocess_inputs_to_gpu_fills_pinned_views():
658
"""stage_postprocess_inputs_to_gpu writes each request's state_idx and
659
scheduled/computed/draft counts into slot `i` for `req_ids[i]`, leaves
661
- slots past `num_reqs` untouched, and mirrors the values to the GPU buffers.
662
- """
660
+ slots past `num_reqs` untouched, and mirrors the values to the GPU buffers."""
661
device = torch.device("cpu")
662
max_num_reqs = 8
663
ctx = _make_staging_ctx(max_num_reqs, device)
@@ -731,8 +729,7 @@ def test_stage_postprocess_inputs_to_gpu_fills_pinned_views():
729
730
def test_stage_postprocess_inputs_to_gpu_asserts_on_missing_state_idx():
731
"""If preprocess_mamba didn't populate mamba_state_idx for a req in the
734
- batch, staging must fail loudly rather than silently writing a stale index.
735
- """
732
+ batch, staging must fail loudly rather than silently writing a stale index."""
733
device = torch.device("cpu")
734
ctx = _make_staging_ctx(max_num_reqs=4, device=device)
735
scheduler_output = _make_postprocess_scheduler_output(
@@ -810,8 +807,7 @@ def _run_gpu_postprocess(
807
device: torch.device,
808
) -> None:
809
"""Initialize the GPU context against `block_table`, run the fused
813
- postprocess kernel for `req_ids`, and synchronize.
814
- """
810
+ postprocess kernel for `req_ids`, and synchronize."""
811
812
def t(values):
813
return torch.tensor(values, dtype=torch.int32, device=device)
tests/v1/worker/test_mixed_warmup_gate.py
+1
-2
@@ -17,8 +17,7 @@ def _fail(*args, **kwargs):
17
@pytest.mark.parametrize("max_num_reqs", [1, 0])
18
def test_mixed_warmup_skipped_for_single_seq(max_num_reqs):
19
"""A mixed prefill+decode step needs >=2 requests; with max_num_reqs < 2
20
- the warmup must be skipped without touching the worker callbacks.
21
- """
20
+ the warmup must be skipped without touching the worker callbacks."""
21
runner = SimpleNamespace(is_pooling_model=False, max_num_reqs=max_num_reqs)
22
23
assert (
tests/v1/worker/test_prompt_embeds_state.py
+4
-8
@@ -78,8 +78,7 @@ def _apply(
78
def test_overlay_chunked_prefill_and_decode():
79
"""Rows within the embeds range come from prompt_embeds at the
80
num_computed offset; requests without embeds and requests past their
81
- embeds length (decode) keep the base embedding.
82
- """
81
+ embeds length (decode) keep the base embedding."""
82
state = _make_state()
83
embeds_a = torch.randn(6, HIDDEN, dtype=torch.float32)
84
embeds_b = torch.randn(5, HIDDEN, dtype=torch.float32)
@@ -98,8 +97,7 @@ def test_overlay_chunked_prefill_and_decode():
97
98
def test_overlay_clamps_to_embeds_length():
99
"""A window straddling the end of the prompt embeds writes only the
101
- in-range rows (e.g. final prefill chunk + sampled token).
102
- """
100
+ in-range rows (e.g. final prefill chunk + sampled token)."""
101
state = _make_state()
102
embeds = torch.randn(4, HIDDEN, dtype=torch.float32)
103
state.add_request(3, _NewReqData("a", embeds))
@@ -114,8 +112,7 @@ def test_overlay_clamps_to_embeds_length():
112
113
def test_overlay_respects_is_token_ids_mask():
114
"""Mixed mode: positions marked as real token ids keep the base
117
- embedding; only embed positions are overwritten.
118
- """
115
+ embedding; only embed positions are overwritten."""
116
state = _make_state()
117
embeds = torch.randn(5, HIDDEN, dtype=torch.float32)
118
is_token_ids = [True, False, False, True, False]
@@ -133,8 +130,7 @@ def test_overlay_respects_is_token_ids_mask():
130
131
def test_index_reuse_clears_stale_entry():
132
"""A request added at a previously-used index without embeds must not
136
- inherit the prior occupant's pointer-table entry.
137
- """
133
+ inherit the prior occupant's pointer-table entry."""
134
state = _make_state()
135
state.add_request(0, _NewReqData("a", torch.randn(4, HIDDEN, dtype=torch.float32)))
136
# A second live embeds request so the kernel actually launches (the
tests/v1/worker/test_workspace.py
+1
-2
@@ -84,8 +84,7 @@ def test_workspace_lanes_compose_with_ubatches(monkeypatch) -> None:
84
85
def test_workspace_lock_blocks_growth_and_unlock_restores(monkeypatch) -> None:
86
"""Once locked, oversized requests fail loudly instead of reallocating the
87
- buffer that captured CUDA graphs point at; unlock restores growth.
88
- """
87
+ buffer that captured CUDA graphs point at; unlock restores growth."""
88
monkeypatch.setattr(workspace, "dbo_current_ubatch_id", lambda: 0)
89
manager = workspace.WorkspaceManager(torch.device("cpu"), num_lanes=1)
90
tools/report_build_time_ninja.py
+3
-6
@@ -56,8 +56,7 @@ class Target:
56
57
def __init__(self, start, end):
58
"""Creates a target object by passing in the start/end times in seconds
59
- as a float.
60
- """
59
+ as a float."""
60
self.start = start
61
self.end = end
62
# A list of targets, appended to by the owner of this object.
@@ -105,8 +104,7 @@ class Target:
104
def ReadTargets(log, show_all):
105
"""Reads all targets from .ninja_log file |log_file|, sorted by duration.
106
108
- The result is a list of Target objects.
109
- """
107
+ The result is a list of Target objects."""
108
header = log.readline()
109
assert header == "# ninja log v5\n", "unrecognized ninja log version {!r}".format(
110
header
@@ -155,8 +153,7 @@ def GetExtension(target, extra_patterns):
153
154
For targets that generate multiple outputs it is important to return a
155
consistent 'canonical' extension. Ultimately the goal is to group build steps
158
- by type.
159
- """
156
+ by type."""
157
for output in target.targets:
158
if extra_patterns:
159
for fn_pattern in extra_patterns.split(";"):
vllm/_aiter_ops.py
+1
-2
@@ -1974,8 +1974,7 @@ class rocm_aiter_ops:
1974
enabled aiter. Only aiter's Triton kernels exist on gfx12 (no CK build),
1975
so this deliberately stays off the gfx9/CK `@if_aiter_supported` umbrella
1976
and gates only the Triton paths rdna4 uses. The gfx12 analog of
1977
- `is_enabled()`.
1978
- """
1977
+ `is_enabled()`."""
1978
if not current_platform.is_rocm() or not IS_AITER_FOUND:
1979
return False
1980
from vllm.platforms.rocm import on_rdna4
vllm/benchmarks/datasets/create_txt_slices_dataset.py
+1
-2
@@ -65,8 +65,7 @@ def create_txt_slices_jsonl(
65
trust_remote_code: bool = False,
66
) -> None:
67
"""Read *input_path*, slice it into prompts, and write JSONL to
68
- *output_path*.
69
- """
68
+ *output_path*."""
69
tokenizer = AutoTokenizer.from_pretrained(
70
tokenizer_name, trust_remote_code=trust_remote_code
71
)
vllm/benchmarks/datasets/datasets.py
+1
-2
@@ -4383,8 +4383,7 @@ class PrefixRepetitionRandomDataset(BenchmarkDataset):
4383
4384
def _generate_exact_length_tokens(target_length: int) -> tuple[list[int], int]:
4385
"""Generate tokens that decode and re-encode to exactly
4386
- target_length.
4387
- """
4386
+ target_length."""
4387
# Generate random tokens
4388
tokens = np.random.randint(0, vocab_size, size=target_length).tolist()
4389
vllm/benchmarks/lib/endpoint_request_func.py
+2
-4
@@ -22,8 +22,7 @@ AIOHTTP_TIMEOUT = aiohttp.ClientTimeout(total=6 * 60 * 60)
22
23
class StreamedResponseHandler:
24
"""Handles streaming HTTP responses by accumulating chunks until complete
25
- messages are available.
26
- """
25
+ messages are available."""
26
27
def __init__(self):
28
self.buffer = ""
@@ -31,8 +30,7 @@ class StreamedResponseHandler:
30
31
def add_chunk(self, chunk_bytes: bytes) -> list[str]:
32
"""Add a chunk of bytes to the buffer and return any complete
34
- messages.
35
- """
33
+ messages."""
34
chunk_str = self._decoder.decode(chunk_bytes)
35
self.buffer += chunk_str
36
vllm/compilation/backends.py
+1
-2
@@ -150,8 +150,7 @@ class CompilerManager:
150
def compile_context(self, compile_range: Range) -> Generator[None, None, None]:
151
"""Provide compilation context for the duration of compilation to set
152
any torch global properties we want to scope to a single Inductor
153
- compilation (e.g. partition rules, pass context).
154
- """
153
+ compilation (e.g. partition rules, pass context)."""
154
with pass_context(compile_range):
155
if self.compilation_config.use_inductor_graph_partition:
156
with inductor_partition_rule_context(
vllm/compilation/compiler_interface.py
+1
-2
@@ -153,8 +153,7 @@ def _get_vllm_functorch_config() -> dict[str, Any]:
153
"""Return the functorch config overrides that vLLM applies at compile time.
154
155
Used by both set_functorch_config() and get_inductor_factors() to ensure
156
- the compile-time config and cache key are always consistent.
157
- """
156
+ the compile-time config and cache key are always consistent."""
157
cfg: dict[str, Any] = {}
158
if not envs.VLLM_USE_MEGA_AOT_ARTIFACT:
159
cfg["bundled_autograd_cache"] = False
vllm/compilation/passes/fusion/allreduce_rms_fusion.py
+1
-2
@@ -66,8 +66,7 @@ def _view_flashinfer_nvfp4_scale_out_as_int32(
66
67
def _norm_input_weight_dtype_match(match: pm.Match) -> bool:
68
"""Prevent fusion when the norm input and weight dtypes differ (e.g. a Gemma
69
- fp32 weight.float()+1 gamma), covering rms_norm and fused_add_rms_norm.
70
- """
69
+ fp32 weight.float()+1 gamma), covering rms_norm and fused_add_rms_norm."""
70
for node in match.nodes:
71
if node.target == _IR_RMS_NORM_OP:
72
x, weight = node.args[0], node.args[1]
vllm/compilation/passes/utility/split_coalescing.py
+1
-2
@@ -30,8 +30,7 @@ logger = init_logger(__name__)
30
31
class SplitCoalescingPass(VllmInductorPass):
32
"""Replace duplicate ``split_with_sizes`` nodes with a single canonical
33
- node when they share the same input tensor and split sizes.
34
- """
33
+ node when they share the same input tensor and split sizes."""
34
35
@VllmInductorPass.time_and_log
36
def __call__(self, graph: fx.Graph) -> None:
vllm/config/compilation.py
+2
-4
@@ -36,8 +36,7 @@ logger = init_logger(__name__)
36
37
class CompilationMode(enum.IntEnum):
38
"""The compilation approach used for torch.compile-based compilation of the
39
- model.
40
- """
39
+ model."""
40
41
NONE = 0
42
"""No torch.compile compilation is applied, model runs in fully eager pytorch mode.
@@ -337,8 +336,7 @@ class PassConfig:
336
class DynamicShapesType(str, enum.Enum):
337
"""Types of dynamic shapes handling in torch.compile().
338
see Dynamic shapes and vllm guard dropping in torch_compile.md
340
- for more details.
341
- """
339
+ for more details."""
340
341
BACKED = "backed"
342
"""Use backed dynamic shapes. torch.compile() guards on backed dynamic
vllm/config/model.py
+1
-2
@@ -1005,8 +1005,7 @@ class ModelConfig:
1005
1006
def _get_transformers_backend_cls(self) -> str:
1007
"""Determine which Transformers modeling backend class will be used if
1008
- `model_impl` is set to `transformers` or `auto`.
1009
- """
1008
+ `model_impl` is set to `transformers` or `auto`."""
1009
cls = "Transformers"
1010
# If 'hf_config is not hf_text_config' it's a nested config, i.e. multimodal
1011
cls += "MultiModal" if self.hf_config is not self.hf_text_config else ""
vllm/config/multimodal.py
+1
-2
@@ -524,8 +524,7 @@ class MultiModalConfig:
524
525
def get_video_pruning_spec(self) -> tuple[VideoPruningMethod, float] | None:
526
"""Return `(method, rate)` when video pruning is enabled, else None.
527
- `rate` is the fraction of video tokens to prune.
528
- """
527
+ `rate` is the fraction of video tokens to prune."""
528
if self.video_pruning_rate is not None and self.video_pruning_rate > 0:
529
return (self.video_pruning_method, float(self.video_pruning_rate))
530
return None
vllm/config/observability.py
+1
-2
@@ -156,8 +156,7 @@ class ObservabilityConfig:
156
cls, value: list[DetailedTraceModules] | None
157
) -> list[DetailedTraceModules] | None:
158
"""Handle the legacy case where users might provide a comma-separated
159
- string instead of a list of strings.
160
- """
159
+ string instead of a list of strings."""
160
if value is not None and len(value) == 1 and "," in value[0]:
161
value = cast(list[DetailedTraceModules], value[0].split(","))
162
return value
vllm/config/reasoning.py
+2
-4
@@ -47,15 +47,13 @@ class ReasoningConfig:
47
@property
48
def enabled(self) -> bool:
49
"""Returns True if reasoning is enabled (i.e. if token IDs have been
50
- initialized), False otherwise.
51
- """
50
+ initialized), False otherwise."""
51
return self._enabled
52
53
@property
54
def reasoning_start_token_ids(self) -> list[int] | None:
55
"""Token IDs derived from `reasoning_start_str`. Set automatically by
57
- `initialize_token_ids`. Not intended to be configured directly.
58
- """
56
+ `initialize_token_ids`. Not intended to be configured directly."""
57
return self._reasoning_start_token_ids
58
59
@property
vllm/config/speculative.py
+2
-4
@@ -543,8 +543,7 @@ class SpeculativeConfig:
543
@staticmethod
544
def _acceptance_length_to_rates(length: float, n: int) -> list[float]:
545
"""Mean acceptance length to unconditional per-position rates, using
546
- the minimum-variance schedule.
547
- """
546
+ the minimum-variance schedule."""
547
num_drafts = length - 1 # expected number of accepted draft tokens
548
num_full = int(num_drafts)
549
return (
@@ -558,8 +557,7 @@ class SpeculativeConfig:
557
length: float | None,
558
) -> list[float]:
559
"""Return per-position unconditional acceptance rates from exactly one
561
- of `rates` or `length` (validates range, length, and monotonicity).
562
- """
560
+ of `rates` or `length` (validates range, length, and monotonicity)."""
561
if (rates is None) == (length is None):
562
raise ValueError(
563
"rejection_sample_method='synthetic' requires exactly one of "
vllm/config/utils.py
+2
-4
@@ -84,8 +84,7 @@ def config(
84
85
def get_field(cls: ConfigType, name: str) -> Any:
86
"""Get the default factory field of a dataclass by name. Used for getting
87
- default factory fields in `EngineArgs`.
88
- """
87
+ default factory fields in `EngineArgs`."""
88
if not is_dataclass(cls):
89
raise TypeError("The given class is not a dataclass.")
90
try:
@@ -122,8 +121,7 @@ def is_init_field(cls: ConfigType, name: str) -> bool:
121
def replace(dataclass_instance: ConfigT, /, **kwargs) -> ConfigT:
122
"""Like [`dataclasses.replace`](https://docs.python.org/3/library/dataclasses.html#dataclasses.replace),
123
but compatible with Pydantic dataclasses which use `pydantic.fields.Field` instead
125
- of `dataclasses.field`
126
- """
124
+ of `dataclasses.field`"""
125
cls = type(dataclass_instance)
126
dataclass_dict = dataclass_instance.__dict__
127
dataclass_dict = {k: v for k, v in dataclass_dict.items() if is_init_field(cls, k)}
vllm/config/vllm.py
+2
-4
@@ -153,8 +153,7 @@ IS_DENSE = False
153
154
def enable_norm_fusion(cfg: "VllmConfig") -> bool:
155
"""Enable if either RMS norm or quant FP8 custom op is active;
156
- otherwise Inductor handles fusion.
157
- """
156
+ otherwise Inductor handles fusion."""
157
return (
158
cfg.compilation_config.is_custom_op_enabled("rms_norm")
159
or cfg.compilation_config.is_custom_op_enabled("quant_fp8")
@@ -744,8 +743,7 @@ class VllmConfig:
743
744
def _is_dflash2_draft(self) -> bool:
745
"""Whether the DFlash draft is a DFlash2 one, by the architecture the
747
- speculator selects on (v1/worker/gpu/spec_decode/__init__.py).
748
- """
746
+ speculator selects on (v1/worker/gpu/spec_decode/__init__.py)."""
747
spec = self.speculative_config
748
if spec is None or spec.method != "dflash":
749
return False
vllm/device_allocator/sleep_mode_backend.py
+5
-10
@@ -70,8 +70,7 @@ class SleepModeBackend(ABC):
70
71
def state(self) -> SleepModeState:
72
"""Current lifecycle state. Lets ``/health`` distinguish a healthy-idle
73
- (suspended) engine from a healthy-serving one (see RFC #34303).
74
- """
73
+ (suspended) engine from a healthy-serving one (see RFC #34303)."""
74
return self._state
75
76
# -- Capability introspection (no instance required) --
@@ -84,30 +83,26 @@ class SleepModeBackend(ABC):
83
@classmethod
84
def preserves_communicators(cls) -> bool:
85
"""If False, collective communicators (e.g. NCCL) are destroyed by
87
- ``suspend`` and the executor must re-initialize them on ``resume``.
88
- """
86
+ ``suspend`` and the executor must re-initialize them on ``resume``."""
87
return False
88
89
@classmethod
90
def preserves_compiled_artifacts(cls) -> bool:
91
"""If True, torch.compile / JIT kernels survive suspend/resume and need
94
- not be recompiled on resume.
95
- """
92
+ not be recompiled on resume."""
93
return False
94
95
@classmethod
96
def preserves_graphs_with_communicators(cls) -> bool:
97
"""If True, CUDA graphs containing collective communicators (e.g. NCCL)
98
stay valid after resume. False when communicators are rebuilt (embedded
102
- comm handles go stale).
103
- """
99
+ comm handles go stale)."""
100
return False
101
102
@classmethod
103
def supports_durable_storage(cls) -> bool:
104
"""If True, suspended state can be persisted beyond the process
109
- lifetime (disk or object storage) and restored in a new process.
110
- """
105
+ lifetime (disk or object storage) and restored in a new process."""
106
return False
107
108
vllm/distributed/device_communicators/all_reduce_utils.py
+1
-2
@@ -156,8 +156,7 @@ def should_nccl_symm_mem_allreduce(world_size: int, input_tensor: torch.Tensor)
156
157
def should_nccl_symm_mem_ag_rs() -> bool:
158
"""Check whether NCCL symmetric memory should be used for
159
- AllGather / ReduceScatter collectives.
160
- """
159
+ AllGather / ReduceScatter collectives."""
160
from vllm.distributed.device_communicators.pynccl_allocator import (
161
is_symmetric_memory_enabled,
162
)
vllm/distributed/device_communicators/shm_broadcast.py
+2
-4
@@ -650,8 +650,7 @@ class MessageQueue:
650
651
def shutdown(self):
652
"""If this is an idle reader, wakes it up so it can clean up and shut
653
- down
654
- """
653
+ down"""
654
self.shutting_down = True
655
if self._spin_condition is not None:
656
self._spin_condition.cancel()
@@ -761,8 +760,7 @@ class MessageQueue:
760
761
def should_warn(self) -> bool:
762
"""Returns true if it's time to log a warning for a timeout that is not
764
- indefinite
765
- """
763
+ indefinite"""
764
if self._should_warn:
765
elapsed = time.monotonic() - self.started
766
if elapsed >= VLLM_RINGBUFFER_WARNING_INTERVAL * self.n_warning:
vllm/distributed/ec_transfer/ec_connector/cpu/scheduler/embedding_cache.py
+1
-2
@@ -15,8 +15,7 @@ from collections import OrderedDict
15
16
class CacheEntry:
17
"""A single cache entry. Read `.block_ids` and `.ready` freely;
18
- mutations only through EmbeddingCache methods.
19
- """
18
+ mutations only through EmbeddingCache methods."""
19
20
__slots__ = ("block_ids", "_pin_count")
21
vllm/distributed/eplb/eplb_communicator.py
+2
-4
@@ -84,8 +84,7 @@ class EplbCommunicator(ABC):
84
@property
85
def needs_profile_buffer_reservation(self) -> bool:
86
"""Whether the profile path must run a dummy collective operation to reserve
87
- communication buffers.
88
- """
87
+ communication buffers."""
88
return True
89
90
def set_stream(self, cuda_stream: torch.cuda.Stream | None) -> None:
@@ -443,8 +442,7 @@ class NixlEplbCommunicator(EplbCommunicator):
442
443
def _exchange_remote_send_meta(self) -> None:
444
"""Exchange per-layer per-tensor metadata so receivers can compute
446
- remote RDMA addresses at transfer time.
447
- """
445
+ remote RDMA addresses at transfer time."""
446
local_meta: dict[tuple[int, int], tuple[int, int, int]] = {}
447
for layer_idx, layer_tensors in enumerate(self._all_expert_weights):
448
for t_idx, t in enumerate(layer_tensors):
vllm/distributed/kv_transfer/kv_connector/utils.py
+1
-2
@@ -51,8 +51,7 @@ def get_kv_connector_cache_layout(vllm_config: VllmConfig | None = None):
51
52
class KVOutputAggregator:
53
"""Utility class to aggregate the output of all workers into a single
54
- output corresponding to Rank 0 for scheduler.
55
- """
54
+ output corresponding to Rank 0 for scheduler."""
55
56
def __init__(self, expected_finished_count: int):
57
# Complete transfer tracker. Used to track finished requests
vllm/distributed/kv_transfer/kv_connector/v1/example_hidden_states_connector.py
+1
-2
@@ -278,8 +278,7 @@ class ExampleHiddenStatesConnector(KVConnectorBase_V1, SupportsHMA):
278
279
def _on_write_done(self, req_id: str, future: Future) -> None:
280
"""Surface any exception from the disk-write thread and drop the
281
- completed future from the in-flight tracking dict.
282
- """
281
+ completed future from the in-flight tracking dict."""
282
self._req_futures.pop(req_id, None)
283
exc = future.exception()
284
if exc is not None:
vllm/distributed/kv_transfer/kv_connector/v1/lmcache_mp_connector.py
+2
-4
@@ -231,8 +231,7 @@ class LMCacheMPRequestTracker:
231
####
232
def needs_retrieve(self) -> bool:
233
"""Check whether the current request needs retrieve, will be used
234
- update_stage_after_alloc
235
- """
234
+ update_stage_after_alloc"""
235
return (
236
self.num_lmcache_hit_blocks > self.num_vllm_hit_blocks
237
and self.state != LMCacheMPRequestState.READY
@@ -240,8 +239,7 @@ class LMCacheMPRequestTracker:
239
240
def is_ready_for_retrieving(self) -> bool:
241
"""Check whether the current request is ready for retrieving,
243
- will be used in process_loading_requests
244
- """
242
+ will be used in process_loading_requests"""
243
return (
244
self.state == LMCacheMPRequestState.WAITING_FOR_LOAD
245
and self.needs_retrieve()
vllm/distributed/kv_transfer/kv_connector/v1/mooncake/mooncake_connector.py
+4
-8
@@ -718,8 +718,7 @@ class MooncakeConnectorScheduler:
718
719
def _get_remote_prefill_token_count(self, num_prompt_tokens: int) -> int:
720
"""D-side only. Returns N-1 for Mamba models since the decoder
721
- always recomputes the last token and must start from h(N-1).
722
- """
721
+ always recomputes the last token and must start from h(N-1)."""
722
if self._has_mamba and num_prompt_tokens > 1:
723
return num_prompt_tokens - 1
724
return num_prompt_tokens
@@ -730,8 +729,7 @@ class MooncakeConnectorScheduler:
729
derive h(N) correctly.
730
731
Guarded by ``_p_side_truncated`` to avoid repeated truncation if the
733
- request is preempted and rescheduled.
734
- """
732
+ request is preempted and rescheduled."""
733
params = request.kv_transfer_params
734
if (
735
params is not None
@@ -1677,8 +1675,7 @@ class MooncakeConnectorWorker:
1675
def _bind_sender_thread_device(self) -> None:
1676
"""ThreadPoolExecutor initializer — binds each pool thread to the
1677
correct CUDA device. CUDA device selection is thread-local, so
1680
- without this, NVLink transfers fail for TP ranks > 0.
1681
- """
1678
+ without this, NVLink transfers fail for TP ranks > 0."""
1679
current_platform.set_device(self.device_id)
1680
1681
def _send_blocks(
@@ -1904,8 +1901,7 @@ class MooncakeConnectorWorker:
1901
1902
def get_kv_connector_stats(self) -> KVConnectorStats | None:
1903
"""Return transfer stats collected since the last call, or None
1907
- if nothing has been recorded in this interval.
1908
- """
1904
+ if nothing has been recorded in this interval."""
1905
if self.xfer_stats.is_empty():
1906
return None
1907
return self.xfer_stats.clone_and_reset()
vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/coordinator.py
+1
-2
@@ -73,8 +73,7 @@ class ExternalCachedBlockPool:
73
74
class MooncakeStoreCoordinator:
75
"""Mirror of ``HybridKVCacheCoordinator.find_longest_cache_hit`` over an
76
- ``ExternalCachedBlockPool``.
77
- """
76
+ ``ExternalCachedBlockPool``."""
77
78
def __init__(
79
self,
vllm/distributed/kv_transfer/kv_connector/v1/mooncake/store/worker.py
+1
-2
@@ -2629,8 +2629,7 @@ class LookupKeyClient:
2629
non_block: bool = False,
2630
) -> MooncakeLookupResult | None:
2631
"""If non_block is True, will return None until the result is ready,
2632
- so the caller retries on a later step.
2633
- """
2632
+ so the caller retries on a later step."""
2633
future = self.futures.get(req_id)
2634
if future is None:
2635
future = self.executor.submit(self._lookup, num_tokens, list(block_hashes))
vllm/distributed/kv_transfer/kv_connector/v1/moriio/moriio_connector.py
+1
-2
@@ -548,8 +548,7 @@ class MoRIIOConnectorScheduler:
548
self, request_id: ReqId, transfer_id: TransferId | None = None
549
):
550
"""Unmap request_id/transfer_id. Uses transfer_id for lookup if
551
- exact request_id match fails (handles input_processor mutation).
552
- """
551
+ exact request_id match fails (handles input_processor mutation)."""
552
if request_id in self.request_id_to_transfer_id:
553
tid = self.request_id_to_transfer_id[request_id]
554
del self.request_id_to_transfer_id[request_id]
vllm/distributed/kv_transfer/kv_connector/v1/nixl/base_scheduler.py
+2
-4
@@ -400,8 +400,7 @@ class NixlBaseConnectorScheduler:
400
def _get_remote_prefill_token_count(self, num_prompt_tokens: int) -> int:
401
"""D-side only. The number of prompt tokens to load from the prefiller.
402
Stops short of the trailing ``_prefill_backoff()`` tokens that the decoder
403
- will recompute locally.
404
- """
403
+ will recompute locally."""
404
backoff = self._prefill_backoff()
405
if backoff and num_prompt_tokens > backoff:
406
return num_prompt_tokens - backoff
@@ -414,8 +413,7 @@ class NixlBaseConnectorScheduler:
413
multi-module MTP it is the drafter's whole lookahead window.
414
415
Guarded by ``_p_side_truncated`` to avoid repeated truncation if the
417
- request is preempted and rescheduled.
418
- """
416
+ request is preempted and rescheduled."""
417
backoff = self._prefill_backoff()
418
params = request.kv_transfer_params
419
if (
vllm/distributed/kv_transfer/kv_connector/v1/nixl/base_worker.py
+2
-4
@@ -1873,8 +1873,7 @@ class NixlBaseConnectorWorker:
1873
) -> np.ndarray:
1874
"""Build remote desc regions (conv sub-projections + ssm) per layer.
1875
For hetero-TP, each D rank reads only its sub-projection slice from
1876
- the P rank. Returns an Nx3 uint64 array.
1877
- """
1876
+ the P rank. Returns an Nx3 uint64 array."""
1877
assert nixl_agent_meta.kv_caches_base_addr, (
1878
"Remote KV cache base addresses must not be empty."
1879
)
@@ -2657,8 +2656,7 @@ class NixlBaseConnectorWorker:
2656
@cached_property
2657
def _attention_kv_caches(self) -> list[torch.Tensor]:
2658
"""Device KV caches of attention layers (mamba states excluded),
2660
- as consumed by the receive post-process.
2661
- """
2659
+ as consumed by the receive post-process."""
2660
assert self.device_kv_caches, (
2661
"_attention_kv_caches accessed before register_kv_caches"
2662
)
vllm/distributed/kv_transfer/kv_connector/v1/nixl/push_worker.py
+2
-4
@@ -315,8 +315,7 @@ class NixlPushConnectorWorker(NixlBaseConnectorWorker):
315
executes on the writer; the handshake runs on the background executor
316
and the request is re-queued onto ``_reg_send_inbox`` once it
317
completes (at which point ``_ensure_handshake`` returns ``None`` and we
318
- send directly).
319
- """
318
+ send directly)."""
319
remote_pp_size = reg_data.get("remote_pp_size", 1)
320
fut = self._ensure_handshake(
321
reg_data["remote_engine_id"],
@@ -508,8 +507,7 @@ class NixlPushConnectorWorker(NixlBaseConnectorWorker):
507
``BlockIds`` is canonically a tuple of per-group lists, but some
508
registration payloads collapse a single-group case to a flat
509
list. Re-wrap that case so downstream group-aware helpers see a
511
- consistent shape.
512
- """
510
+ consistent shape."""
511
if block_ids and not isinstance(block_ids[0], (list, tuple)):
512
return (list(block_ids),)
513
return block_ids
vllm/distributed/kv_transfer/kv_connector/v1/offloading/canonical_mapping.py
+4
-8
@@ -37,8 +37,7 @@ def canonical_format_id(kv_cache_layout: str) -> str:
37
Canonical pages keep the worker's KV layout family, so the id couples the
38
format version with that family; consumers must match it exactly. The family
39
keeps its historical NHD/HND spelling so ids stay stable for KV persisted
40
- before the layout enum existed.
41
- """
40
+ before the layout enum existed."""
41
layout = KVCacheLayout[kv_cache_layout]
42
legacy = {KVCacheLayout.LBNHC: "nhd", KVCacheLayout.LBHNC: "hnd"}
43
family = legacy.get(layout, layout.name.lower())
@@ -122,8 +121,7 @@ def _interleave_cp_tokens(
121
ctx: _RankContext,
122
) -> tuple[CopyRun, ...]:
123
"""Place each region's num_tokens rows at their canonical token positions,
125
- one run per chunk of interleaved tokens.
126
- """
124
+ one run per chunk of interleaved tokens."""
125
runs: list[CopyRun] = []
126
for region in regions:
127
if ctx.cp_size == 1:
@@ -258,8 +256,7 @@ def _attention_byte_regions(
256
cp_size: int,
257
) -> list[ByteRegion] | None:
258
"""Byte regions of an attention page, given this rank's head shard.
261
- None when the physical layout is not recognized (fail closed).
262
- """
259
+ None when the physical layout is not recognized (fail closed)."""
260
bs, heads, head_size = spec.block_size, spec.num_kv_heads, spec.head_size
261
if tuple(kv_cache.shape) == (num_blocks, heads, bs, 2 * head_size):
262
return _packed_kv_regions(kv_cache, spec, head_shard, num_head_shards, cp_size)
@@ -373,8 +370,7 @@ def _is_exact_partition(intervals: list[tuple[int, int]], size: int) -> bool:
370
371
def _verify_tiling(layer_name: str, per_rank: list[CanonicalPageMapping]) -> None:
372
"""Whichever ranks a block elects as writers must tile the canonical page
376
- exactly once, and each rank's runs must cover exactly its local page.
377
- """
373
+ exactly once, and each rank's runs must cover exactly its local page."""
374
size = per_rank[0].canonical_page_size_bytes
375
num_writers = per_rank[0].num_writers
376
for mapping in per_rank:
vllm/distributed/kv_transfer/kv_connector/v1/offloading/events.py
+3
-6
@@ -79,8 +79,7 @@ def get_offloading_event_group_spec(
79
class _OffloadEventMetadata:
80
"""BlockStored payload snapshot for one OffloadKey, captured while the
81
Request is available and kept until the final matching removal event.
82
- ``medium`` and ``ownership`` are forwarded from the OffloadingEvent.
83
- """
82
+ ``medium`` and ``ownership`` are forwarded from the OffloadingEvent."""
83
84
# The chunk's constituent block hashes; the last one is the OffloadKey.
85
block_hashes: tuple[BlockHash, ...]
@@ -256,8 +255,7 @@ class OffloadingEventsTracker:
255
256
def reset(self) -> None:
257
"""Drop all tracked state; pending payloads are stale after a
259
- manager cache reset.
260
- """
258
+ manager cache reset."""
259
self._pending_event_metadata.clear()
260
261
def _build_event_metadata(
@@ -268,8 +266,7 @@ class OffloadingEventsTracker:
266
) -> _OffloadEventMetadata:
267
"""Build the payload snapshot for one offloaded chunk: its
268
constituent per-block hashes, the whole chunk's tokens, and the
271
- per-block ``block_size``.
272
- """
269
+ per-block ``block_size``."""
270
hashes_per_chunk = group_config.hashes_per_chunk
271
assert hashes_per_chunk > 0
272
assert chunk_idx >= 0
vllm/distributed/kv_transfer/kv_connector/v1/offloading/scheduler.py
+2
-4
@@ -676,8 +676,7 @@ class OffloadingConnectorScheduler:
676
start_chunk_idx: int,
677
) -> int | None:
678
"""Return the number of consecutive offloaded chunks from the start,
679
- or None if the backend deferred a lookup.
680
- """
679
+ or None if the backend deferred a lookup."""
680
hit_count = 0
681
defer_lookup = False
682
for local_idx, key in enumerate(keys):
@@ -712,8 +711,7 @@ class OffloadingConnectorScheduler:
711
"""Return the end index (in `keys`) of the last run of
712
`sliding_window_size` consecutive hits, scanning from the end.
713
The first run may need a larger window for a partial rightmost chunk.
715
- Returns 0 on miss, None if the backend deferred a lookup.
716
- """
714
+ Returns 0 on miss, None if the backend deferred a lookup."""
715
defer_lookup = False
716
pending_in_window = False
717
consecutive_hits = 0
vllm/distributed/utils.py
+1
-2
@@ -59,8 +59,7 @@ def ensure_divisibility(numerator, denominator):
59
60
def divide(numerator, denominator):
61
"""Ensure that numerator is divisible by the denominator and return
62
- the division value.
63
- """
62
+ the division value."""
63
ensure_divisibility(numerator, denominator)
64
return numerator // denominator
65
vllm/distributed/weight_transfer/factory.py
+1
-2
@@ -141,8 +141,7 @@ class WeightTransferTrainerFactory:
141
class_name: str | None = None,
142
) -> None:
143
"""Register a trainer engine. Same conventions as
144
- `WeightTransferEngineFactory.register_engine`.
145
- """
144
+ `WeightTransferEngineFactory.register_engine`."""
145
if name in cls._registry:
146
raise ValueError(
147
f"Weight transfer trainer engine '{name}' is already registered."
vllm/distributed/weight_transfer/ipc_engine.py
+2
-4
@@ -40,8 +40,7 @@ class IPCWeightTransferInitInfo(WeightTransferInitInfo):
40
`packed` is a must-agree wire param: the trainer ships it here at the init
41
handshake so the worker decodes with the same setting the trainer encoded
42
with. The consumer rebuilds from the IPC handle + `tensor_sizes`, so it does
43
- not need the buffer size (producer-only).
44
- """
43
+ not need the buffer size (producer-only)."""
44
45
packed: bool = False
46
@@ -54,8 +53,7 @@ class IPCTrainerInitInfo(TrainerInitInfo):
53
54
`packed` / `packed_buffer_size_bytes` are the transfer's wire params. The
55
trainer propagates `packed` to the worker at `trainer_init` so the two sides
57
- cannot disagree. `backend` is the factory dispatch key.
58
- """
56
+ cannot disagree. `backend` is the factory dispatch key."""
57
58
backend: ClassVar[str] = "ipc"
59
packed: bool = False
vllm/distributed/weight_transfer/nccl_common.py
+1
-2
@@ -118,8 +118,7 @@ def worker_init_payload(init_info: NCCLWeightTransferInitInfo) -> dict:
118
"""Serialize a worker init info for `init_weight_transfer_engine`, dropping
119
the unset rendezvous field (the UID in TCP mode) so the wire payload carries
120
only the mode actually in use. Shared by the dense and sparse trainer
121
- engines so the two cannot drift.
122
- """
121
+ engines so the two cannot drift."""
122
return {key: value for key, value in asdict(init_info).items() if value is not None}
123
124
vllm/distributed/weight_transfer/nccl_engine.py
+2
-4
@@ -69,8 +69,7 @@ class NCCLTrainerInitInfo(TrainerInitInfo):
69
propagates them to the worker at `trainer_init` so the two sides cannot
70
disagree. Note this defaults to packed, unlike the worker-side
71
`NCCLWeightTransferInitInfo`, whose default only applies when no trainer
72
- ships a value. `backend` is the factory dispatch key.
73
- """
72
+ ships a value. `backend` is the factory dispatch key."""
73
74
backend: ClassVar[str] = "nccl"
75
@@ -365,8 +364,7 @@ class NCCLTrainerWeightTransferEngine(TrainerWeightTransferEngine[NCCLTrainerIni
364
def _broadcast(self, source: WeightSource, meta: list[ParamMeta]) -> None:
365
"""Iterate the source (materializing each tensor — a collective on all
366
ranks) and, on the sender, broadcast from rank 0, packed or one-by-one.
368
- Non-sender ranks only replay the iteration to stay in the collective.
369
- """
367
+ Non-sender ranks only replay the iteration to stay in the collective."""
368
if not self.is_sender:
369
for _ in source:
370
pass
vllm/distributed/weight_transfer/sharded_rdt_common.py
+3
-6
@@ -214,8 +214,7 @@ class RdtRouter:
214
215
def class_of(self, name: str) -> int:
216
"""The name's owner class — the planner's bucketing key, since all names
217
- of a chunk must share one producer.
218
- """
217
+ of a chunk must share one producer."""
218
return self._class_of.get(name, 0)
219
220
def owners(self, name: str) -> list[int]:
@@ -286,8 +285,7 @@ class RdtRouter:
285
def bind(self, actors: list, produce_methods: list, consumer_id: int) -> None:
286
"""Attach this consumer's producer handles. Rebuilt wholesale per init,
287
never appended to: every owner index is a position in these lists, so a
289
- rejoining engine that re-inits must not shift them.
290
- """
288
+ rejoining engine that re-inits must not shift them."""
289
if len(actors) != len(produce_methods):
290
raise ValueError("actors and produce_methods must be parallel")
291
self._actors = list(actors)
@@ -350,6 +348,5 @@ def buffer_alloc_bytes(nbytes: int, presize: int = 0) -> int:
348
optional ``presize`` floor, and a coarse 256MB round-up, so the buffer is
349
allocated ONCE and never regrows. Regrowth is a correctness hazard, not just a
350
perf one -- see ``buffer_presize_gb``. Shared by the consumer's receive buffers
353
- and the producer's serve rings.
354
- """
351
+ and the producer's serve rings."""
352
return max(nbytes, presize, -(-nbytes // (256 << 20)) * (256 << 20))
vllm/distributed/weight_transfer/sharded_rdt_engine.py
+16
-32
@@ -134,8 +134,7 @@ class _PendingPull:
134
135
``targets``/``blob`` must stay strongly referenced until it completes:
136
``set_target_for_ref`` stores WEAKREFS, so dropping them silently reroutes the
137
- transfer into a fallback buffer.
138
- """
137
+ transfer into a fallback buffer."""
138
139
ref: "Any"
140
keys: "list[FetchKey]"
@@ -562,8 +561,7 @@ class ShardedRDTWeightTransferEngine(
561
562
def _build_static_plan(self, init_info: ShardedRDTWeightTransferInitInfo) -> None:
563
"""Build the chunk/free plan once. It never changes across syncs, so
565
- ``update_weights`` needs no per-sync names.
566
- """
564
+ ``update_weights`` needs no per-sync names."""
565
if not init_info.group_lens:
566
raise ValueError(
567
"Sharded RDT engine requires init_info.group_lens (the gather-"
@@ -587,8 +585,7 @@ class ShardedRDTWeightTransferEngine(
585
Both sides are sized from the static plan: receive buffers are
586
``ring_depth`` slots at the largest chunk's ``pack_bytes``, and each bound
587
producer is asked to pre-register a serve ring at the max bytes this
590
- consumer will pull from it. A no-op when this worker has no chunks.
591
- """
588
+ consumer will pull from it. A no-op when this worker has no chunks."""
589
plan = self._cached_plan
590
if plan is None or not plan.chunks:
591
return
@@ -633,8 +630,7 @@ class ShardedRDTWeightTransferEngine(
630
``data_parallel_index``, not ``data_parallel_rank``: vLLM resets the
631
latter to 0 in a dense worker but keeps the former as the distinct global
632
DP rank. Same formula as the sibling ``nccl_engine``, so dense-via-TP and
636
- MoE-via-DP+EP both yield distinct 0..C-1.
637
- """
633
+ MoE-via-DP+EP both yield distinct 0..C-1."""
634
pc = self.parallel_config
635
return pc.data_parallel_index * pc.world_size + pc.rank # world_size = TP*PP
636
@@ -642,16 +638,14 @@ class ShardedRDTWeightTransferEngine(
638
"""Total inference-worker count. Prefers the driver-supplied
639
``init_info.num_consumers`` (authoritative -- the driver knows the whole
640
fleet); else ``world_size_across_dp``, the same stride
645
- ``_global_worker_index`` indexes with, so the two agree at any pp.
646
- """
641
+ ``_global_worker_index`` indexes with, so the two agree at any pp."""
642
if self._num_consumers_override > 0:
643
return self._num_consumers_override
644
return self.parallel_config.world_size_across_dp
645
646
def start_weight_update(self) -> None:
647
"""Put the model's params on meta so layerwise reload streams them in
653
- as each layer's slices land. Baked replay uses checkpoint format.
654
- """
648
+ as each layer's slices land. Baked replay uses checkpoint format."""
649
from vllm.model_executor.model_loader.reload import (
650
initialize_layerwise_reload,
651
)
@@ -660,8 +654,7 @@ class ShardedRDTWeightTransferEngine(
654
655
def finish_weight_update(self) -> None:
656
"""Drain the deferred pull/process pipeline (so every layer is fully
663
- loaded) before finalizing the layerwise reload.
664
- """
657
+ loaded) before finalizing the layerwise reload."""
658
from vllm.model_executor.model_loader.reload import (
659
finalize_layerwise_reload,
660
)
@@ -674,8 +667,7 @@ class ShardedRDTWeightTransferEngine(
667
device sync: post-processing is deferred to background threads and a
668
sync here would block on them and serialize the pull/process pipeline.
669
Completion is guaranteed by ``drain_pending`` in
677
- ``finish_weight_update``.
678
- """
670
+ ``finish_weight_update``."""
671
self.receive_weights(self.parse_update_info(update_info))
672
673
def receive_weights(
@@ -717,8 +709,7 @@ class ShardedRDTWeightTransferEngine(
709
device: torch.device,
710
) -> list[tuple[str, torch.Tensor]]:
711
"""Zero-storage lazies for ``names``, dtype/shape from the init metadata,
720
- all feeding the bake's recording sink.
721
- """
712
+ all feeding the bake's recording sink."""
713
return [
714
(
715
name,
@@ -986,8 +977,7 @@ class ShardedRDTWeightTransferEngine(
977
978
def _ensure_proc_worker(self) -> None:
979
"""Lazily create the per-slot events, the background CUDA stream, the work
989
- queue, and the single processing thread. Idempotent.
990
- """
980
+ queue, and the single processing thread. Idempotent."""
981
if self._proc_thread is not None:
982
return
983
import queue
@@ -1046,8 +1036,7 @@ class ShardedRDTWeightTransferEngine(
1036
def _mark_slot_done(self, slot: int) -> None:
1037
"""Publish that a queued item's read-done event has been recorded (or the
1038
item failed) so a pull waiting to reuse ``slot`` can proceed to its
1049
- CUDA-event synchronize.
1050
- """
1039
+ CUDA-event synchronize."""
1040
with self._slot_cv:
1041
self._slot_done[slot] += 1
1042
self._slot_cv.notify_all()
@@ -1063,8 +1052,7 @@ class ShardedRDTWeightTransferEngine(
1052
"""Block until the background thread has processed every queued item and
1053
its stream work is complete, then re-raise any error it hit. Called from
1054
the worker's ``finish_weight_update`` before ``finalize_layerwise_reload``
1066
- so every baked layer is fully loaded (and ``info.reset()``-ed) first.
1067
- """
1055
+ so every baked layer is fully loaded (and ``info.reset()``-ed) first."""
1056
if self._proc_queue is not None:
1057
self._proc_queue.join() # every put() item task_done()'d
1058
# The scatter thread feeds the quant thread, so join it SECOND (all
@@ -1116,8 +1104,7 @@ class ShardedRDTWeightTransferEngine(
1104
which is exactly what an owner class is. The cut is a pure function of
1105
the bake and the ownership table. Copy order within a chunk is bake
1106
order, and a module's copies may span chunks (materialize/quant fire on
1119
- its first/last chunk; see ``_build_call_plan``).
1120
- """
1107
+ its first/last chunk; see ``_build_call_plan``)."""
1108
assert self._router is not None
1109
by_class: dict[int, list[_Scatter]] = {}
1110
for copies in modules:
@@ -1248,8 +1235,7 @@ class ShardedRDTWeightTransferEngine(
1235
pulls nothing from. Refs are held and drained in ``drain_pending`` so
1236
every signal has EXECUTED before the sync ends: ``begin_sync`` resets
1237
the counters, and a straggler landing in the next sync would credit a
1251
- group it does not belong to.
1252
- """
1238
+ group it does not belong to."""
1239
assert self._router is not None
1240
self._pending_frees.extend(self._router.free_group(group_idx))
1241
@@ -1384,8 +1370,7 @@ class ShardedRDTWeightTransferEngine(
1370
the modules' scatters via ``ready``; touches only the scattered params
1371
(never a receive slot), so it can overlap subsequent chunks' RDMA and
1372
scatters. ``info.reset()`` is what makes finalize skip the layer —
1387
- drain_pending joins the quant queue before finalize runs.
1388
- """
1373
+ drain_pending joins the quant queue before finalize runs."""
1374
from vllm.model_executor.layers.quantization.base_config import (
1375
QuantizeMethodBase,
1376
)
@@ -1418,8 +1403,7 @@ class ShardedRDTWeightTransferEngine(
1403
1404
def _quant_worker_loop(self) -> None:
1405
"""Dedicated quant thread: drains (completed_modules, scatter-done event)
1421
- batches. Errors surface via _proc_error like the scatter thread's.
1422
- """
1406
+ batches. Errors surface via _proc_error like the scatter thread's."""
1407
torch.cuda.set_device(self.device)
1408
q = self._quant_queue
1409
assert q is not None
vllm/distributed/weight_transfer/sharded_rdt_fake.py
+2
-4
@@ -206,8 +206,7 @@ class FakeRDTTensor(torch.Tensor):
206
207
def _meta(self) -> torch.Tensor:
208
"""A zero-storage meta tensor of this fake's shape/dtype, so PyTorch
209
- itself computes post-op geometry rather than us reimplementing it.
210
- """
209
+ itself computes post-op geometry rather than us reimplementing it."""
210
return torch.empty(self.shape, dtype=self.dtype, device="meta")
211
212
@classmethod
@@ -251,8 +250,7 @@ class FakeRDTTensor(torch.Tensor):
250
):
251
"""Append the op and return a child, or a tuple of children for
252
multi-return ops. Each child's geometry comes from running the op on a
254
- meta tensor.
255
- """
253
+ meta tensor."""
254
meta = self_._meta()
255
with torch._C.DisableTorchFunctionSubclass():
256
meta_result = func(meta, *args, **kwargs)
vllm/distributed/weight_transfer/sharded_rdt_trainer.py
+14
-28
@@ -132,8 +132,7 @@ PRODUCE_METHOD_NAME = "rdt_produce_weights_batched"
132
@dataclass
133
class _SharedPack:
134
"""One generation of one slot-sharing group: the rendezvous state for a
135
- single chunk, identified by the consumers' issue index.
136
- """
135
+ single chunk, identified by the consumers' issue index."""
136
137
group: int
138
slot: int
@@ -467,8 +466,7 @@ class _RDTProducerServer:
466
467
def end_sync(self) -> list[int]:
468
"""Block until every published group has been freed by its consumers;
470
- return the remaining freed keys so the engine drops its last refs.
471
- """
469
+ return the remaining freed keys so the engine drops its last refs."""
470
with self._cache_cond:
471
self._wait_for(
472
lambda: bool(self._inflight_groups),
@@ -481,8 +479,7 @@ class _RDTProducerServer:
479
480
def set_gather_error(self, message: str) -> None:
481
"""Record a trainer-side gather failure so blocked serves / publishes
484
- stop waiting and surface it.
485
- """
482
+ stop waiting and surface it."""
483
with self._cache_cond:
484
self._gather_error = RuntimeError(message)
485
self._cache_cond.notify_all()
@@ -511,8 +508,7 @@ class _RDTProducerServer:
508
def _new_serve_buffer(self, nbytes: int) -> torch.Tensor:
509
"""Allocate + NIXL-register one serve slot: the single allocation seam,
510
so registration cannot be skipped on either of the two paths that make
514
- buffers (the init-time reservation and the serve-path backstop).
515
- """
511
+ buffers (the init-time reservation and the serve-path backstop)."""
512
t = torch.empty(nbytes, dtype=torch.uint8, device=self._serve_device)
513
with self._reg_lock:
514
register_nixl_memory(t)
@@ -584,15 +580,13 @@ class _RDTProducerServer:
580
def _share_group(self, consumer_id: int) -> int:
581
"""The slot-sharing group ``consumer_id`` belongs to: its index within
582
its own deployment, since that is what fixes the plan. Without a width
587
- the group is the consumer itself and nothing is shared.
588
- """
583
+ the group is the consumer itself and nothing is shared."""
584
return consumer_id % self._share_width if self._share_width > 0 else consumer_id
585
586
def _sharers_of(self, sg: int) -> frozenset:
587
"""The LIVE consumers of group ``sg``: the rendezvous width. Derived from
588
``begin_sync``'s live set, so a degraded sync narrows the barrier instead
594
- of waiting forever on a dead deployment. Caller holds ``_cache_cond``.
595
- """
589
+ of waiting forever on a dead deployment. Caller holds ``_cache_cond``."""
590
cached = self._sharers.get(sg)
591
if cached is None:
592
if not self._sharing_active or self._live_ids is None:
@@ -628,8 +622,7 @@ class _RDTProducerServer:
622
def _await_shared_pack(self, gen: _SharedPack) -> torch.Tensor:
623
"""Block until this generation's packer published its blob, and return
624
it. A failed pack is re-raised here, so every sharer of a bad pack fails
631
- instead of reading a half-written slot.
632
- """
625
+ instead of reading a half-written slot."""
626
with self._cache_cond:
627
self._wait_for(
628
lambda: not gen.done and gen.error is None,
@@ -650,8 +643,7 @@ class _RDTProducerServer:
643
"""Group ``sg``'s ring slot ``idx``, grown if this chunk outgrew the
644
reservation. Growing registers memory while the fabric is busy, the
645
hazard ``reserve_serve_buffer`` exists to avoid, so it is a backstop: the
653
- reservation is sized from the same static plan as this pack.
654
- """
646
+ reservation is sized from the same static plan as this pack."""
647
with self._serve_lock:
648
buffer = self._serve_rings.setdefault(sg, [None] * self._nring)[idx]
649
if buffer is not None and buffer.numel() >= need:
@@ -663,8 +655,7 @@ class _RDTProducerServer:
655
656
def _fail_shared_pack(self, gen: _SharedPack, exc: BaseException) -> None:
657
"""Publish a pack failure so waiting sharers raise instead of hanging on
666
- a generation that will never complete.
667
- """
658
+ a generation that will never complete."""
659
with self._cache_cond:
660
gen.error = exc
661
self._cache_cond.notify_all()
@@ -866,8 +857,7 @@ class ShardedRDTTrainerWeightTransferEngine(
857
def _rpc(self, method: str, *args: Any) -> Any:
858
"""Call one of the server actor's methods and block for the result.
859
The single seam through which the engine talks to its server, so tests
869
- can inject a local (non-Ray) fake server.
870
- """
860
+ can inject a local (non-Ray) fake server."""
861
import ray
862
863
return ray.get(getattr(self._server, method).remote(*args))
@@ -944,8 +934,7 @@ class ShardedRDTTrainerWeightTransferEngine(
934
"""Fire publish_group WITHOUT waiting on the RPC (the gather loop
935
overlaps the publish's server-side rebuild with the next group's
936
gather) and return a handle that ``_await_publish`` resolves. Ray actor
947
- handle in production; a plain (non-Ray) fake server runs inline.
948
- """
937
+ handle in production; a plain (non-Ray) fake server runs inline."""
938
method = self._server.publish_group
939
remote = getattr(method, "remote", None)
940
if remote is not None:
@@ -956,8 +945,7 @@ class ShardedRDTTrainerWeightTransferEngine(
945
"""Resolve one async publish so a server-side rebuild error surfaces at
946
window depth instead of at end_sync. Publishes carry nothing back —
947
freed groups flow only through wait_freed/end_sync (one channel; see
959
- publish_group).
960
- """
948
+ publish_group)."""
949
import ray
950
951
if isinstance(ref, ray.ObjectRef):
@@ -1144,8 +1132,7 @@ class ShardedRDTTrainerWeightTransferEngine(
1132
by stall watchdog 300s later: consumers route pulls here, the pull
1133
passes the served-names guard, and the cache wait never completes. With
1134
it, that is an immediate error naming the weight. One set lookup per
1147
- name per sync.
1148
- """
1135
+ name per sync."""
1136
if self._held_names is None:
1137
return
1138
for name, tensor in zip(names, tensors):
@@ -1346,8 +1333,7 @@ class ShardedRDTTrainerWeightTransferEngine(
1333
credit releases when every live consumer has signaled the group). So
1334
the loop self-paces to the consumers' pull rate with at most
1335
`gather_lookahead + 1` groups resident. Runs on every rank; only the
1349
- sender has an `update_future` to fail fast on.
1350
- """
1336
+ sender has an `update_future` to fail fast on."""
1337
assert self.source is not None # guaranteed by trainer_init
1338
# The live IDS ride along with the count: the free barrier needs only
1339
# the count, but the slot-sharing rendezvous needs to know WHICH
vllm/distributed/weight_transfer/sparse_nccl_engine.py
+2
-4
@@ -68,8 +68,7 @@ class SparseNCCLTrainerInitInfo(TrainerInitInfo):
68
69
Same rendezvous shape as the dense NCCL backend (the sender opens its
70
endpoint as NCCL rank 0), but with no packed wire params: sparse transfers
71
- are never packed. `backend` is the factory dispatch key.
72
- """
71
+ are never packed. `backend` is the factory dispatch key."""
72
73
backend: ClassVar[str] = "sparse_nccl"
74
@@ -368,8 +367,7 @@ class SparseNCCLTrainerWeightTransferEngine(
367
rebuild or free the patch tensors as soon as a send method returns rather
368
than relying on same-stream ordering. See
369
`NCCLTrainerWeightTransferEngine._post_send_sync` for why there is no
371
- cross-rank barrier.
372
- """
370
+ cross-rank barrier."""
371
if torch.cuda.is_available():
372
torch.cuda.current_stream().synchronize()
373
vllm/entrypoints/cli/main.py
+1
-2
@@ -3,8 +3,7 @@
3
"""The CLI entrypoints of vLLM.
4
5
Note that all future modules must be lazily loaded within main
6
-to avoid certain eager import breakage.
7
-"""
6
+to avoid certain eager import breakage."""
7
8
import importlib.metadata
9
import sys
vllm/entrypoints/generate/base/serving.py
+1
-2
@@ -295,8 +295,7 @@ class GenerateBaseServing(BaseServing, BeamSearchOnlineMixin):
295
) -> _T:
296
"""Wrap a `create_*` coroutine so that, if it raises or returns an
297
ErrorResponse (i.e. the request never reached the engine), the KV
298
- connector is notified to free any pinned remote-prefill blocks.
299
- """
298
+ connector is notified to free any pinned remote-prefill blocks."""
299
kv_transfer_params = self.has_kv_connector and request.kv_transfer_params
300
if not kv_transfer_params or not kv_transfer_params.get("do_remote_prefill"):
301
return await awaitable
vllm/entrypoints/openai/models/serving.py
+2
-4
@@ -123,8 +123,7 @@ class OpenAIServingModels:
123
124
async def init_static_loras(self):
125
"""Loads all static LoRA modules.
126
- Raises if any fail to load
127
- """
126
+ Raises if any fail to load"""
127
if self.static_lora_modules is None:
128
return
129
for lora in self.static_lora_modules:
@@ -149,8 +148,7 @@ class OpenAIServingModels:
148
149
async def show_available_models(self) -> ModelList:
150
"""Show available models. This includes the base model and all
152
- adapters.
153
- """
151
+ adapters."""
152
model_list = await self.registry.show_available_models()
153
lora_cards = [
154
ModelCard(
vllm/entrypoints/openai/responses/context.py
+1
-2
@@ -408,8 +408,7 @@ class ParsableContext(ConversationContext):
408
409
def need_builtin_tool_call(self) -> bool:
410
"""Return true if the last message is a builtin tool call
411
- that the request has enabled.
412
- """
411
+ that the request has enabled."""
412
last_message = self.response_messages[-1]
413
if last_message.type != "function_call":
414
return False
vllm/entrypoints/openai/responses/harmony.py
+1
-2
@@ -52,8 +52,7 @@ logger = init_logger(__name__)
52
53
def _parse_harmony_format_message(chat_msg: dict) -> Message:
54
"""Reconstruct a Message from Harmony-format dict,
55
- preserving channel, recipient, and content_type.
56
- """
55
+ preserving channel, recipient, and content_type."""
56
author_dict = chat_msg["author"]
57
role = author_dict.get("role")
58
name = author_dict.get("name")
vllm/entrypoints/openai/responses/protocol.py
+1
-2
@@ -117,8 +117,7 @@ def serialize_messages(msgs):
117
118
class ResponseRawMessageAndToken(OpenAIBaseModel):
119
"""Class to show the raw message.
120
- If message / tokens diverge, tokens is the source of truth
121
- """
120
+ If message / tokens diverge, tokens is the source of truth"""
121
122
message: str
123
tokens: list[int]
vllm/entrypoints/pooling/pooling/io_processor.py
+1
-2
@@ -44,8 +44,7 @@ class PluginWithoutIOProcessorPlugins(PoolingIOProcessor):
44
45
class PluginWithIOProcessorPlugins(PoolingIOProcessor):
46
"""IO Processor plugins are a feature that allows pre- and post-processing
47
- of the model input and output for pooling models.
48
- """
47
+ of the model input and output for pooling models."""
48
49
name = "plugin"
50
vllm/entrypoints/scale_out/token_in_token_out/mm_serde.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Encode/decode utilities for multimodal tensors and field metadata
4
-over JSON/HTTP, used by the disaggregated generate endpoint.
5
-"""
4
+over JSON/HTTP, used by the disaggregated generate endpoint."""
5
6
from __future__ import annotations
7
vllm/entrypoints/serve/exception_handling/handlers/validation.py
+1
-2
@@ -126,8 +126,7 @@ def _format_error(err: object) -> str:
126
127
def _is_internal_loc_segment(segment: str) -> bool:
128
"""True if `segment` is a Pydantic-internal wrapper/union-branch
129
- marker rather than a user-meaningful field name or list index.
130
- """
129
+ marker rather than a user-meaningful field name or list index."""
130
if _BRACKETED_INTERNAL_RE.search(segment):
131
return True
132
return segment.lower() in _INTERNAL_LOC_MARKERS
vllm/entrypoints/serve/lora/api_router.py
+2
-4
@@ -63,8 +63,7 @@ def _attach_router(app: FastAPI):
63
@router.post("/v1/load_lora_adapter", dependencies=[Depends(validate_json_request)])
64
async def load_lora_adapter(request: LoadLoRAAdapterRequest, raw_request: Request):
65
"""Handle POST /v1/load_lora_adapter: load a LoRA adapter into the
66
- serving engine.
67
- """
66
+ serving engine."""
67
handler: OpenAIServingModels = models(raw_request)
68
response = await handler.load_lora_adapter(request)
69
if isinstance(response, ErrorResponse):
@@ -86,8 +85,7 @@ def _attach_router(app: FastAPI):
85
request: UnloadLoRAAdapterRequest, raw_request: Request
86
):
87
"""Handle POST /v1/unload_lora_adapter: unload a LoRA adapter from
89
- the serving engine.
90
- """
88
+ the serving engine."""
89
handler: OpenAIServingModels = models(raw_request)
90
response = await handler.unload_lora_adapter(request)
91
if isinstance(response, ErrorResponse):
vllm/entrypoints/serve/sagemaker/api_router.py
+2
-4
@@ -30,8 +30,7 @@ EndpointFn = Callable[[RequestType, Request], Awaitable[Any]]
30
def _snapshot_handler_levels() -> list[tuple[logging.Handler, int]]:
31
"""Snapshot handler levels for loggers that may be affected by third-party
32
logging configuration side effects (e.g. model_hosting_container_standards
33
- calling configure_root_logger() at import time).
34
- """
33
+ calling configure_root_logger() at import time)."""
34
loggers = [logging.getLogger(), logging.getLogger("vllm")]
35
seen: set[int] = set()
36
snapshot: list[tuple[logging.Handler, int]] = []
@@ -74,8 +73,7 @@ def _attach_router(
73
model_config: ModelConfig | None = None,
74
):
75
"""Register the SageMaker hosting routes (/ping, /invocations) on the
77
- app.
78
- """
76
+ app."""
77
import model_hosting_container_standards.sagemaker as sagemaker_standards
78
79
router = APIRouter()
vllm/entrypoints/serve/utils/fingerprint.py
+2
-4
@@ -33,8 +33,7 @@ def set_default_fingerprint_mode(
33
custom_value: str | None = None,
34
) -> None:
35
"""Configure the fingerprint mode for subsequent ``get_system_fingerprint``
36
- calls. Called once at server startup.
37
- """
36
+ calls. Called once at server startup."""
37
global _DEFAULT_MODE, _CUSTOM_VALUE
38
_DEFAULT_MODE = mode
39
_CUSTOM_VALUE = custom_value
@@ -42,8 +41,7 @@ def set_default_fingerprint_mode(
41
42
def get_system_fingerprint(vllm_config: Any) -> str | None:
43
"""Return the fingerprint for ``vllm_config`` using the mode configured by
45
- ``set_default_fingerprint_mode``.
46
- """
44
+ ``set_default_fingerprint_mode``."""
45
return build_system_fingerprint(vllm_config, _DEFAULT_MODE, _CUSTOM_VALUE)
46
47
vllm/entrypoints/speech_to_text/base/serving.py
+2
-4
@@ -92,8 +92,7 @@ def asr_inter_chunk_separator(
92
93
class SpeechToTextBaseServing(GenerateBaseServing):
94
"""Base class for speech-to-text operations like transcription and
95
- translation.
96
- """
95
+ translation."""
96
97
def __init__(
98
self,
@@ -427,8 +426,7 @@ class SpeechToTextBaseServing(GenerateBaseServing):
426
stream_generator_method: Callable[..., AsyncGenerator[str, None]],
427
) -> T | V | AsyncGenerator[str, None] | ErrorResponse:
428
"""Base method for speech-to-text operations like transcription and
430
- translation.
431
- """
429
+ translation."""
430
if request.stream and request.use_beam_search:
431
return self.create_error_response(
432
"Streaming is not currently supported with beam search"
vllm/env_override.py
+1
-2
@@ -581,8 +581,7 @@ _constrain_to_fx_strides_patched = False
581
def _apply_constrain_to_fx_strides_patch():
582
"""Patch lowering.constrain_to_fx_strides globally. Safe to call
583
multiple times; only the first call does anything.
584
- Only applies for torch >= 2.11 and < 2.12.
585
- """
584
+ Only applies for torch >= 2.11 and < 2.12."""
585
global _constrain_to_fx_strides_patched
586
if _constrain_to_fx_strides_patched:
587
return
vllm/envs.py
+1
-2
@@ -2249,8 +2249,7 @@ def compile_factors() -> dict[str, object]:
2249
"""Return env vars used for torch.compile cache keys.
2250
2251
Start with every known vLLM env var; drop entries in `ignored_factors`;
2252
- hash everything else. This keeps the cache key aligned across workers.
2253
- """
2252
+ hash everything else. This keeps the cache key aligned across workers."""
2253
ignored_factors: set[str] = {
2254
"MAX_JOBS",
2255
"VLLM_RPC_BASE_PATH",
vllm/forward_context.py
+1
-2
@@ -209,8 +209,7 @@ def is_forward_context_available() -> bool:
209
210
def in_piecewise_cudagraph() -> bool:
211
"""Whether the current forward runs in piecewise cudagraph mode (graph
212
- segments separated by eager breaks), at capture or replay time.
213
- """
212
+ segments separated by eager breaks), at capture or replay time."""
213
return (
214
is_forward_context_available()
215
and get_forward_context().cudagraph_runtime_mode == CUDAGraphMode.PIECEWISE
vllm/logger.py
+1
-2
@@ -216,8 +216,7 @@ def _configure_vllm_root_logger() -> None:
216
def init_logger(name: str) -> _VllmLogger:
217
"""The main purpose of this function is to ensure that loggers are
218
retrieved in such a way that we can be sure the root vllm logger has
219
- already been configured.
220
- """
219
+ already been configured."""
220
logger = logging.getLogger(name)
221
222
for method_name, method in _METHODS_TO_PATCH.items():
vllm/lora/layers/column_parallel_linear.py
+1
-2
@@ -733,8 +733,7 @@ class MergedColumnParallelLinearVariableSliceWithLoRA(
733
lora_b: torch.Tensor | list[torch.Tensor],
734
):
735
"""Override to handle single tensor weights
736
- that need to be split into slices.
737
- """
736
+ that need to be split into slices."""
737
self.reset_lora(index)
738
739
# Handle case where checkpoint has single tensor weights
vllm/lora/lora_model.py
+1
-2
@@ -90,8 +90,7 @@ class LoRAModel:
90
def clone(self, lora_model_id: int) -> "LoRAModel":
91
"""Return a copy of the object with different ids.
92
93
- Will share the underlying tensors.
94
- """
93
+ Will share the underlying tensors."""
94
return self.__class__(
95
lora_model_id,
96
rank=self.rank,
vllm/lora/worker_manager.py
+3
-6
@@ -28,8 +28,7 @@ class WorkerLoRAManager:
28
"""WorkerLoRAManager that manages LoRA models on the worker side.
29
30
Every request, the requested LoRAs will be loaded (unless they are already
31
- loaded), and every other LoRA will be unloaded.
32
- """
31
+ loaded), and every other LoRA will be unloaded."""
32
33
_manager_cls: type[LoRAModelManager] = LoRAModelManager
34
@@ -75,8 +74,7 @@ class WorkerLoRAManager:
74
@contextmanager
75
def dummy_lora_cache(self):
76
"""Use this context manager to reuse the dummy lora model
78
- to avoid creating it repeatedly.
79
- """
77
+ to avoid creating it repeatedly."""
78
self._cached_dummy_lora = None
79
yield
80
self._cached_dummy_lora = False
@@ -251,8 +249,7 @@ class LRUCacheWorkerLoRAManager(WorkerLoRAManager):
249
250
Uses an LRU Cache. Every request, the requested LoRAs will be loaded
251
(unless they are already loaded) and least recently used LoRAs will
254
- be unloaded if the cache is above capacity.
255
- """
252
+ be unloaded if the cache is above capacity."""
253
254
_manager_cls: type[LRUCacheLoRAModelManager] = LRUCacheLoRAModelManager
255
vllm/model_executor/hw_agnostic/custom_op.py
+1
-2
@@ -135,8 +135,7 @@ class CustomOp(nn.Module):
135
136
def forward_native(self, *args, **kwargs):
137
"""PyTorch-native implementation; OOT plugins override via
138
- :meth:`forward_oot`.
139
- """
138
+ :meth:`forward_oot`."""
139
raise NotImplementedError
140
141
def forward_oot(self, *args, **kwargs):
vllm/model_executor/hw_agnostic/layers/layernorm.py
+1
-2
@@ -10,8 +10,7 @@ from vllm.model_executor.hw_agnostic.custom_op import CustomOp
10
@CustomOp.register("rms_norm")
11
class RMSNorm(CustomOp):
12
"""``x -> w * x / sqrt(E[x^2] + eps)``. With ``residual``, fuses
13
- ``residual += x`` then RMSNorm and returns ``(normalized, residual)``.
14
- """
13
+ ``residual += x`` then RMSNorm and returns ``(normalized, residual)``."""
14
15
def __init__(
16
self,
vllm/model_executor/kernels/linear/__init__.py
+4
-8
@@ -881,8 +881,7 @@ def choose_mp_linear_kernel(
881
882
def init_mxfp8_linear_kernel(*, bmm_batch_size: int | None = None) -> Mxfp8LinearKernel:
883
"""Select and instantiate the best MXFP8 linear kernel for the
884
- current platform.
885
- """
884
+ current platform."""
885
config = Mxfp8LinearLayerConfig(bmm_batch_size=bmm_batch_size)
886
887
platform = current_platform._enum
@@ -934,8 +933,7 @@ def init_mxfp4_linear_kernel(
933
activation_quant_key: QuantKey | None = None,
934
) -> MxFp4LinearKernel:
935
"""Select and instantiate the best MXFP4 linear kernel for the
937
- current platform.
938
- """
936
+ current platform."""
937
config = MxFp4LinearLayerConfig(
938
activation_quant_key=activation_quant_key,
939
)
@@ -982,8 +980,7 @@ def init_mxfp6_linear_kernel(
980
activation_quant_key: QuantKey | None = None,
981
) -> MxFp6LinearKernel:
982
"""Select and instantiate the best MXFP6 linear kernel for the
985
- current platform.
986
- """
983
+ current platform."""
984
config = MxFp6LinearLayerConfig(
985
weight_quant_key=weight_quant_key,
986
activation_quant_key=activation_quant_key,
@@ -1071,8 +1068,7 @@ def init_wfp8_a16_linear_kernel(
1068
1069
def init_nvfp4_linear_kernel(use_a16: bool = False) -> NvFp4LinearKernel:
1070
"""Select and instantiate the best NVFP4 linear kernel for the
1074
- current platform.
1075
- """
1071
+ current platform."""
1072
config = NvFp4LinearLayerConfig()
1073
a16_kernels = (
1074
FlashInferCuteDslNvFp4W4A16LinearKernel,
vllm/model_executor/kernels/linear/nvfp4/flashinfer.py
+1
-2
@@ -177,8 +177,7 @@ class FlashInferCutlassNvFp4LinearKernel(NvFp4LinearKernel):
177
178
def input_quant_key(self) -> QuantKey | None:
179
"""This kernel supports dynamic quantization of the input. By
180
- convention, pre-quantized blockscales must use the swizzled layout.
181
- """
180
+ convention, pre-quantized blockscales must use the swizzled layout."""
181
return kNvfp4Dynamic
182
183
@classmethod
vllm/model_executor/kernels/linear/scaled_mm/BlockScaledMMLinearKernel.py
+1
-2
@@ -41,8 +41,7 @@ class FP8BlockParams(FP8Params):
41
@property
42
def block_scale_attr(self) -> str:
43
"""Fp8LinearMethod registers the block scale as ``weight_scale_inv``,
44
- compressed-tensors as ``weight_scale``.
45
- """
44
+ compressed-tensors as ``weight_scale``."""
45
return (
46
self.WEIGHT_SCALE
47
if self.weight_scale_inv is None
vllm/model_executor/kernels/linear/scaled_mm/cutlass.py
+2
-4
@@ -174,8 +174,7 @@ class CutlassFP8ScaledMMLinearKernel(FP8ScaledMMLinearKernel):
174
175
def input_quant_key(self) -> QuantKey | None:
176
"""Only static per-tensor activation quantization is supported for external
177
- quantization.
178
- """
177
+ quantization."""
178
if self.config.activation_quant_key == kFp8StaticTensorSym:
179
return kFp8StaticTensorSym
180
return None
@@ -185,8 +184,7 @@ class CutlassFP8ScaledMMLinearKernel(FP8ScaledMMLinearKernel):
184
x: torch.Tensor, dim: int, alignment: int, value: float = 0.0
185
) -> torch.Tensor:
186
"""Pad tensor ``x`` along ``dim`` to the next multiple of
188
- ``alignment``.
189
- """
187
+ ``alignment``."""
188
remainder = x.shape[dim] % alignment
189
if remainder == 0:
190
return x
vllm/model_executor/layers/activation.py
+1
-2
@@ -804,8 +804,7 @@ _ACTIVATION_REGISTRY = LazyDict(
804
805
def _get_gelu_pytorch_tanh() -> nn.Module:
806
"""Get PyTorch GELU with tanh approximation, with ROCm fallback
807
- and fast GELU for ARM.
808
- """
807
+ and fast GELU for ARM."""
808
if current_platform.is_rocm():
809
# TODO:[ROCm] PyTorch native GELU with tanh is unstable with torch.compile
810
logger.warning_once(
vllm/model_executor/layers/attention/mla_attention.py
+1
-2
@@ -1568,8 +1568,7 @@ class MLACommonBackend(AttentionBackend):
1568
@classmethod
1569
def customize_spec(cls, spec: "AttentionSpec") -> "AttentionSpec":
1570
"""Per-token-head modes pack an inline fp32 scale pair after the
1571
- latent data (single-sided: ``head_size_v == 0`` for MLA).
1572
- """
1571
+ latent data (single-sided: ``head_size_v == 0`` for MLA)."""
1572
spec = super().customize_spec(spec)
1573
mode = spec.kv_quant_mode
1574
if spec.state_content_bytes is not None or not mode.is_per_token_head:
vllm/model_executor/layers/fused_allreduce_gemma_rms_norm.py
+1
-2
@@ -55,8 +55,7 @@ _FI_SUPPORTED_DTYPES = (torch.bfloat16, torch.float16)
55
56
def _max_token_num(tp_size: int, hidden_size: int, dtype: torch.dtype) -> int | None:
57
"""Workspace token budget for flashinfer fused all-reduce, or None if the
58
- current world size / device is unsupported. Mirrors ``FlashInferAllReduce``.
59
- """
58
+ current world size / device is unsupported. Mirrors ``FlashInferAllReduce``."""
59
from vllm.config.compilation import PassConfig
60
61
max_size_mb = PassConfig.default_fi_allreduce_fusion_max_size_mb().get(tp_size)
vllm/model_executor/layers/fused_embed_norm.py
+1
-2
@@ -170,8 +170,7 @@ def _fused_embed_eh_norm_kernel(
170
``table[ids]``, zero it at position 0, RMSNorm(embed) with enorm and
171
RMSNorm(prev_hidden) with hnorm, written side-by-side into ``out`` ([N, 2H])
172
ready for the eh_proj GEMM. Replaces embedding lookup + where + 2x RMSNorm +
173
- cat. Requires the full table on-rank (replicated embedding).
174
- """
173
+ cat. Requires the full table on-rank (replicated embedding)."""
174
tok = tl.program_id(0)
175
off = tl.arange(0, BLOCK)
176
mask = off < H
vllm/model_executor/layers/fused_moe/activation.py
+1
-2
@@ -56,8 +56,7 @@ class MoEActivation(Enum):
56
@property
57
def custom_op_name(self) -> str:
58
"""Maps to the CustomOp name of activations
59
- in vllm/model_executor/layers/activation.py.
60
- """
59
+ in vllm/model_executor/layers/activation.py."""
60
return _CUSTOM_OP_NAMES[self]
61
62
def without_mul(self) -> "MoEActivation":
vllm/model_executor/layers/fused_moe/experts/aiter_mxfp8_moe.py
+1
-2
@@ -36,8 +36,7 @@ def is_aiter_mxfp8_moe_available() -> bool:
36
nightly lacking #3811 would wrongly select FlyDSL instead of falling back to
37
the native Triton dot_scaled path. #3811 added no probe-able public symbol,
38
so detect the ``minimax_m3_mxfp8`` tuned config it shipped. Every check fails
39
- closed (returns False -> triton dot_scaled), which is always safe.
40
- """
39
+ closed (returns False -> triton dot_scaled), which is always safe."""
40
if not (current_platform.is_rocm() and current_platform.supports_mx()):
41
return False
42
try:
vllm/model_executor/layers/fused_moe/experts/cpu_moe.py
+3
-6
@@ -192,8 +192,7 @@ class CPUUnquantizedExperts(mk.FusedMoEExpertsModular):
192
193
def _pad_moe_intermediate(self, layer: torch.nn.Module) -> None:
194
"""Zero-pad the per-partition MoE intermediate dim of both weights and
195
- the expert bias, see `_padded_intermediate_size`.
196
- """
195
+ the expert bias, see `_padded_intermediate_size`."""
196
intermediate_size = self.moe_config.intermediate_size_per_partition
197
padded_size = self._padded_intermediate_size(self.moe_config)
198
if padded_size == intermediate_size:
@@ -953,8 +952,7 @@ class CPUExpertsInt4(mk.FusedMoEExpertsModular):
952
953
class CPUExpertsInt8(mk.FusedMoEExpertsModular):
954
"""CPU INT8 W8A8 per-channel weight / dynamic per-token activation
956
- modular MoE experts.
957
- """
955
+ modular MoE experts."""
956
957
def __init__(
958
self,
@@ -1287,8 +1285,7 @@ class ArmCPUExpertsInt8(mk.FusedMoEExpertsModular):
1285
1286
class ZenCPUExpertsInt8(mk.FusedMoEExpertsModular):
1287
"""AMD Zen INT8 MoE with per-token activation and channelwise weight
1290
- quantization, dispatched through zentorch.
1291
- """
1288
+ quantization, dispatched through zentorch."""
1289
1290
def __init__(
1291
self,
vllm/model_executor/layers/fused_moe/experts/mxfp8_native_moe.py
+1
-2
@@ -34,8 +34,7 @@ from vllm.triton_utils import tl, triton
34
35
def _select_cfg(M, N, K, block_m):
36
"""Pick the launch config from host constants only (M=num_valid_tokens, N, K,
37
- block_m) — graph-capture safe (no GPU-scalar branch).
38
- """
37
+ block_m) — graph-capture safe (no GPU-scalar branch)."""
38
# Per-regime winners (measured, isolated cuda-event A/B on gfx950, GPU 3):
39
# BLOCK_K=256 (fewer K-iters + bigger MX scale-load coalesced with the dot),
40
# num_stages=2 (software-pipeline overlaps the E8M0 scale-load with the scaled
vllm/model_executor/layers/fused_moe/oracle/base.py
+5
-10
@@ -55,28 +55,24 @@ class MoEKernelOracle(ABC, Generic[BackendT]):
55
@abstractmethod
56
def backend_enum_cls(self) -> type[BackendT]:
57
"""Return the concrete `Enum` class enumerating this oracle's
58
- backends (e.g. `UnquantizedMoeBackend`, `Fp8MoeBackend`).
59
- """
58
+ backends (e.g. `UnquantizedMoeBackend`, `Fp8MoeBackend`)."""
59
60
@abstractmethod
61
def get_priority_backends(self, moe_config: FusedMoEConfig) -> list[BackendT]:
62
"""Return platform-appropriate backends in priority order for
64
- this `moe_config`.
65
- """
63
+ this `moe_config`."""
64
65
@abstractmethod
66
def backend_to_kernel_cls(
67
self, backend: BackendT
68
) -> list[type[mk.FusedMoEExperts]]:
69
"""Map a backend enum value to its concrete `FusedMoEExperts`
72
- subclasses, in selection priority order.
73
- """
70
+ subclasses, in selection priority order."""
71
72
@abstractmethod
73
def map_backend(self, runner_backend: MoEBackend) -> BackendT:
74
"""Map a user-facing `MoEBackend` (from the runner config) to
78
- this oracle's enum.
79
- """
75
+ this oracle's enum."""
76
77
@abstractmethod
78
def select_backend(
@@ -108,8 +104,7 @@ class MoEKernelOracle(ABC, Generic[BackendT]):
104
routing_tables: tuple[torch.Tensor, torch.Tensor, torch.Tensor] | None = None,
105
) -> mk.FusedMoEKernel:
106
"""Construct the `FusedMoEKernel` (Prepare/Finalize + Experts
111
- combinator) for the chosen backend.
112
- """
107
+ combinator) for the chosen backend."""
108
109
def convert_to_kernel_format(
110
self,
vllm/model_executor/layers/fused_moe/oracle/fp8.py
+1
-2
@@ -451,8 +451,7 @@ def _humming_fp8_weight_schema(
451
layer: RoutedExperts, weight: torch.Tensor, weight_scale: torch.Tensor
452
) -> dict[str, Any]:
453
"""Build the humming weight schema from the canonical on-device fp8/mxfp8
454
- tensors (scale dtype/shape, block size), not the producing quant method.
455
- """
454
+ tensors (scale dtype/shape, block size), not the producing quant method."""
455
# mxfp8: e8m0 group-32 scales (stored as uint8 bytes or e8m0). humming has
456
# no compressed-tensors mxfp8 loader; its modelopt schema fits both sources.
457
if weight_scale.dtype in (torch.uint8, torch.float8_e8m0fnu):
vllm/model_executor/layers/fused_moe/oracle/int8.py
+1
-2
@@ -224,8 +224,7 @@ def _humming_int8_weight_schema(
224
weight: torch.Tensor, weight_scale: torch.Tensor
225
) -> dict[str, Any]:
226
"""Build the humming compressed-tensors int8 schema from the canonical
227
- on-device tensors; humming does the signed-int8 -> native conversion.
228
- """
227
+ on-device tensors; humming does the signed-int8 -> native conversion."""
228
config: dict[str, Any] = {
229
"quant_method": "compressed-tensors",
230
"format": "int-quantized",
vllm/model_executor/layers/fused_moe/oracle/int_wna16.py
+2
-4
@@ -512,8 +512,7 @@ def _process_weights_flashinfer(
512
513
def _pad_w13_shard_cols(x: torch.Tensor, unit: int, padded_unit: int) -> torch.Tensor:
514
"""Zero-pad each of the two gate/up shards of a ``(E, rows, 2 * unit)``
515
- tensor along its last dim, from ``unit`` to ``padded_unit`` columns.
516
- """
515
+ tensor along its last dim, from ``unit`` to ``padded_unit`` columns."""
516
if padded_unit == unit:
517
return x
518
e, rows, _ = x.shape
@@ -1081,8 +1080,7 @@ def _humming_wna16_weight_schema(
1080
quant_config: QuantizationConfig | QuantizationArgs | None,
1081
) -> dict[str, Any]:
1082
"""Humming weight schema for a WNA16 checkpoint, derived from the quant
1084
- config rather than the running kernel.
1085
- """
1083
+ config rather than the running kernel."""
1084
from vllm.model_executor.layers.quantization.auto_awq import AutoAWQConfig
1085
from vllm.model_executor.layers.quantization.auto_gptq import AutoGPTQConfig
1086
vllm/model_executor/layers/fused_moe/oracle/mxfp4.py
+3
-6
@@ -331,8 +331,7 @@ def map_mxfp4_backend(runner_backend: MoEBackend) -> list[Mxfp4MoeBackend]:
331
332
def _get_priority_backends_for_gpt_oss() -> list[Mxfp4MoeBackend]:
333
"""Available backends in priority order, BF16-act variant before
334
- activation-quantized variant within each vendor family.
335
- """
334
+ activation-quantized variant within each vendor family."""
335
_AVAILABLE_BACKENDS = [
336
Mxfp4MoeBackend.FLASHINFER_TRTLLM_MXFP4_BF16,
337
Mxfp4MoeBackend.FLASHINFER_TRTLLM_MXFP4_MXFP8,
@@ -411,8 +410,7 @@ def _resolve_activation_key(
410
model_activation_key: QuantKey | None,
411
) -> QuantKey | None:
412
"""Combine the model-supplied activation key with the user override.
414
- Raises on conflict (both set and disagreeing).
415
- """
413
+ Raises on conflict (both set and disagreeing)."""
414
user_override = _user_moe_activation_override()
415
if user_override is None:
416
return model_activation_key
@@ -462,8 +460,7 @@ def _filter_by_activation(
460
) -> list[Mxfp4MoeBackend]:
461
"""Pick variants matching ``requested_activation_key``; without one,
462
prefer BF16 if the list has any, else keep the list as-is so explicit
465
- non-BF16 picks (e.g. the ``_afp8`` aliases) still land.
466
- """
463
+ non-BF16 picks (e.g. the ``_afp8`` aliases) still land."""
464
if requested_activation_key is not None:
465
return [
466
b
vllm/model_executor/layers/fused_moe/router/zero_expert_router.py
+1
-2
@@ -71,8 +71,7 @@ class ZeroExpertRouter(BaseRouter):
71
input_ids: torch.Tensor | None = None,
72
) -> tuple[torch.Tensor, torch.Tensor]:
73
"""Compute routing with full bias, compute zero expert output,
74
- mask zero expert IDs.
75
- """
74
+ mask zero expert IDs."""
75
topk_weights, topk_ids = fused_topk_bias(
76
hidden_states=hidden_states,
77
gating_output=router_logits,
vllm/model_executor/layers/indexer_topk.py
+3
-6
@@ -163,8 +163,7 @@ class SparseIndexerTopk(torch.nn.Module):
163
) -> str:
164
"""Resolve the decode top-k implementation from the configured
165
backend ("auto" = the pre-existing chain, or a validated explicit
166
- value).
167
- """
166
+ value)."""
167
if self._backend == "auto":
168
return self._resolve_auto(logits, topk_tokens, num_rows)
169
@@ -211,8 +210,7 @@ class SparseIndexerTopk(torch.nn.Module):
210
self, logits: torch.Tensor, topk_tokens: int, num_rows: int
211
) -> str:
212
"""The pre-existing priority chain: cooperative -> persistent ->
214
- per_row. deep_select/flashinfer/torch are opt-in only.
215
- """
213
+ per_row. deep_select/flashinfer/torch are opt-in only."""
214
if not self._cooperative_constraints(logits, topk_tokens, num_rows):
215
return "cooperative"
216
if self._is_cuda and topk_tokens in (512, 1024, 2048):
@@ -274,8 +272,7 @@ class SparseIndexerTopk(torch.nn.Module):
272
max_seq_len: int,
273
) -> None:
274
"""Run the resolved decode top-k implementation, writing into
277
- topk_indices (int32, -1 fill for rows shorter than topk_tokens).
278
- """
275
+ topk_indices (int32, -1 fill for rows shorter than topk_tokens)."""
276
backend = self.resolve_backend(logits, topk_tokens, logits.shape[0])
277
if backend == "deep_select":
278
row_ends = self._row_ends(seq_lens, next_n, logits.shape[0])
vllm/model_executor/layers/linear.py
+1
-2
@@ -158,8 +158,7 @@ class LinearMethodBase(QuantizeMethodBase):
158
bias: torch.Tensor | None = None,
159
) -> torch.Tensor:
160
"""Apply the weights in layer to the input tensor.
161
- Expects create_weights to have been called before on the layer.
162
- """
161
+ Expects create_weights to have been called before on the layer."""
162
raise NotImplementedError
163
164
vllm/model_executor/layers/mamba/gdn/qwen_gdn_linear_attn.py
+1
-2
@@ -861,8 +861,7 @@ class QwenGatedDeltaNetAttention(GatedDeltaNetAttention):
861
hidden_states: torch.Tensor,
862
) -> torch.Tensor:
863
"""ROCm forward using AITER Triton fused projection+attention when
864
- available, otherwise falling back to the generic CUDA path.
865
- """
864
+ available, otherwise falling back to the generic CUDA path."""
865
if GDN_AITER_TRITON_AVAILABLE:
866
num_tokens = hidden_states.size(0)
867
projected_states_qkvz, _ = self.in_proj_qkvz(hidden_states)
vllm/model_executor/layers/mamba/mamba_utils.py
+1
-2
@@ -261,8 +261,7 @@ class MambaStateShapeCalculator:
261
@classmethod
262
def extra_groups_for_head_shards(cls, ngroups: int, tp_size: int):
263
"""Compute the increase in group numbers to account for
264
- replication in order to accompany the head shards.
265
- """
264
+ replication in order to accompany the head shards."""
265
# in the case ngoups % tp_size == 0, this will be zero
266
if ngroups % tp_size == 0:
267
return 0
vllm/model_executor/layers/mamba/ops/mamba_ssm.py
+2
-4
@@ -59,8 +59,7 @@ def get_ssm_device_name() -> str:
59
60
def _canonical_cache_dtype(cache_dtype: str) -> str:
61
"""Canonical key for config lookup. bf16 and fp16 share the same tuned
62
- configs because the kernel only sees bit width when accessing state.
63
- """
62
+ configs because the kernel only sees bit width when accessing state."""
63
return "float16" if cache_dtype == "bfloat16" else cache_dtype
64
65
@@ -161,8 +160,7 @@ _ssm_config_override: tuple[int, int] | None = None
160
@contextmanager
161
def override_ssm_config(config: tuple[int, int]):
162
"""Pin ``try_get_optimal_ssm_config`` to ``config`` for the duration of
164
- the context. Used by the tuning benchmark to time specific configs.
165
- """
163
+ the context. Used by the tuning benchmark to time specific configs."""
164
global _ssm_config_override
165
prev = _ssm_config_override
166
_ssm_config_override = config
vllm/model_executor/layers/minimax_rms_norm/lamport_workspace.py
+1
-2
@@ -210,8 +210,7 @@ class LamportWorkspace:
210
@property
211
def workspace(self) -> torch.Tensor:
212
"""Device tensor (int64) that can be passed to the kernel
213
- as ``void** workspace``.
214
- """
213
+ as ``void** workspace``."""
214
return self._workspace
215
216
# ------------------------------------------------------------------
vllm/model_executor/layers/quantization/base_config.py
+4
-8
@@ -46,24 +46,21 @@ class QuantizeMethodBase(ABC):
46
):
47
"""Create weights for a layer.
48
49
- The weights will be set as attributes of the layer.
50
- """
49
+ The weights will be set as attributes of the layer."""
50
raise NotImplementedError
51
52
@abstractmethod
53
def apply(self, layer: torch.nn.Module, *args, **kwargs) -> torch.Tensor:
54
"""Apply the weights in layer to the input tensor.
55
57
- Expects create_weights to have been called before on the layer.
58
- """
56
+ Expects create_weights to have been called before on the layer."""
57
raise NotImplementedError
58
59
# Not required functions
60
def embedding(self, layer: torch.nn.Module, *args, **kwargs) -> torch.Tensor:
61
"""Gather embeddings in the layer based on indices in the input tensor.
62
65
- Expects create_weights to have been called before on the layer.
66
- """
63
+ Expects create_weights to have been called before on the layer."""
64
raise NotImplementedError
65
66
# Not required functions
@@ -76,8 +73,7 @@ class QuantizeMethodBase(ABC):
73
Quantization methods that need special weight handling (e.g. repacked
74
weights) override this.
75
79
- Expects create_weights to have been called before on the layer.
80
- """
76
+ Expects create_weights to have been called before on the layer."""
77
layer.weight = embed_tokens.weight
78
return layer
79
vllm/model_executor/layers/quantization/compressed_tensors/compressed_tensors.py
+2
-4
@@ -665,8 +665,7 @@ class CompressedTensorsConfig(QuantizationConfig):
665
) -> bool:
666
"""Weight N-bit INT (pack-quantized for sub-byte, int-quantized for 8-bit)
667
with static per-tensor INT8 input/output activation quant, applied as a float
668
- fake-quant around a weight-only matmul.
669
- """
668
+ fake-quant around a weight-only matmul."""
669
is_int_pack_format = format in (
670
CompressionFormat.pack_quantized.value,
671
CompressionFormat.int_quantized.value,
@@ -702,8 +701,7 @@ class CompressedTensorsConfig(QuantizationConfig):
701
format: str | None,
702
) -> bool:
703
"""Weight N-bit INT with symmetric dynamic INT activation quant
705
- via Humming kernel.
706
- """
704
+ via Humming kernel."""
705
if input_quant is None:
706
return False
707
is_pack_format = format == CompressionFormat.pack_quantized.value
vllm/model_executor/layers/quantization/compressed_tensors/compressed_tensors_embedding.py
+1
-2
@@ -37,8 +37,7 @@ def _dequant_gather_kernel(
37
BLOCK: tl.constexpr,
38
):
39
"""Gather embedding rows by token id, unpack int32-packed INT weights, and
40
- dequantize to ``out`` dtype in one pass (no int8 intermediate).
41
- """
40
+ dequantize to ``out`` dtype in one pass (no int8 intermediate)."""
41
row = tl.program_id(0)
42
col = tl.program_id(1) * BLOCK + tl.arange(0, BLOCK)
43
col_mask = col < hidden
vllm/model_executor/layers/quantization/compressed_tensors/schemes/compressed_tensors_wNa8o8.py
+1
-2
@@ -211,8 +211,7 @@ class CompressedTensorsWNA8O8Int(CompressedTensorsScheme):
211
212
def _pack_int_quantized_weight(self, layer: torch.nn.Module) -> None:
213
"""Normalize an int-quantized (plain int8) weight to the canonical
214
- ``weight_packed`` int32 + ``weight_shape`` layout the MP kernels expect.
215
- """
214
+ ``weight_packed`` int32 + ``weight_shape`` layout the MP kernels expect."""
215
weight = layer.weight
216
out_features, in_features = weight.shape
217
packed = pack_to_int32(weight.data.contiguous(), self.num_bits)
vllm/model_executor/layers/quantization/inc/config_parser.py
+1
-2
@@ -86,8 +86,7 @@ class INCConfigParser:
86
87
def is_explicitly_configured(name: str) -> bool:
88
"""Return True if *name* has an explicit entry in extra_config,
89
- either via exact key match or via a regex pattern key.
90
- """
89
+ either via exact key match or via a regex pattern key."""
90
if not self._config.extra_config:
91
return False
92
if name in self._config.extra_config:
vllm/model_executor/layers/quantization/inc/schemes/inc_scheme.py
+1
-2
@@ -48,8 +48,7 @@ class INCScheme(ABC):
48
layer_config: "INCLayerConfig",
49
) -> "FusedMoEMethodBase | None":
50
"""Optional. Override if this scheme supports MoE.
51
- Default raises NotImplementedError.
52
- """
51
+ Default raises NotImplementedError."""
52
raise NotImplementedError(
53
f"{type(self).__name__} does not support MoE layers. "
54
f"Layer config: {layer_config}"
vllm/model_executor/layers/quantization/modelopt.py
+6
-12
@@ -1988,8 +1988,7 @@ class KNvfp4Static(QuantKeyScheme):
1988
1989
class KNvfp4Dynamic(QuantKeyScheme):
1990
"""NVFP4 activation scheme (W4A4). Has a static global input scale on disk;
1991
- the per-group scale is computed at runtime inside the kernel.
1992
- """
1991
+ the per-group scale is computed at runtime inside the kernel."""
1992
1993
key = kNvfp4Dynamic
1994
@@ -2026,8 +2025,7 @@ class KNvfp4Dynamic(QuantKeyScheme):
2025
2026
class KFp8StaticTensor(QuantKeyScheme):
2027
"""Plain per-tensor static FP8 — bivalent: serves BOTH the weight slot and
2029
- the activation slot (W8A8). One key in both QuantSpec slots.
2030
- """
2028
+ the activation slot (W8A8). One key in both QuantSpec slots."""
2029
2030
key = kFp8StaticTensorSym
2031
@@ -2097,8 +2095,7 @@ class KFp8StaticTensor(QuantKeyScheme):
2095
2096
class KFp8StaticChannel(QuantKeyScheme):
2097
"""Per-channel static FP8 weight (the 'PcPt' weight). Weight-role only —
2100
- there is no static per-channel *activation* today.
2101
- """
2098
+ there is no static per-channel *activation* today."""
2099
2100
key = kFp8StaticTokenSym
2101
@@ -2139,8 +2136,7 @@ class KFp8StaticChannel(QuantKeyScheme):
2136
class KFp8Block128(QuantKeyScheme):
2137
"""128x128 block-static FP8 weight ('PbWo'). Weight-role only. ModelOpt
2138
exports the scale 4-D [out_blk,1,in_blk,1]; process squeezes to 2-D.
2142
- No transpose (block kernel keeps [out,in]).
2143
- """
2139
+ No transpose (block kernel keeps [out,in])."""
2140
2141
key = kFp8Static128BlockSym
2142
@@ -2196,8 +2192,7 @@ class KFp8Block128(QuantKeyScheme):
2192
2193
class KMxfp8Static(QuantKeyScheme):
2194
"""MXFP8 weight: fp8-e4m3 values + per-32-block e8m0 (uint8) scale.
2199
- Weight-role only. process is validate-only plus an idempotency guard.
2200
- """
2195
+ Weight-role only. process is validate-only plus an idempotency guard."""
2196
2197
key = kMxfp8Static
2198
@@ -2272,8 +2267,7 @@ class KDynamicNoParam(QuantKeyScheme):
2267
"""Dynamic activation with no stored scale (W8A8): quantized at runtime in
2268
the kernel. NOT the same as activation=None (weight-only) — init_fp8 needs a
2269
non-None activation key. Activation-role only. Serves the fp8 per-token, fp8
2275
- per-block, and mxfp8 dynamic activation keys.
2276
- """
2270
+ per-block, and mxfp8 dynamic activation keys."""
2271
2272
def create_weights(self, layer, role, ctx, shapes, wl) -> None:
2273
if role is not ACT:
vllm/model_executor/layers/quantization/mxfp4.py
+1
-2
@@ -79,8 +79,7 @@ class Mxfp4Config(QuantizationConfig):
79
80
def _make_moe_method(self, moe: FusedMoEConfig) -> FusedMoEMethodBase:
81
"""MoE method for RoutedExperts. Subclasses override to pick a
82
- checkpoint-specific kernel family.
83
- """
82
+ checkpoint-specific kernel family."""
83
return Mxfp4MoEMethod(moe)
84
85
def get_quant_method(
vllm/model_executor/layers/quantization/online/base.py
+1
-2
@@ -139,8 +139,7 @@ def _find_matching_targets(
139
140
class OnlineQuantizationConfig(QuantizationConfig):
141
"""Model-level config for online quantization (quantize fp16/bf16 weights
142
- during model loading, without requiring a pre-quantized checkpoint).
143
- """
142
+ during model loading, without requiring a pre-quantized checkpoint)."""
143
144
def __init__(
145
self,
vllm/model_executor/layers/quantization/online/fp8.py
+6
-12
@@ -118,8 +118,7 @@ def _is_tp_sharded(layer: Module, *, reduces_output_dim: bool = True) -> bool:
118
119
class OnlineLinearBase(LinearMethodBase):
120
"""Shared base for online FP8 linear methods. Loads fp16/bf16 checkpoint
121
- weights onto meta device and materializes them just-in-time.
122
- """
121
+ weights onto meta device and materializes them just-in-time."""
122
123
uses_meta_device: bool = True
124
@@ -163,8 +162,7 @@ class OnlineLinearBase(LinearMethodBase):
162
163
class Fp8PerTensorOnlineLinearMethod(OnlineLinearBase):
164
"""Online tensorwise FP8 linear quantization.
166
- Loads fp16/bf16 weights and quantizes them per-tensor during loading.
167
- """
165
+ Loads fp16/bf16 weights and quantizes them per-tensor during loading."""
166
167
def __init__(self):
168
super().__init__()
@@ -265,8 +263,7 @@ class Fp8PerTensorOnlineLinearMethod(OnlineLinearBase):
263
264
class Fp8PerBlockOnlineLinearMethod(OnlineLinearBase):
265
"""Online blockwise FP8 linear quantization.
268
- Loads fp16/bf16 weights and quantizes them per-block during loading.
269
- """
266
+ Loads fp16/bf16 weights and quantizes them per-block during loading."""
267
268
def __init__(self):
269
super().__init__()
@@ -440,8 +437,7 @@ class Fp8PtpcOnlineLinearMethod(OnlineLinearBase):
437
438
class _Fp8OnlineMoEBase(OnlineMoEMethodBase):
439
"""Shared base for online FP8 MoE methods. Loads fp16/bf16 checkpoint
443
- weights onto meta device and materializes them just-in-time.
444
- """
440
+ weights onto meta device and materializes them just-in-time."""
441
442
# Declared here for mypy; actual values are set in __init__.
443
fp8_backend: "Fp8MoeBackend"
@@ -562,8 +558,7 @@ class _Fp8OnlineMoEBase(OnlineMoEMethodBase):
558
559
class Fp8PerTensorOnlineMoEMethod(_Fp8OnlineMoEBase):
560
"""Online tensorwise FP8 MoE quantization.
565
- Loads fp16/bf16 weights and quantizes them per-tensor during loading.
566
- """
561
+ Loads fp16/bf16 weights and quantizes them per-tensor during loading."""
562
563
def __init__(
564
self,
@@ -620,8 +615,7 @@ class Fp8PerTensorOnlineMoEMethod(_Fp8OnlineMoEBase):
615
616
class Fp8PerBlockOnlineMoEMethod(_Fp8OnlineMoEBase):
617
"""Online blockwise FP8 MoE quantization.
623
- Loads fp16/bf16 weights and quantizes them per-block during loading.
624
- """
618
+ Loads fp16/bf16 weights and quantizes them per-block during loading."""
619
620
def __init__(
621
self,
vllm/model_executor/layers/quantization/utils/fp8_utils.py
+2
-4
@@ -69,8 +69,7 @@ def input_to_float8(
69
x: torch.Tensor, dtype: torch.dtype | None = None
70
) -> tuple[torch.Tensor, torch.Tensor]:
71
"""This function quantizes input values to float8 values "
72
- "with tensor-wise quantization.
73
- """
72
+ "with tensor-wise quantization."""
73
dtype = current_platform.fp8_dtype() if dtype is None else dtype
74
finfo = torch.finfo(dtype)
75
min_val, max_val = x.aminmax()
@@ -1195,8 +1194,7 @@ def prepare_fp8_moe_layer_for_deepgemm(
1194
1195
def _maybe_pad_fp8_weight(weight: torch.Tensor) -> torch.Tensor:
1196
"""Pad the weight tensor. This is an optimization on ROCm platform, which
1198
- can benefit from tensors located far enough from one another in memory
1199
- """
1197
+ can benefit from tensors located far enough from one another in memory"""
1198
if (
1199
envs.VLLM_ROCM_FP8_PADDING
1200
and current_platform.is_rocm()
vllm/model_executor/layers/quantization/utils/humming_utils.py
+2
-4
@@ -297,8 +297,7 @@ def _humming_input_schema_to_quant_key(
297
schema: "HummingInputSchema",
298
) -> QuantKey | None:
299
"""Convert a HummingInputSchema to a QuantKey. Returns None if
300
- the schema represents unquantized (bf16/fp16) inputs.
301
- """
300
+ the schema represents unquantized (bf16/fp16) inputs."""
301
if schema.a_dtype is None or schema.a_dtype.num_bits >= 16:
302
return None
303
@@ -427,8 +426,7 @@ def convert_linear_layer_to_humming_standard(
426
):
427
"""Rename/reshape a linear layer's quantized params (the canonical MPLinear
428
layout: ``weight_packed`` int32 + ``weight_scale``) into the parameter names
430
- and layout humming's weight schema expects (``weight`` / ``weight_scale``).
431
- """
429
+ and layout humming's weight schema expects (``weight`` / ``weight_scale``)."""
430
for name, checkpoint_name in name_map.items():
431
tensor = getattr(layer, checkpoint_name)
432
delattr(layer, checkpoint_name)
vllm/model_executor/layers/quantization/utils/marlin_utils.py
+3
-6
@@ -245,8 +245,7 @@ def marlin_padded_nk(size_n: int, size_k: int, group_size: int = -1) -> tuple[in
245
246
def marlin_repacked_nk(qweight: torch.Tensor, num_bits: int) -> tuple[int, int]:
247
"""Recover the (size_n, size_k) a Marlin weight was repacked with
248
- (including any tile padding) from its packed shape.
249
- """
248
+ (including any tile padding) from its packed shape."""
249
pack_factor = 32 // num_bits
250
size_k = qweight.size(0) * GPTQ_MARLIN_TILE
251
size_n = qweight.size(1) * pack_factor // GPTQ_MARLIN_TILE
@@ -257,8 +256,7 @@ def marlin_pad_qweight(
256
qweight: torch.Tensor, size_n: int, size_k: int, padded_n: int, padded_k: int
257
) -> torch.Tensor:
258
"""Zero-pad a GPTQ-layout packed weight (size_k / pack, size_n) for
260
- gptq_marlin_repack.
261
- """
259
+ gptq_marlin_repack."""
260
if (padded_n, padded_k) == (size_n, size_k):
261
return qweight
262
pack_factor = size_k // qweight.size(0)
@@ -276,8 +274,7 @@ def marlin_pad_scales(
274
group_size: int,
275
) -> torch.Tensor:
276
"""Zero-pad weight scales (num_groups, size_n); call before
279
- marlin_permute_scales and pass the padded extents to it.
280
- """
277
+ marlin_permute_scales and pass the padded extents to it."""
278
if (padded_n, padded_k) == (size_n, size_k):
279
return scales
280
pad_rows = padded_k // group_size - scales.size(0) if group_size > 0 else 0
vllm/model_executor/layers/quantization/utils/marlin_utils_fp4.py
+3
-6
@@ -41,8 +41,7 @@ def _nvfp4_compute_scale_factor(
41
) -> float:
42
"""Compute the power-of-2 scale_factor needed so that all non-zero
43
values in marlin_scales * 2^7 are >= 2 after rescaling.
44
- Returns a Python float (power of 2, >= 1.0).
45
- """
44
+ Returns a Python float (power of 2, >= 1.0)."""
45
# Since half has a smaller dynamic range compared to bfloat16,
46
# no rescaling is applied here if active dtype is half.
47
if a_dtype is not None and a_dtype == torch.half:
@@ -376,8 +375,7 @@ def prepare_nvfp4_moe_layer_for_marlin(
375
376
def pad_w13(x: torch.Tensor) -> torch.Tensor:
377
"""Zero-pad each gate/up shard of a (E, num_shards * N, cols)
379
- tensor to padded_N rows.
380
- """
378
+ tensor to padded_N rows."""
379
if padded_N == N:
380
return x
381
x = x.view(E, num_shards, N, x.size(-1))
@@ -386,8 +384,7 @@ def prepare_nvfp4_moe_layer_for_marlin(
384
385
def pad_w2(x: torch.Tensor, packing: int) -> torch.Tensor:
386
"""Zero-pad the packed N (last) dim of a (E, K, N / packing)
389
- tensor.
390
- """
387
+ tensor."""
388
if padded_N == N:
389
return x
390
return torch.nn.functional.pad(x, (0, (padded_N - N) // packing))
vllm/model_executor/layers/quantization/utils/marlin_utils_fp8.py
+1
-2
@@ -217,8 +217,7 @@ def prepare_fp8_layer_for_marlin(
217
218
def _moe_pad_shard_rows(x: torch.Tensor, n: int, padded_n: int) -> torch.Tensor:
219
"""Zero-pad each gate/up shard of a ``(E, 2 * n, ...)`` tensor to padded_n
220
- rows. FP8 zero decodes to 0.0, so the padded rows contribute nothing.
221
- """
220
+ rows. FP8 zero decodes to 0.0, so the padded rows contribute nothing."""
221
if padded_n == n:
222
return x
223
e = x.size(0)
vllm/model_executor/layers/rotary_embedding/ntk_scaling_rope.py
+1
-2
@@ -9,8 +9,7 @@ from .base import RotaryEmbedding
9
10
class NTKScalingRotaryEmbedding(RotaryEmbedding):
11
"""RotaryEmbedding extended with fixed and mixed NTK scaling.
12
- https://kexue.fm/archives/9706
13
- """
12
+ https://kexue.fm/archives/9706"""
13
14
def __init__(
15
self,
vllm/model_executor/layers/sparse_attn_indexer.py
+2
-4
@@ -285,8 +285,7 @@ def _gather_workspace_shapes(
285
"""Return ((values_shape, values_dtype), (scales_shape, scales_dtype)) for
286
the K-gather workspace. FP8 path: (T, head_dim) fp8 + (T, 4) uint8 fp32
287
scales. MXFP4 path: (T, head_dim // 2) uint8 packed mxfp4 +
288
- (T, head_dim // MXFP4_BLOCK_SIZE) uint8 ue8m0 scales.
289
- """
288
+ (T, head_dim // MXFP4_BLOCK_SIZE) uint8 ue8m0 scales."""
289
if use_fp4_cache:
290
return (
291
((total_seq_lens, head_dim // 2), torch.uint8),
@@ -304,8 +303,7 @@ def kv_cache_as_quant_view(
303
use_fp4_cache: bool,
304
) -> torch.Tensor:
305
"""4D ``[num_blocks, block_size, 1, head_width]`` view expected by
307
- DeepGEMM, from the 3D indexer kv-cache allocation.
308
- """
306
+ DeepGEMM, from the 3D indexer kv-cache allocation."""
307
if use_fp4_cache:
308
assert kv_cache.ndim == 3 and kv_cache.dtype == torch.uint8
309
num_blocks, block_size, _ = kv_cache.shape
vllm/model_executor/layers/sparse_mqa_indexer.py
+2
-4
@@ -41,8 +41,7 @@ def _prefill_k_workspaces(
41
total_seq_lens: int, head_dim: int
42
) -> tuple[torch.Tensor, torch.Tensor]:
43
"""The packed MXFP4 K-gather workspace ``(values, scales)``, shared with
44
- the dense indexer layers of the same model.
45
- """
44
+ the dense indexer layers of the same model."""
45
values_spec, scales_spec = _gather_workspace_shapes(
46
total_seq_lens, head_dim, current_platform.fp8_dtype(), use_fp4_cache=True
47
)
@@ -120,8 +119,7 @@ class SparseMQAIndexer(nn.Module):
119
120
def _reserve_workspaces(self, device: torch.device) -> None:
121
"""Profiling run: claim the K-gather workspace and the peak sparse
123
- logits allocation so the memory estimate covers them.
124
- """
122
+ logits allocation so the memory estimate covers them."""
123
_prefill_k_workspaces(self.max_total_seq_len, self.head_dim)
124
max_logits_bytes = envs.VLLM_SPARSE_INDEXER_MAX_LOGITS_MB * 1024 * 1024
125
torch.empty(max_logits_bytes, dtype=torch.uint8, device=device)
vllm/model_executor/layers/vocab_parallel_embedding.py
+1
-2
@@ -376,8 +376,7 @@ class VocabParallelEmbedding(PluggableLayer):
376
) -> VocabParallelEmbeddingShardIndices:
377
"""Get start and end indices for vocab parallel embedding, following the
378
layout outlined in the class docstring, based on the given tp_rank and
379
- tp_size.
380
- """
379
+ tp_size."""
380
num_added_embeddings_padded = vocab_size_padded - org_vocab_size_padded
381
padded_org_vocab_start_index, padded_org_vocab_end_index = (
382
vocab_range_from_global_vocab_size(org_vocab_size_padded, tp_rank, tp_size)
vllm/model_executor/model_loader/base_loader.py
+1
-2
@@ -36,8 +36,7 @@ class BaseModelLoader(ABC):
36
@abstractmethod
37
def load_weights(self, model: nn.Module, model_config: ModelConfig) -> None:
38
"""Load weights into a model. This standalone API allows
39
- inplace weights loading for an already-initialized model
40
- """
39
+ inplace weights loading for an already-initialized model"""
40
raise NotImplementedError
41
42
def create_model(
vllm/model_executor/model_loader/default_loader.py
+1
-2
@@ -135,8 +135,7 @@ class DefaultModelLoader(BaseModelLoader):
135
) -> tuple[str, list[str], bool]:
136
"""Prepare weights for the model.
137
138
- If the model is not local, it will be downloaded.
139
- """
138
+ If the model is not local, it will be downloaded."""
139
model_name_or_path = (
140
maybe_download_from_modelscope(model_name_or_path, revision)
141
or model_name_or_path
vllm/model_executor/model_loader/ep_weight_filter.py
+2
-4
@@ -23,8 +23,7 @@ def parse_expert_id(weight_name: str) -> int | None:
23
24
Returns ``None`` for dense weights (attention, layernorm, embedding),
25
shared experts, and 3D fused-expert tensors where all experts are stored
26
- in a single tensor without a numeric expert id in the name.
27
- """
26
+ in a single tensor without a numeric expert id in the name."""
27
m = _EXPERT_ID_RE.search(weight_name)
28
return int(m.group(1)) if m else None
29
@@ -71,8 +70,7 @@ def should_skip_weight(
70
local_expert_ids: set[int] | None,
71
) -> bool:
72
"""Return ``True`` if *weight_name* is an expert weight that does not
74
- belong to the local rank and should be skipped during loading.
75
- """
73
+ belong to the local rank and should be skipped during loading."""
74
if local_expert_ids is None:
75
return False
76
eid = parse_expert_id(weight_name)
vllm/model_executor/model_loader/reload/layerwise.py
+2
-4
@@ -308,8 +308,7 @@ def _reload_attention_scales(layer: torch.nn.Module, info: LayerReloadingInfo) -
308
309
Assumes dtype/shapes of attention tensors do not change during
310
processing, since we use .data.copy_() to preserve kernel tensor
311
- references.
312
- """
311
+ references."""
312
quant_method = getattr(layer, "quant_method", None)
313
if quant_method is not None:
314
# Re-create scale Parameters with sentinel values so unloaded scales
@@ -388,8 +387,7 @@ def _get_weight_loader(tensor: torch.Tensor):
387
388
def _copy_and_restore_kernel_tensors(layer: torch.nn.Module, info: LayerReloadingInfo):
389
"""Copy processed values into original kernel tensor storage and restore
391
- kernel tensor references on the layer. Preserves cudagraph references.
392
- """
390
+ kernel tensor references on the layer. Preserves cudagraph references."""
391
assert info.kernel_tensors is not None
392
parameters, buffers = info.kernel_tensors
393
non_persistent = info.kernel_non_persistent_buffers
vllm/model_executor/model_loader/runai_streamer_loader.py
+1
-2
@@ -81,8 +81,7 @@ class RunaiModelStreamerLoader(BaseModelLoader):
81
) -> list[str]:
82
"""Prepare weights for the model.
83
84
- If the model is not local, it will be downloaded.
85
- """
84
+ If the model is not local, it will be downloaded."""
85
is_object_storage_path = is_runai_obj_uri(model_name_or_path)
86
is_local = os.path.isdir(model_name_or_path)
87
safetensors_pattern = "*.safetensors"
vllm/model_executor/model_loader/tensorizer.py
+1
-2
@@ -497,8 +497,7 @@ def _check_tensors_on_meta_device(model: nn.Module) -> None:
497
498
def _resize_lora_embeddings(model: nn.Module):
499
"""Modify LoRA embedding layers to use bigger tensors
500
- to allow for adapter added tokens.
501
- """
500
+ to allow for adapter added tokens."""
501
for child in model.modules():
502
if (
503
isinstance(child, VocabParallelEmbedding)
vllm/model_executor/model_loader/tensorizer_loader.py
+1
-2
@@ -105,8 +105,7 @@ class TensorizerLoader(BaseModelLoader):
105
106
Expects a vLLM-tensorized model. See the
107
examples/features/tensorize_vllm_model.py example script
108
- for serializing vLLM models.
109
- """
108
+ for serializing vLLM models."""
109
if is_vllm_tensorized(self.tensorizer_config):
110
tensorizer_config = self._patch_tensorizer_config(model_config)
111
deserialize_tensorizer_model(model, tensorizer_config)
vllm/model_executor/model_loader/weight_cache/ipc_loader.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""IPC model loader: maps post-quantized weights from a local weight cache
4
-daemon via CUDA IPC instead of loading from disk.
5
-"""
4
+daemon via CUDA IPC instead of loading from disk."""
5
6
import dataclasses
7
import socket
vllm/model_executor/model_loader/weight_tying.py
+1
-2
@@ -78,8 +78,7 @@ def maybe_retie_word_embeddings(model: nn.Module, model_config: ModelConfig) ->
78
79
Checkpoints produced by quantization or fine-tuning tooling often keep a redundant
80
copy of the tied `lm_head`. Sharing the storage again reclaims the memory it would
81
- otherwise cost.
82
- """
81
+ otherwise cost."""
82
if not model_config.word_embeddings_untied_by_checkpoint:
83
return
84
if (untied := _get_untied_lm_head(model)) is None:
vllm/model_executor/model_loader/weight_utils.py
+3
-6
@@ -144,8 +144,7 @@ def atomic_writer(
144
145
def _natural_sort_key(filepath: str) -> list:
146
"""Natural sort key for filenames with numeric components, such as
147
- model-00001-of-00005.safetensors -> ['model-', 1, '-of-', 5, '.safetensors']
148
- """
147
+ model-00001-of-00005.safetensors -> ['model-', 1, '-of-', 5, '.safetensors']"""
148
return [
149
int(s) if s.isdigit() else s
150
for s in re.split(r"(\d+)", os.path.basename(filepath))
@@ -162,8 +161,7 @@ def maybe_download_from_modelscope(
161
"""Download model from ModelScope hub if VLLM_USE_MODELSCOPE is True.
162
163
Returns the path to the downloaded model, or None if the model is not
165
- downloaded from ModelScope.
166
- """
164
+ downloaded from ModelScope."""
165
if envs.VLLM_USE_MODELSCOPE:
166
# download model from ModelScope hub,
167
# lazy import so that modelscope is not required for normal use.
@@ -1148,8 +1146,7 @@ def instanttensor_weights_iterator(
1146
use_tqdm_on_load: bool,
1147
) -> Generator[tuple[str, torch.Tensor], None, None]:
1148
"""Iterate over the weights in the model safetensor files
1151
- using instanttensor library.
1152
- """
1149
+ using instanttensor library."""
1150
try:
1151
import instanttensor
1152
except ImportError as e:
vllm/model_executor/models/arcee.py
+5
-10
@@ -47,8 +47,7 @@ from .utils import (
47
48
class ArceeMLP(nn.Module):
49
"""Feed-forward layer for Arcee using ReLU^2 activation
50
- (no gating as in LLaMA).
51
- """
50
+ (no gating as in LLaMA)."""
51
52
def __init__(
53
self,
@@ -96,8 +95,7 @@ class ArceeMLP(nn.Module):
95
96
class ArceeDecoderLayer(nn.Module):
97
"""Transformer decoder block for Arcee, with self-attention and
99
- ReLU^2 MLP.
100
- """
98
+ ReLU^2 MLP."""
99
100
def __init__(
101
self,
@@ -177,8 +175,7 @@ class ArceeDecoderLayer(nn.Module):
175
@support_torch_compile
176
class ArceeModel(nn.Module, EagleModelMixin):
177
"""The transformer model backbone for Arcee (embedding layer + stacked
180
- decoder blocks + final norm).
181
- """
178
+ decoder blocks + final norm)."""
179
180
def __init__(
181
self,
@@ -280,8 +277,7 @@ class ArceeForCausalLM(
277
nn.Module, SupportsLoRA, SupportsPP, SupportsEagle, SupportsEagle3
278
):
279
"""Arcee Model for causal language modeling, integrated with vLLM
283
- runtime.
284
- """
280
+ runtime."""
281
282
hf_to_vllm_mapper = WeightsMapper(
283
orig_to_new_stacked={
@@ -362,8 +358,7 @@ class ArceeForCausalLM(
358
359
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
360
"""Load weights into the model (delegates to inner model and handles
365
- tied embeddings).
366
- """
361
+ tied embeddings)."""
362
loader = AutoWeightsLoader(self)
363
# AutoWeightLoader handles weight name remapping, including fusing
364
# separate q_proj, k_proj, v_proj into qkv_proj
vllm/model_executor/models/blip.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Minimal implementation of BlipVisionModel intended to be only used
4
-within a vision language model.
5
-"""
4
+within a vision language model."""
5
6
from collections.abc import Iterable
7
vllm/model_executor/models/cohere2_moe.py
+1
-2
@@ -96,8 +96,7 @@ class RMSNorm(nn.Module):
96
97
def select_norm_impl(config: CohereConfig) -> tuple[type[nn.Module], float]:
98
"""Returns (norm_class, eps). Uses RMSNorm when config.rms_norm_eps is set,
99
- otherwise falls back to LayerNorm with config.layer_norm_eps.
100
- """
99
+ otherwise falls back to LayerNorm with config.layer_norm_eps."""
100
rms_eps = getattr(config, "rms_norm_eps", None)
101
if rms_eps is not None:
102
return RMSNorm, rms_eps
vllm/model_executor/models/cohere_asr.py
+1
-2
@@ -667,8 +667,7 @@ class ConvSubsampling(nn.Module):
667
repeat_num: int = 1,
668
) -> torch.Tensor:
669
"""Calculates the output length of a Tensor passed
670
- through a convolution or max pooling layer
671
- """
670
+ through a convolution or max pooling layer"""
671
add_pad: float = all_paddings - kernel_size
672
one: float = 1.0
673
for i in range(repeat_num):
vllm/model_executor/models/deepencoder.py
+1
-2
@@ -363,8 +363,7 @@ class ImageEncoderViT(nn.Module):
363
364
class Block(nn.Module):
365
"""Transformer blocks with support of window attention and residual propagation
366
- blocks
367
- """
366
+ blocks"""
367
368
def __init__(
369
self,
vllm/model_executor/models/deepseek_ocr.py
+1
-2
@@ -139,8 +139,7 @@ class NoRepeatNGramLogitsProcessor:
139
140
class NGramPerReqLogitsProcessor(AdapterLogitsProcessor):
141
"""Example of overriding the wrapper class `__init__()` in order to utilize
142
- info about the device type
143
- """
142
+ info about the device type"""
143
144
@classmethod
145
def validate_params(cls, params: SamplingParams):
vllm/model_executor/models/diffusion_gemma.py
+1
-2
@@ -511,8 +511,7 @@ def _compiled_sample_step(
511
accept/renoise → convergence, all as vectorized PyTorch ops.
512
513
Returns the temperature-scaled logits ``[num_decode, CL, vocab]`` so the
514
- caller can compute logprobs outside the compiled region.
515
- """
514
+ caller can compute logprobs outside the compiled region."""
515
num_decode = decode_slots.shape[0]
516
device = decode_slots.device
517
vllm/model_executor/models/gemma3n.py
+1
-2
@@ -814,8 +814,7 @@ class Gemma3nCrossDecoder(nn.Module):
814
def _kv_sharing_weights_mapper(config: Gemma3nTextConfig) -> WeightsMapper:
815
"""KV-shared layers only have q_proj, so qkv_proj packing applies to the
816
other layers. Original checkpoints still ship K/V tensors for the shared
817
- layers (fine-tuned ones omit them); those are dropped.
818
- """
817
+ layers (fine-tuned ones omit them); those are dropped."""
818
first_kv_shared_layer_idx = config.num_hidden_layers - config.num_kv_shared_layers
819
return WeightsMapper(
820
orig_to_new_substr={
vllm/model_executor/models/gemma3n_mm.py
+1
-2
@@ -499,8 +499,7 @@ class Gemma3nMultiModalProcessor(BaseMultiModalProcessor[Gemma3nProcessingInfo])
499
500
class Gemma3nMultimodalEmbedder(nn.Module):
501
"""Embeds token ids or soft tokens for multimodal content into language
502
- model space.
503
- """
502
+ model space."""
503
504
def __init__(
505
self,
vllm/model_executor/models/glm4_1v.py
+1
-2
@@ -25,8 +25,7 @@
25
# See the License for the specific language governing permissions and
26
# limitations under the License.
27
"""Inference-only GLM-4.1V & GLM-4.6V-Flash, AutoGLM-Phone-9B model
28
-compatible with HuggingFace weights.
29
-"""
28
+compatible with HuggingFace weights."""
29
30
import math
31
from collections.abc import Callable, Hashable, Iterable, Iterator, Mapping, Sequence
vllm/model_executor/models/glm4_moe.py
+1
-2
@@ -22,8 +22,7 @@
22
# See the License for the specific language governing permissions and
23
# limitations under the License.
24
"""Inference-only GLM-4.5, GLM-4.6, GLM-4.7 model
25
-compatible with HuggingFace weights.
26
-"""
25
+compatible with HuggingFace weights."""
26
27
from collections.abc import Iterable
28
from itertools import islice
vllm/model_executor/models/glm4_moe_mtp.py
+1
-2
@@ -22,8 +22,7 @@
22
# See the License for the specific language governing permissions and
23
# limitations under the License.
24
"""Inference-only GLM-4.5, GLM-4.6, GLM-4.7 MTP
25
-model compatible with HuggingFace weights.
26
-"""
25
+model compatible with HuggingFace weights."""
26
27
import typing
28
from collections.abc import Callable, Iterable
vllm/model_executor/models/granite_speech.py
+1
-2
@@ -462,8 +462,7 @@ class GraniteSpeechConformerConvModule(nn.Module):
462
463
class GraniteSpeechConformerBlock(nn.Module):
464
"""Conformer block, consisting largely of linear layers,
465
- attention, and convolutional layers.
466
- """
465
+ attention, and convolutional layers."""
466
467
def __init__(self, config: PretrainedConfig, prefix: str = ""):
468
super().__init__()
vllm/model_executor/models/interfaces.py
+5
-10
@@ -892,8 +892,7 @@ def has_inner_state(
892
@runtime_checkable
893
class IsAttentionFree(Protocol):
894
"""The interface required for all models like Mamba that lack attention,
895
- but do have state whose size is constant wrt the number of tokens.
896
- """
895
+ but do have state whose size is constant wrt the number of tokens."""
896
897
is_attention_free: ClassVar[Literal[True]] = True
898
"""
@@ -921,8 +920,7 @@ def is_attention_free(
920
class IsHybrid(Protocol):
921
"""The interface required for all models like Jamba that have both
922
attention and mamba blocks, indicates that
924
- hf_config has 'layers_block_type'
925
- """
923
+ hf_config has 'layers_block_type'"""
924
925
is_hybrid: ClassVar[Literal[True]] = True
926
"""
@@ -1338,8 +1336,7 @@ class SupportsTranscription(Protocol):
1336
) -> "PromptType":
1337
"""Get the prompt for the ASR model.
1338
The model has control over the construction, as long as it
1341
- returns a valid PromptType.
1342
- """
1339
+ returns a valid PromptType."""
1340
...
1341
1342
@classmethod
@@ -1631,8 +1628,7 @@ class EagleModelMixin:
1628
@runtime_checkable
1629
class SupportsEagle(SupportsEagleBase, Protocol):
1630
"""The interface required for models that support
1634
- EAGLE-1 and EAGLE-2 speculative decoding.
1635
- """
1631
+ EAGLE-1 and EAGLE-2 speculative decoding."""
1632
1633
supports_eagle: ClassVar[Literal[True]] = True
1634
"""
@@ -1662,8 +1658,7 @@ def supports_eagle(
1658
@runtime_checkable
1659
class SupportsEagle3(SupportsEagleBase, Protocol):
1660
"""The interface required for models that support
1665
- EAGLE-3 speculative decoding.
1666
- """
1661
+ EAGLE-3 speculative decoding."""
1662
1663
supports_eagle3: ClassVar[Literal[True]] = True
1664
"""
vllm/model_executor/models/keye.py
+1
-2
@@ -345,8 +345,7 @@ def apply_rotary_pos_emb_flashatt(
345
346
class KeyeSiglipAttention(nn.Module):
347
"""Multi-headed attention from 'Attention Is All You
348
- Need' paper.
349
- """
348
+ Need' paper."""
349
350
def __init__(
351
self,
vllm/model_executor/models/lfm2_siglip2.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Implementation of Siglip2VisionModel intended to be only used
4
-within a vision language model.
5
-"""
4
+within a vision language model."""
5
6
from collections.abc import Iterable
7
vllm/model_executor/models/medusa.py
+1
-2
@@ -51,8 +51,7 @@ class Medusa(nn.Module):
51
truncated_vocab_size < vocab_size. To use this technique, one has to find
52
the top-k most frequent tokens in target dataset and add that as a tensor
53
in the draft checkpoint (using key token_map). Also, the draft config
54
- needs to have truncated_vocab_size (=k) as an attribute.
55
- """
54
+ needs to have truncated_vocab_size (=k) as an attribute."""
55
56
def __init__(self, *, vllm_config: VllmConfig, prefix: str = "") -> None:
57
speculative_config = vllm_config.speculative_config
vllm/model_executor/models/minicpmv4_6.py
+1
-2
@@ -858,8 +858,7 @@ class MiniCPMV4_6ViTWindowAttentionMerger(nn.Module):
858
859
class MiniCPMV4_6DownsampleMLP(nn.Module):
860
"""Match HF (transformers v5.7+) parameter naming: pre_norm/linear_1/
861
- act/linear_2 (instead of pre_norm + Sequential(mlp.0/mlp.2)).
862
- """
861
+ act/linear_2 (instead of pre_norm + Sequential(mlp.0/mlp.2))."""
862
863
def __init__(
864
self,
vllm/model_executor/models/mllama4.py
+1
-2
@@ -1090,8 +1090,7 @@ class Llama4ForConditionalGeneration(
1090
1091
def _rename_weight_for_modelopt_checkpoint(self, name: str) -> str:
1092
"""Rename weights from ModelOpt llama4 fp8 checkpoints to vLLM
1093
- format.
1094
- """
1093
+ format."""
1094
if name.startswith("model.") or name.startswith("language_model.model."):
1095
renamed = (
1096
name.replace("model.", "language_model.model.", 1)
vllm/model_executor/models/muse_glimmer.py
+3
-6
@@ -114,8 +114,7 @@ logger = init_logger(__name__)
114
def _text_config(config):
115
"""MuseGlimmer checkpoints may nest the text config under ``text_config``
116
(multimodal ``MuseGlimmerConfig``) or expose it directly
117
- (``MuseGlimmerTextConfig``).
118
- """
117
+ (``MuseGlimmerTextConfig``)."""
118
return getattr(config, "text_config", config)
119
120
@@ -489,8 +488,7 @@ class MuseGlimmerMultiModalProcessor(
488
def _muse_glimmer_use_qk_norm(config) -> bool:
489
"""Whether QK-norm is applied. MuseGlimmer ALWAYS applies QK-norm; the modular HF
490
``text_config`` schema simply omits ``use_qk_norm`` (reads as ``None``).
492
- Treat a missing/None flag as True — only an explicit ``False`` disables it.
493
- """
491
+ Treat a missing/None flag as True — only an explicit ``False`` disables it."""
492
val = getattr(config, "use_qk_norm", None)
493
return True if val is None else bool(val)
494
@@ -498,8 +496,7 @@ def _muse_glimmer_use_qk_norm(config) -> bool:
496
def _muse_glimmer_use_attn_output_gate(config) -> bool:
497
"""Whether the per-head sigmoid attention output gate is applied. MuseGlimmer ALWAYS
498
applies it; the modular HF ``text_config`` omits ``use_attn_output_gate``
501
- (reads as ``None``). Missing/None -> True; only explicit ``False`` disables.
502
- """
499
+ (reads as ``None``). Missing/None -> True; only explicit ``False`` disables."""
500
val = getattr(config, "use_attn_output_gate", None)
501
return True if val is None else bool(val)
502
vllm/model_executor/models/nano_nemotron_vl.py
+1
-2
@@ -1188,8 +1188,7 @@ class NemotronH_Nano_VL_V2(
1188
self, video_input: NanoNemotronVLVideoPixelInputs
1189
) -> tuple[torch.Tensor, ...]:
1190
"""Process video input and create final embeddings with video content
1191
- and indicator tokens.
1192
- """
1191
+ and indicator tokens."""
1192
T = self.video_temporal_patch_size
1193
1194
if T > 1:
vllm/model_executor/models/phi4mm_utils.py
+1
-2
@@ -1462,8 +1462,7 @@ class NemoConvSubsampling(torch.nn.Module):
1462
1463
def conv_split_by_channel(self, x: Tensor) -> Tensor:
1464
"""For dw convs, tries to split input by time, run conv and concat
1465
- results
1466
- """
1465
+ results"""
1466
x = self.conv[0](x) # full conv2D
1467
x = self.conv[1](x) # activation
1468
vllm/model_executor/models/qwen3_dflash.py
+4
-8
@@ -69,8 +69,7 @@ def _dflash_layer_causal(config: Qwen3Config, layer_idx: int) -> bool:
69
70
def dflash_has_any_non_causal(config: Qwen3Config) -> bool:
71
"""Whether the draft needs a non-causal-capable backend, resolved from config
72
- (config mirror of the model's ``get_draft_attn_causal``, usable pre-build).
73
- """
72
+ (config mirror of the model's ``get_draft_attn_causal``, usable pre-build)."""
73
return not all(
74
_dflash_layer_causal(config, i) for i in range(config.num_hidden_layers)
75
)
@@ -155,8 +154,7 @@ class DFlashQwen3Attention(nn.Module):
154
155
Context KVs are pre-inserted into the KV cache before the forward pass.
156
This layer handles only query tokens via standard attention.
158
- Adapted from Qwen3Attention.
159
- """
157
+ Adapted from Qwen3Attention."""
158
159
def __init__(
160
self,
@@ -250,8 +248,7 @@ class DFlashQwen3Attention(nn.Module):
248
"""DFlash attention assumes that the KV cache is already populated
249
with the context K/V from the target model's hidden states. This forward op
250
computes attention for the query tokens only.
253
- See also: precompute_and_store_context_kv
254
- """
251
+ See also: precompute_and_store_context_kv"""
252
qkv, _ = self.qkv_proj(hidden_states)
253
q, k, v = qkv.split([self.q_size, self.kv_size, self.kv_size], dim=-1)
254
@@ -743,8 +740,7 @@ class DFlashQwen3ForCausalLM(Qwen3ForCausalLM):
740
741
def get_draft_attn_causal(self) -> list[bool]:
742
"""Per-layer attention causality, aligned with
746
- get_draft_kv_cache_layer_names.
747
- """
743
+ get_draft_kv_cache_layer_names."""
744
return [layer.self_attn.causal for layer in self.model.layers]
745
746
def compute_logits(
vllm/model_executor/models/qwen3_vl.py
+1
-2
@@ -1321,8 +1321,7 @@ class Qwen3VLMultiModalProcessor(BaseMultiModalProcessor[Qwen3VLProcessingInfo])
1321
def _expands_only_video_token(hf_processor: ProcessorMixin) -> bool:
1322
"""Transformers>=5.10 processors override `replace_video_token`
1323
to expand only the bare video token, keeping the prompt's outer
1324
- `<|vision_start|>`/`<|vision_end|>` markers.
1325
- """
1324
+ `<|vision_start|>`/`<|vision_end|>` markers."""
1325
mixin_impl = getattr(ProcessorMixin, "replace_video_token", None)
1326
proc_impl = getattr(type(hf_processor), "replace_video_token", None)
1327
return proc_impl is not None and proc_impl is not mixin_impl
vllm/model_executor/models/radio.py
+2
-4
@@ -599,8 +599,7 @@ class RadioInternVisionModel(nn.Module):
599
self, imgs_sizes: list[tuple[int, int]], device: torch.device
600
) -> MaskMetadata:
601
"""Build mask metadata from image pixel sizes. Adds num_skip to each
602
- sequence length (cls/register tokens) to match patch generator output.
603
- """
602
+ sequence length (cls/register tokens) to match patch generator output."""
603
patch_size = self.patch_generator.patch_size
604
num_skip = self.patch_generator.num_skip
605
@@ -613,8 +612,7 @@ class RadioInternVisionModel(nn.Module):
612
) -> MaskMetadata:
613
"""Build mask metadata from actual sequence lengths (already including
614
cls/register tokens, i.e. patch_count + num_skip per item).
616
- Use inter_image_mask_metadata() when you only have imgs_sizes.
617
- """
615
+ Use inter_image_mask_metadata() when you only have imgs_sizes."""
616
assert len(seq_lens) > 0
617
cu_seqlens = torch.tensor(
618
list(accumulate(seq_lens, initial=0)), dtype=torch.int32, device=device
vllm/model_executor/models/siglip2navit.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Implementation of SiglipVisionModel intended to be only used
4
-within a vision language model.
5
-"""
4
+within a vision language model."""
5
6
from collections.abc import Iterable
7
vllm/model_executor/models/stablelm.py
+1
-2
@@ -20,8 +20,7 @@
20
# https://huggingface.co/stabilityai/stablelm-3b-4e1t/blob/main/modeling_stablelm_epoch.py
21
# https://huggingface.co/stabilityai/stablelm-3b-4e1t/blob/main/config.json
22
"""Inference-only StableLM (https://github.com/Stability-AI/StableLM)
23
-model compatible with HuggingFace weights.
24
-"""
23
+model compatible with HuggingFace weights."""
24
25
from collections.abc import Iterable
26
from itertools import islice
vllm/model_executor/models/transformers/base.py
+2
-4
@@ -207,8 +207,7 @@ class Base(
207
def _mark_model_components(self, vllm_config: "VllmConfig"):
208
"""Mark language model and tower submodules as `self.model` is created.
209
210
- Nothing to do in `Base`, `MultiModalMixin` will override.
211
- """
210
+ Nothing to do in `Base`, `MultiModalMixin` will override."""
211
yield
212
213
@cached_property
@@ -281,8 +280,7 @@ class Base(
280
281
def _decorate_for_torch_compile(self):
282
"""Decorate the model's decoder class to indicate to vLLM that it
284
- supports torch compile if `can_enable_torch_compile` is True.
285
- """
283
+ supports torch compile if `can_enable_torch_compile` is True."""
284
self._decorate_cls_for_torch_compile(
285
cls=self._pre_trained_model_classes.decoder,
286
# Applied to a PreTrainedModel so the batch dimension will exist
vllm/model_executor/models/transformers/fusers/base.py
+9
-18
@@ -55,20 +55,17 @@ class BaseFuser(ABC):
55
self, module: nn.Module, prefix: str, vllm_config: "VllmConfig"
56
) -> nn.Module:
57
"""Apply the fusion to an already-validated `module`, returning the
58
- module to install in its place (mutated in place, or freshly built).
59
- """
58
+ module to install in its place (mutated in place, or freshly built)."""
59
60
def orig_to_new_stacked(self, prefix: str) -> dict[str, tuple[str, ShardId]]:
61
"""`WeightsMapper.orig_to_new_stacked` entries this fuser contributes
63
- (none unless it stacks weights).
64
- """
62
+ (none unless it stacks weights)."""
63
return {}
64
65
@property
66
def packed_modules_mapping(self) -> dict[str, list[str]]:
67
"""`packed_modules_mapping` entries this fuser contributes (none unless
70
- it stacks weights).
71
- """
68
+ it stacks weights)."""
69
return {}
70
71
@@ -122,8 +119,7 @@ class RewriteFuser(BaseFuser):
119
) -> nn.Module:
120
"""Fuse an already-validated `module` in place (see `Fusers.__getitem__`).
121
125
- Builds the merged submodule and binds the compiled forward.
126
- """
122
+ Builds the merged submodule and binds the compiled forward."""
123
self.update_attrs(module, prefix, vllm_config)
124
module.forward = types.MethodType(self.fused_forward, module)
125
return module
@@ -132,8 +128,7 @@ class RewriteFuser(BaseFuser):
128
@dataclass
129
class StackedFuser(RewriteFuser):
130
"""A fuser that merges sibling projections into one stacked linear and
135
- rewrites the forward to call it.
136
- """
131
+ rewrites the forward to call it."""
132
133
merged_name: ClassVar[str]
134
"""Attribute name of the merged module created by `update_attrs`."""
@@ -152,16 +147,14 @@ class StackedFuser(RewriteFuser):
147
def shards(self) -> list[tuple[str, ShardId]]:
148
"""Each projection's original name and its shard id in the merged module.
149
155
- Source for both `orig_to_new_stacked` and `packed_modules_mapping`.
156
- """
150
+ Source for both `orig_to_new_stacked` and `packed_modules_mapping`."""
151
152
def orig_to_new_stacked(self, prefix: str) -> dict[str, tuple[str, ShardId]]:
153
"""`WeightsMapper.orig_to_new_stacked` entries for one fused instance.
154
155
Maps each checkpoint name to `(merged_name, shard_id)`, keyed by qualname
156
so only this exact layer is remapped, never a same-named projection
163
- elsewhere (e.g. an unfused MoE expert's `gate_proj`).
164
- """
157
+ elsewhere (e.g. an unfused MoE expert's `gate_proj`)."""
158
merged = maybe_prefix(prefix, self.merged_name)
159
return {
160
maybe_prefix(prefix, name): (merged, shard) for name, shard in self.shards
@@ -170,8 +163,7 @@ class StackedFuser(RewriteFuser):
163
@property
164
def packed_modules_mapping(self) -> dict[str, list[str]]:
165
"""`{merged_name: [projection names]}` so quantization can unpack the
173
- fused layer into its per-shard configs.
174
- """
166
+ fused layer into its per-shard configs."""
167
return {self.merged_name: [name for name, _ in self.shards]}
168
169
def _unguarded_calls(
@@ -182,8 +174,7 @@ class StackedFuser(RewriteFuser):
174
`update_attrs` deletes the projections it merges, so any reference to one beyond
175
its call site must be a guard on its existence; folding those to their constant
176
value keeps the rewritten forward off a name that no longer exists. A reference
185
- that is not such a guard raises, so fusion is skipped.
186
- """
177
+ that is not such a guard raises, so fusion is skipped."""
178
calls = []
179
for name in names:
180
call, refs = self_call_and_refs(funcdef, name)
vllm/model_executor/models/transformers/fusers/mla.py
+1
-2
@@ -232,8 +232,7 @@ class MLAFuser(StackedFuser):
232
def update_forward(self, module: nn.Module) -> None:
233
"""Merge `q_a_proj` and `kv_a_proj` into one fused down proj then split.
234
Bypass the KV expansion method so the compressed latent reaches the `vllm_mla`
235
- attention interface unexpanded.
236
- """
235
+ attention interface unexpanded."""
236
funcdef, fn = recover_forward(type(module))
237
if self.has_q_lora:
238
# q_a_proj is usually inside the `else` of `if self.q_lora_rank is None`.
vllm/model_executor/models/transformers/fusers/moe.py
+4
-8
@@ -80,8 +80,7 @@ def _forced_dtype(nodes: Iterable[fx.Node]) -> torch.dtype | None:
80
81
Computations that must run in higher precision say so in their forward (e.g.
82
`hidden_states.type(torch.float32)`), so the dtype is readable from the graph
83
- even when the config does not name it.
84
- """
83
+ even when the config does not name it."""
84
for node in nodes:
85
if node.op not in ("call_method", "call_function"):
86
continue
@@ -126,8 +125,7 @@ class SharedExpertMLP(nn.Module):
125
def _moe_block_forward(self: nn.Module, hidden_states: torch.Tensor) -> torch.Tensor:
126
"""Standard MoE block forward.
127
129
- Routing and any shared experts are handled inside `self.experts: MoERunner`.
130
- """
128
+ Routing and any shared experts are handled inside `self.experts: MoERunner`."""
129
orig_shape = hidden_states.shape
130
hidden_states = hidden_states.reshape(-1, orig_shape[-1])
131
num_tokens = hidden_states.shape[0]
@@ -154,8 +152,7 @@ class MoEBlockFuser:
152
def _match_router(gate: nn.Module) -> tuple[str, torch.dtype | None] | None:
153
"""Matches `topk(score(linear(x)))`, `score` being `softmax`/`sigmoid`.
154
157
- Returns the scoring function and the dtype the router computes in.
158
- """
155
+ Returns the scoring function and the dtype the router computes in."""
156
state = {name for name, _ in named_state(gate)}
157
if "weight" not in state or state - {"weight", "e_score_correction_bias"}:
158
return None
@@ -283,8 +280,7 @@ class MoEBlockFuser:
280
self, moe_block: nn.Module, prefix: str
281
) -> SharedExpertMLP | None:
282
"""Build the HF shared expert (and its optional gate)
286
- as a `SharedExpertMLP` for vLLM's fused MoE.
287
- """
283
+ as a `SharedExpertMLP` for vLLM's fused MoE."""
284
if self.shared_name is None:
285
return None
286
shared_experts = getattr(moe_block, self.shared_name)
vllm/model_executor/models/transformers/fx_utils.py
+11
-22
@@ -43,8 +43,7 @@ def _reference_weight(module: nn.Module) -> torch.Tensor | None:
43
"""A weight whose trailing dim is the module's hidden size.
44
45
Linears and 2-D gate weights are `[out, hidden]`; norm weights are
46
- `[hidden]`. Used to fabricate a placeholder input of matching size/dtype.
47
- """
46
+ `[hidden]`. Used to fabricate a placeholder input of matching size/dtype."""
47
for child in module.modules():
48
if isinstance(child, nn.Linear):
49
return child.weight
@@ -59,8 +58,7 @@ class _MetaProxy(fx.Proxy):
58
59
Shape questions (`len`, iteration, `.shape` unpacks) are answered by
60
executing each op on the meta values, so PyTorch's meta kernels are the
62
- single source of shape inference — no per-op rules.
63
- """
61
+ single source of shape inference — no per-op rules."""
62
63
meta: object = _UNKNOWN
64
@@ -84,8 +82,7 @@ class _MetaAttribute(_MetaProxy, fx.proxy.Attribute):
82
"""Attribute proxy (e.g. `x.shape`) carrying its meta value.
83
84
`Proxy.__getattr__` constructs `Attribute` directly, bypassing
87
- `Tracer.proxy`, so the meta value must be grafted on here too.
88
- """
85
+ `Tracer.proxy`, so the meta value must be grafted on here too."""
86
87
def __init__(self, root: fx.Proxy, attr: str):
88
super().__init__(root, attr)
@@ -221,8 +218,7 @@ def _leaf_attention_interfaces():
218
"""Patch `AttentionInterface.get_interface` so traced forwards see a leaf node.
219
220
`vllm_attention_function` needs runtime context so it is untraceable.
224
- Every interface returns `(attn_output, attn_weights)`.
225
- """
221
+ Every interface returns `(attn_output, attn_weights)`."""
222
from transformers.modeling_utils import AttentionInterface
223
224
original = AttentionInterface.get_interface
@@ -300,8 +296,7 @@ def forward_parameters(cls: type[nn.Module]) -> dict[str, inspect.Parameter]:
296
def forward_input_count(cls: type[nn.Module]) -> int:
297
"""The number of tensor inputs `cls.forward` declares, excluding `self` and
298
any `*args`/`**kwargs`. Read from the signature, so it is independent of
303
- whether the trace completes (unlike counting placeholders).
304
- """
299
+ whether the trace completes (unlike counting placeholders)."""
300
params = list(forward_parameters(cls).values())
301
if not params:
302
return 1 # uninspectable: assume a single input and let matching decide
@@ -378,8 +373,7 @@ def _in_boolean_context(funcdef: ast.FunctionDef, ref: ast.expr) -> bool:
373
374
In these positions the object's identity never escapes, so a reference that
375
is always truthy can be replaced by `True`. `and`/`or` are excluded: they
381
- yield an operand, so the module could escape (`x and self.<name>`).
382
- """
376
+ yield an operand, so the module could escape (`x and self.<name>`)."""
377
for node in ast.walk(funcdef):
378
if (
379
isinstance(node, (ast.If, ast.IfExp, ast.While, ast.Assert))
@@ -412,8 +406,7 @@ def bypass_existence_guard(
406
`not self.<name>`): the reference itself to `True`.
407
408
Any other surviving reference escapes the projection's value, which no longer
415
- exists after fusion, so refuse rather than change semantics.
416
- """
409
+ exists after fusion, so refuse rather than change semantics."""
410
for node in ast.walk(funcdef):
411
# `self.<name> is (not) None`, either operand order.
412
if not (isinstance(node, ast.Compare) and len(node.ops) == 1):
@@ -474,8 +467,7 @@ def _base_name(node: ast.expr) -> str | None:
467
def _rebound_names(region: list[ast.stmt]) -> set[str]:
468
"""Names rebound outright within `region` (`x = ...`, `del x`).
469
477
- These are `Name` nodes in a `Store`/`Del` context.
478
- """
470
+ These are `Name` nodes in a `Store`/`Del` context."""
471
return {
472
node.id
473
for stmt in region
@@ -489,8 +481,7 @@ def _inplace_target(node: ast.AST) -> str | None:
481
482
A write through the name (`x[i] = ...`, `x.attr = ...`) or an in-place method
483
call (`x.mul_(...)`) leaves the base name in a `Load` context, so it is not a
492
- plain `Name` store (see `_rebound_names`).
493
- """
484
+ plain `Name` store (see `_rebound_names`)."""
485
if isinstance(node, (ast.Attribute, ast.Subscript)) and isinstance(
486
node.ctx, (ast.Store, ast.Del)
487
):
@@ -711,8 +702,7 @@ def upstream_linear(node: object, module: nn.Module) -> fx.Node | None:
702
Non-linear submodules are transparent too (e.g. the dropout GPT-style
703
attentions apply after their output projection). Never walks through a leaf
704
call (e.g. an attention interface): its inputs are what attention consumes,
714
- not what produced the value.
715
- """
705
+ not what produced the value."""
706
stack = [node]
707
seen: set[fx.Node] = set()
708
while stack:
@@ -735,8 +725,7 @@ def downstream_linear(node: fx.Node, module: nn.Module) -> fx.Node | None:
725
"""Nearest linear consuming `node`'s output, walking through casts/scalings.
726
727
Never walks through a leaf call (e.g. an attention interface): what crosses
738
- it is consumed by the attention computation, not projected.
739
- """
728
+ it is consumed by the attention computation, not projected."""
729
queue = list(node.users)
730
seen: set[fx.Node] = set()
731
while queue:
vllm/model_executor/models/transformers/layers.py
+1
-2
@@ -22,8 +22,7 @@ _VLLM_PKG = "vllm.model_executor.layers"
22
23
def _resolve(module: str, name: str):
24
"""Return `name` from the hw-agnostic `module` when enabled and available,
25
- else from vLLM. Logs which source was used.
26
- """
25
+ else from vLLM. Logs which source was used."""
26
if envs.VLLM_USE_HW_AGNOSTIC:
27
try:
28
obj = getattr(importlib.import_module(f"{_HW_PKG}.{module}"), name)
vllm/model_executor/models/transformers/moe.py
+2
-4
@@ -75,8 +75,7 @@ class TransformersMoERunner(MoERunner):
75
) -> torch.Tensor:
76
"""In Transformers `experts.forward` will have this signature.
77
78
- We discard any extra kwargs because we cannot use them here.
79
- """
78
+ We discard any extra kwargs because we cannot use them here."""
79
# Note: we need to forward through a custom op so the topk_ids
80
# can be transferred without interfering with cudagraphs.
81
return torch.ops.vllm.transformers_moe_forward(
@@ -368,8 +367,7 @@ class MoEMixin(MixtureOfExperts):
367
moe_state: TransformersMoEState,
368
):
369
"""Return `topk_weights` from `gating_output` and the
371
- `topk_ids` we stored in the layer earlier.
372
- """
370
+ `topk_ids` we stored in the layer earlier."""
371
topk_weights = gating_output
372
topk_ids = moe_state.topk_ids
373
assert topk_ids is not None
vllm/model_executor/models/transformers/multimodal.py
+8
-16
@@ -424,8 +424,7 @@ class LegacyMultiModalProcessor(_MultiModalProcessorBase):
424
out_mm_kwargs: MultiModalKwargsItems,
425
) -> Sequence[PromptUpdate]:
426
"""Empty, because `apply` writes the placeholder ranges itself rather than
427
- deriving them from updates.
428
- """
427
+ deriving them from updates."""
428
return []
429
430
def _get_mm_token_ids(self, modality: str) -> list[int]:
@@ -459,8 +458,7 @@ class LegacyMultiModalProcessor(_MultiModalProcessorBase):
458
num_audios: int,
459
) -> dict[str, list[PlaceholderRange]]:
460
"""Take each contiguous run of the audio token as one item's placeholder,
462
- and record how many tokens the run holds.
463
- """
461
+ and record how many tokens the run holds."""
462
audio_token_ids = self._get_mm_token_ids("audio")
463
prompt_tensor = torch.tensor(prompt_ids)
464
is_audio = torch.isin(prompt_tensor, torch.tensor(audio_token_ids))
@@ -518,8 +516,7 @@ class LegacyMultiModalProcessor(_MultiModalProcessorBase):
516
mm_token_type_ids: torch.Tensor | None,
517
) -> dict[str, list[PlaceholderRange]]:
518
"""Split the positions the processor marks as image into one placeholder per
521
- item, sized by the token count it reports for each image.
522
- """
519
+ item, sized by the token count it reports for each image."""
520
hf_processor = self.info.get_hf_processor(**hf_processor_mm_kwargs)
521
if mm_token_type_ids is None:
522
raise ValueError(
@@ -572,8 +569,7 @@ class LegacyMultiModalProcessor(_MultiModalProcessorBase):
569
timing_ctx: TimingContext,
570
) -> MultiModalInput:
571
"""Process the prompt and every multi-modal item in one HF processor call,
575
- then read the placeholder ranges out of the token ids it returns.
576
- """
572
+ then read the placeholder ranges out of the token ids it returns."""
573
prompt = inputs.prompt
574
mm_items = inputs.mm_data_items
575
hf_processor_mm_kwargs = inputs.hf_processor_mm_kwargs
@@ -711,8 +707,7 @@ class OffsetsMultiModalProcessor(_MultiModalProcessorBase):
707
out_mm_kwargs: MultiModalKwargsItems,
708
) -> Sequence[PromptUpdate]:
709
"""Replace each modality's placeholder token with the token ids that item's
714
- replacement text encodes to, marking which of them hold embeddings.
715
- """
710
+ replacement text encodes to, marking which of them hold embeddings."""
711
hf_processor = self.info.get_hf_processor(**hf_processor_mm_kwargs)
712
tokenizer = self.info.get_tokenizer()
713
@@ -907,8 +902,7 @@ class MultiModalMixin(SupportsMultiModal, SupportsMRoPE):
902
self, model: "PreTrainedModel"
903
) -> dict[str, type["PreTrainedModel"]]:
904
"""Modalities whose encoder cannot be told apart from the model itself are
910
- omitted, as are those `get_encoder` rejects.
911
- """
905
+ omitted, as are those `get_encoder` rejects."""
906
encoder_classes: dict[str, type[PreTrainedModel]] = {}
907
for modality in _MODALITY_TO_TOKEN_TYPE_ID:
908
try:
@@ -1027,8 +1021,7 @@ class MultiModalMixin(SupportsMultiModal, SupportsMRoPE):
1021
def get_language_model(self) -> torch.nn.Module:
1022
"""Transformers modeling backend multimodal classes do not contain a separate
1023
vLLM language model class. Therefore, in order to return a language model vLLM
1030
- class, we use a wrapper to give `self` the same interface as a text model.
1031
- """
1024
+ class, we use a wrapper to give `self` the same interface as a text model."""
1025
# Exclude self and object
1026
bases = self.__class__.mro()[1:-1]
1027
# Keep only classes defined in `vllm.model_executor.models.transformers`
@@ -1182,8 +1175,7 @@ class MultiModalMixin(SupportsMultiModal, SupportsMRoPE):
1175
) -> dict[str, Any]:
1176
"""Narrow the entries of `kwargs` that hold one row per item down to the item
1177
at `index`. Length is all there is to match on, so an unrelated entry of the
1185
- same length is narrowed too.
1186
- """
1178
+ same length is narrowed too."""
1179
return {
1180
key: value[index : index + 1]
1181
if isinstance(value, (torch.Tensor, list)) and len(value) == num_items
vllm/model_executor/models/transformers/utils.py
+2
-4
@@ -201,8 +201,7 @@ def attrsetter(attr: str) -> Callable[[object, object], None]:
201
202
class _UninitializedEmbedding(nn.Embedding):
203
"""Make `__init__` inert, so that `VocabParallelEmbedding.__init__`'
204
- call to `super().__init__` does not invoke `nn.Embedding.__init__`.
205
- """
204
+ call to `super().__init__` does not invoke `nn.Embedding.__init__`."""
205
206
def __init__(self):
207
pass
@@ -210,8 +209,7 @@ class _UninitializedEmbedding(nn.Embedding):
209
210
class _VocabParallelEmbeddingBase(VocabParallelEmbedding, _UninitializedEmbedding):
211
"""Orders `VocabParallelEmbedding` ahead of `nn.Embedding` in the MRO, so that
213
- `super().forward(...)` in an `nn.Embedding` subclass reaches vLLM's embedding.
214
- """
212
+ `super().forward(...)` in an `nn.Embedding` subclass reaches vLLM's embedding."""
213
214
215
@lru_cache
vllm/model_executor/models/utils.py
+2
-4
@@ -47,8 +47,7 @@ ShardId: TypeAlias = str | int | tuple[int, ...]
47
class WeightsMapper:
48
"""Maps the name of each weight if they match the following patterns.
49
50
- If a key maps to a value of `None`, the corresponding weight is ignored.
51
- """
50
+ If a key maps to a value of `None`, the corresponding weight is ignored."""
51
52
orig_to_new_renaming: list["WeightRenaming"] = field(default_factory=list)
53
orig_to_new_regex: Mapping[re.Pattern, str | None] = field(default_factory=dict)
@@ -172,8 +171,7 @@ class WeightsMapper:
171
rather than being rewritten to the stacked vLLM name (`qkv_proj`). Mappings to
172
`None` are dropped because "do not load this weight" is meaningless to such a
173
consumer, and applying it would silently shrink a quantization config's ignore
175
- list or make LoRA name parsing fail.
176
- """
174
+ list or make LoRA name parsing fail."""
175
remove_none = lambda d: {k: v for k, v in d.items() if v is not None}
176
return replace(
177
self,
vllm/model_executor/models/vision.py
+1
-2
@@ -116,8 +116,7 @@ def get_multimodal_config() -> MultiModalConfig | None:
116
"""Return the current ``MultiModalConfig``, or ``None`` when no engine
117
config context is active (e.g., during unit tests) or when the current
118
``model_config`` does not carry a ``multimodal_config`` (e.g., minimal
119
- stubs used in tests).
120
- """
119
+ stubs used in tests)."""
120
vllm_config = get_current_vllm_config_or_none()
121
if vllm_config is None or vllm_config.model_config is None:
122
return None
vllm/model_executor/utils.py
+1
-2
@@ -174,8 +174,7 @@ def get_moe_expert_mapping(
174
175
It will be retrieved from the first module that has a `get_expert_mapping` method.
176
If the model manually implements `get_expert_mapping`, it will be used.
177
- Otherwise, it will use the first RoutedExperts layer.
178
- """
177
+ Otherwise, it will use the first RoutedExperts layer."""
178
for _, module in model.named_modules():
179
get_mapping = getattr(module, "get_expert_mapping", None)
180
if get_mapping is not None:
vllm/model_executor/warmup/qwen4_exp_qsa_warmup.py
+1
-2
@@ -18,8 +18,7 @@ logger = init_logger(__name__)
18
19
def qwen4_exp_qsa_triton_warmup(worker: "Worker") -> None:
20
"""Warm every reachable QSA specialization: indexer decode-query-length
21
- profiles plus the sparse attention split-K/merge configs.
22
- """
21
+ profiles plus the sparse attention split-K/merge configs."""
22
qsa_module = sys.modules.get("vllm.models.qwen4_exp.nvidia.indexer_qsa")
23
attn_module = sys.modules.get("vllm.models.qwen4_exp.nvidia.qsa")
24
if qsa_module is None or attn_module is None:
vllm/models/deepseek_v32/common/kernels.py
+1
-2
@@ -1059,8 +1059,7 @@ def _fused_eh_norm_kernel(
1059
):
1060
"""MTP input fusion: zero embeds at position 0, RMSNorm(embeds) with enorm
1061
and RMSNorm(prev_hidden) with hnorm, written side-by-side into ``out``
1062
- ([N, 2H]) ready for the eh_proj GEMM. Replaces where + 2x RMSNorm + cat.
1063
- """
1062
+ ([N, 2H]) ready for the eh_proj GEMM. Replaces where + 2x RMSNorm + cat."""
1063
tok = tl.program_id(0)
1064
off = tl.arange(0, BLOCK)
1065
mask = off < H
vllm/models/deepseek_v4/amd/model.py
+1
-2
@@ -1425,8 +1425,7 @@ class DeepseekV4ForCausalLM(nn.Module, SupportsPP, SupportsEagle3):
1425
def get_mtp_target_hidden_states(self) -> torch.Tensor | None:
1426
"""Pre-hc_head residual stream buffer (max_num_batched_tokens,
1427
hc_mult * hidden_size) for the MTP draft model. Populated by
1428
- forward(); valid after each target step.
1429
- """
1428
+ forward(); valid after each target step."""
1429
return getattr(self.model, "_mtp_hidden_buffer", None)
1430
1431
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
vllm/models/deepseek_v4/common/mm_preprocess.py
+3
-6
@@ -91,8 +91,7 @@ def validate_image_sentinel_ids(tokenizer) -> None:
91
92
def grid_tokens(best_height, best_width, patch_size, downsample_ratio):
93
"""Number of LLM tokens the aligner grid occupies (N-layout, including
94
- row/align padding).
95
- """
94
+ row/align padding)."""
95
n_llm_h = math.ceil((best_height // patch_size) / downsample_ratio)
96
n_llm_w = math.ceil((best_width // patch_size) / downsample_ratio)
97
num_tokens = n_llm_h * (n_llm_w + 1) + 2
@@ -197,8 +196,7 @@ def load_image(
196
197
def build_image_block(n_llm_h: int, n_llm_w: int, start_pos: int):
198
"""Builds the N-layout token types (final order) and the aligner-row order
200
- for IMAGE slots.
201
- """
199
+ for IMAGE slots."""
200
compress_pad = COMPRESS_PAD_TO - 1 - start_pos % COMPRESS_PAD_TO
201
pad_h = n_llm_h % 2
202
rows = n_llm_h + pad_h
@@ -241,8 +239,7 @@ def build_image_block_pad_free(n_llm_h: int, n_llm_w: int):
239
240
class DeepseekV4VLImageProcessor:
241
"""Per-image transform (the PIL-input equivalent of the reference
244
- ``load_image``).
245
- """
242
+ ``load_image``)."""
243
244
def __init__(self, config: DeepseekV4Config) -> None:
245
super().__init__()
vllm/models/deepseek_v4/common/ops/fused_indexer_q.py
+1
-2
@@ -312,8 +312,7 @@ class FusedIndexerQRopeQuantTritonKernel(
312
def _indexer_weights_out_dtypes(vllm_config: Any) -> tuple[torch.dtype, ...]:
313
"""Weights dtypes the model's indexer layers ask for: fp32 for the dense
314
scoring kernels, plus bf16 when the DeepSeek V4.1 sparse-logits indexer
315
- (`SparseMQAIndexer`) is enabled.
316
- """
315
+ (`SparseMQAIndexer`) is enabled."""
316
if vllm_config.attention_config.indexer_sparse_logits:
317
return (torch.float32, torch.bfloat16)
318
return (torch.float32,)
vllm/models/deepseek_v4/cpu/cpu_compressor.py
+1
-2
@@ -42,8 +42,7 @@ class DeepseekV4CPUCompressor(DeepseekCompressor):
42
weight loading (see
43
``DeepseekV4CPUAttention.process_weights_after_loading``) -- the CPU
44
kernel requires fp32/contiguous but the checkpoint loads this weight
45
- in bf16, and it never changes after loading.
46
- """
45
+ in bf16, and it never changes after loading."""
46
self._norm_weight_fp32 = self.norm.weight.to(torch.float32).contiguous()
47
48
def forward(
vllm/models/deepseek_v4/cpu/cpu_mla.py
+1
-2
@@ -118,8 +118,7 @@ class DeepseekV4CPUSparseSWAMetadataBuilder(DeepseekSparseSWAMetadataBuilder):
118
) -> dict[str, FlashMLASchedMeta | None]:
119
"""CPU never runs the FlashMLA tile-scheduler planner (that's a CUDA
120
C++ decode-path concern) -- always return the all-``None`` sentinel
121
- the shared base's own CPU branch returns.
122
- """
121
+ the shared base's own CPU branch returns."""
122
return {
123
_LAYER_TYPE_SWAONLY: None,
124
_LAYER_TYPE_C4A: None,
vllm/models/deepseek_v4/cpu/cpu_sparse.py
+8
-16
@@ -176,15 +176,13 @@ def _fused_indexer_q_rope_quant_cpu(
176
177
class _NoOpEvent:
178
"""Stand-in for ``torch.cuda.Event`` on CPU: since CPU never sets an aux
179
- stream list, these events are constructed but never actually used.
180
- """
179
+ stream list, these events are constructed but never actually used."""
180
181
182
class DeepseekV4CPUIndexerCache(DeepseekV4IndexerCache):
183
"""CPU indexer K-cache descriptor: same fields as the shared base, just
184
pointing ``get_attn_backend()`` at ``DeepseekV4CPUIndexerBackend``
186
- instead of the shared, CUDA/XPU-oriented ``DeepseekV4IndexerBackend``.
187
- """
185
+ instead of the shared, CUDA/XPU-oriented ``DeepseekV4IndexerBackend``."""
186
187
def get_attn_backend(self) -> type[AttentionBackend]:
188
return DeepseekV4CPUIndexerBackend
@@ -211,8 +209,7 @@ class DeepseekV4CPUIndexer(DeepseekV4Indexer):
209
compressor run straight-line instead of through
210
``maybe_execute_in_parallel``; the short-context check drops the
211
CUDA-only ``is_current_stream_capturing()`` guard (always False
214
- here).
215
- """
212
+ here)."""
213
compressor = self.compressor
214
215
attn_metadata = get_forward_context().attn_metadata
@@ -312,8 +309,7 @@ class DeepseekV4CPUAttention(DeepseekV4Attention):
309
"""Snapshot and pack ``wo_a``'s weight into a bf16 copy for
310
``bmm_cpu`` before the FP8 kernel's own
311
``process_weights_after_loading`` VNNI-repacks it in place for
315
- row-major reads ``_o_proj`` never does.
316
- """
312
+ row-major reads ``_o_proj`` never does."""
313
wo_a = self.wo_a
314
quant_method = wo_a.quant_method
315
orig_pwal = quant_method.process_weights_after_loading
@@ -404,8 +400,7 @@ class DeepseekV4CPUAttention(DeepseekV4Attention):
400
) -> torch.Tensor:
401
"""CPU override: only the fp8_ds_mla (uint8) SWA cache layout is
402
supported here, so the base method's bf16/per-tensor-fp8 branches
407
- are dropped.
408
- """
403
+ are dropped."""
404
if not isinstance(attn_metadata, dict):
405
# Profile run: kernel doesn't fire; produce a padded tensor so
406
# downstream FlashMLA gets the right shape.
@@ -450,8 +445,7 @@ class DeepseekV4CPUAttention(DeepseekV4Attention):
445
) -> tuple[torch.Tensor, torch.Tensor | None, torch.Tensor]:
446
"""CPU override: two ``RMSNorm`` calls instead of the shared
447
``fused_q_kv_rmsnorm``, whose raw ``@triton.jit`` kernel fails to
453
- link under triton-cpu (``undefined symbol: __truncdfbf2``).
454
- """
448
+ link under triton-cpu (``undefined symbol: __truncdfbf2``)."""
449
qr, kv = qr_kv.split([self.q_lora_rank, self.head_dim], dim=-1)
450
return self.q_norm(qr), None, self.kv_norm(kv)
451
@@ -469,8 +463,7 @@ class DeepseekV4CPUAttention(DeepseekV4Attention):
463
) -> None:
464
"""CPU override: no aux streams, so query-projection+KV-insert, the
465
indexer, and the compressor run straight-line instead of through
472
- execute_in_parallel/maybe_execute_in_parallel.
473
- """
466
+ execute_in_parallel/maybe_execute_in_parallel."""
467
attn_metadata = get_forward_context().attn_metadata
468
indexer = self.indexer
469
compressor = self.compressor
@@ -519,8 +512,7 @@ class DeepseekV4CPUAttention(DeepseekV4Attention):
512
out: torch.Tensor,
513
) -> None:
514
"""CPU override: identical body, minus ``@eager_break_during_capture``
522
- (this platform never captures a CUDA graph, so it was a no-op).
523
- """
515
+ (this platform never captures a CUDA graph, so it was a no-op)."""
516
if self.indexer is not None and index_q is not None:
517
assert index_weights is not None
518
# index_q_scale is always None on CPU (FP8-only path).
vllm/models/deepseek_v4/cpu/model.py
+1
-2
@@ -907,8 +907,7 @@ class DeepseekV4ForCausalLM(nn.Module, SupportsPP, SupportsEagle3):
907
def get_mtp_target_hidden_states(self) -> torch.Tensor | None:
908
"""Pre-hc_head residual stream buffer (max_num_batched_tokens,
909
hc_mult * hidden_size) for the MTP draft model. Populated by
910
- forward(); valid after each target step.
911
- """
910
+ forward(); valid after each target step."""
911
return getattr(self.model, "_mtp_hidden_buffer", None)
912
913
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
vllm/models/deepseek_v4/nvidia/fi_moe.py
+1
-2
@@ -159,8 +159,7 @@ class DeepseekV4MegaMoEExpertsFI(DeepseekV4MegaMoEExperts):
159
def _realloc_nvfp4_params(self) -> None:
160
"""Swap the mx-recipe scale params for the NVFP4 checkpoint's:
161
fp8-e4m3 per-16 block scales plus the per-tensor second-level
162
- scales (weight_scale_2, input_scale) modelopt exports.
163
- """
162
+ scales (weight_scale_2, input_scale) modelopt exports."""
163
n_e = self.num_local_experts
164
inter = self.intermediate_size
165
hidden = self.hidden_size
vllm/models/deepseek_v4/nvidia/flashinfer_sparse.py
+1
-2
@@ -56,8 +56,7 @@ def _get_flashinfer_dsv4_workspace(device: torch.device) -> torch.Tensor:
56
def _packed_block_span(pool: torch.Tensor) -> int:
57
"""Per-block stride of ``pool`` in tokens (``stride(0)//stride(-2)``): ==
58
block_size for unpacked KV, larger when packed (#44577). Raises if not
59
- token-aligned.
60
- """
59
+ token-aligned."""
60
block_stride = pool.stride(0)
61
token_stride = pool.stride(-2)
62
if block_stride % token_stride != 0:
vllm/models/deepseek_v4/nvidia/model.py
+1
-2
@@ -1985,8 +1985,7 @@ class DeepseekV4ForCausalLM(
1985
def get_mtp_target_hidden_states(self) -> torch.Tensor | None:
1986
"""Pre-hc_head residual stream buffer (max_num_batched_tokens,
1987
hc_mult * hidden_size) for the MTP draft model. Populated by
1988
- forward(); valid after each target step.
1989
- """
1988
+ forward(); valid after each target step."""
1989
return getattr(self.model, "_mtp_hidden_buffer", None)
1990
1991
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
vllm/models/deepseek_v4/xpu/model.py
+1
-2
@@ -1378,8 +1378,7 @@ class DeepseekV4ForCausalLM(nn.Module, SupportsPP, SupportsEagle3, SupportsLoRA)
1378
def get_mtp_target_hidden_states(self) -> torch.Tensor | None:
1379
"""Pre-hc_head residual stream buffer (max_num_batched_tokens,
1380
hc_mult * hidden_size) for the MTP draft model. Populated by
1381
- forward(); valid after each target step.
1382
- """
1381
+ forward(); valid after each target step."""
1382
return getattr(self.model, "_mtp_hidden_buffer", None)
1383
1384
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
vllm/models/deepseek_v41/amd/model.py
+2
-4
@@ -1062,8 +1062,7 @@ class DeepseekV41LLMForCausalLM(
1062
@property
1063
def token_lookback_depth(self) -> int:
1064
"""Tokens before a chunk start the engram hash needs; the model runner
1065
- passes them as `lookback_token_ids`.
1066
- """
1065
+ passes them as `lookback_token_ids`."""
1066
engram_hash = self.model.engram_hash
1067
return engram_hash.lookback_depth if engram_hash is not None else 0
1068
@@ -1087,8 +1086,7 @@ class DeepseekV41LLMForCausalLM(
1086
def get_mtp_target_hidden_states(self) -> torch.Tensor | None:
1087
"""Pre-collapse residual stream buffer (max_num_batched_tokens,
1088
hc_mult * hidden_size) for the MTP draft model. Populated by
1090
- forward(); valid after each target step.
1091
- """
1089
+ forward(); valid after each target step."""
1090
return getattr(self.model, "_mtp_hidden_buffer", None)
1091
1092
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
vllm/models/deepseek_v41/amd/vl_model.py
+1
-2
@@ -209,8 +209,7 @@ class DeepseekV41ForCausalLM(nn.Module, SupportsMultiModal, SupportsPP, Supports
209
self, image_embeds: torch.Tensor, types: torch.Tensor
210
) -> torch.Tensor:
211
"""Full image span: aligner rows at IMAGE slots, the learned
212
- delimiter vectors at IMAGE_START/IMAGE_NEW_LINE/IMAGE_END.
213
- """
212
+ delimiter vectors at IMAGE_START/IMAGE_NEW_LINE/IMAGE_END."""
213
types = types.to(image_embeds.device)
214
span = image_embeds.new_empty(types.numel(), image_embeds.shape[-1])
215
dtype = image_embeds.dtype
vllm/models/deepseek_v41/attention.py
+1
-2
@@ -1066,8 +1066,7 @@ class DeepseekV4Attention(nn.Module, AttentionLayerBase, ABC):
1066
1067
def _compressed_kv_cache(self) -> torch.Tensor:
1068
"""The compressed-KV cache tensor of this layer's kv source (own
1069
- cache for kv-source layers).
1070
- """
1069
+ cache for kv-source layers)."""
1070
if self.is_kv_source:
1071
return self.kv_cache
1072
assert self.compressed_cache_prefix is not None
vllm/models/deepseek_v41/common/engram.py
+3
-6
@@ -564,8 +564,7 @@ def _engram_head_shard_weight_loader(
564
param: torch.nn.Parameter, loaded_weight: torch.Tensor
565
) -> None:
566
"""Load this rank's complete head buckets. ue8m0 scales arrive as
567
- float8_e8m0fnu; keep the raw bytes (the param stores uint8).
568
- """
567
+ float8_e8m0fnu; keep the raw bytes (the param stores uint8)."""
568
part_rows = param.shape[0]
569
if loaded_weight.dtype == torch.float8_e8m0fnu:
570
loaded_weight = loaded_weight.view(torch.uint8)
@@ -740,8 +739,7 @@ class ParallelEngramEmbedding(nn.Module):
739
740
def forward(self, indices: torch.Tensor) -> torch.Tensor:
741
"""indices: [num_tokens, n_hash_cols] -> [num_tokens, n_hash_cols, dim]
743
- bf16, gathered from all shards for this replica's tokens.
744
- """
742
+ bf16, gathered from all shards for this replica's tokens."""
743
out = torch.empty(
744
(indices.shape[0], self.part_n_hash_cols, self.dim),
745
dtype=torch.bfloat16,
@@ -1002,8 +1000,7 @@ class Engram(nn.Module):
1000
) -> torch.Tensor:
1001
"""hidden_states: [T, hc_mult, dim]; hash_ids: [T, n_hash_cols] (all
1002
tokens, pre sequence-parallel shard); token_mask: [T], False shuts
1005
- the gate so those positions pass through untouched.
1006
- """
1003
+ the gate so those positions pass through untouched."""
1004
kv = self.wkv(self.embed(hash_ids).flatten(-2))
1005
num_kv_tokens = hash_ids.shape[0]
1006
assert token_mask is None or token_mask.shape == (num_kv_tokens,)
vllm/models/deepseek_v41/common/mm_preprocess.py
+3
-6
@@ -82,8 +82,7 @@ def num_image_tokens(n_llm_h: int, n_llm_w: int) -> int:
82
83
def solve_resize_ratio(height, width, patch_size, downsample_ratio, max_n_token):
84
"""Largest aspect-preserving pixel size whose token grid still fits in
85
- max_n_token. Returns (best_height, best_width).
86
- """
85
+ max_n_token. Returns (best_height, best_width)."""
86
r = height / width
87
max_w_float = math.sqrt((max_n_token - 2) / r + 0.25) - 0.5
88
max_h_float = max_w_float * r
@@ -106,8 +105,7 @@ def safe_resize(
105
height, width, best_height, best_width, patch_size, downsample_ratio, max_n_token
106
):
107
"""Shrink the pixel size until the image costs at most max_n_token LLM
109
- tokens.
110
- """
108
+ tokens."""
109
n_llm_h, n_llm_w = llm_grid(best_height, best_width, patch_size, downsample_ratio)
110
if num_image_tokens(n_llm_h, n_llm_w) > max_n_token:
111
best_height, best_width = solve_resize_ratio(
@@ -173,8 +171,7 @@ def image_token_types(n_llm_h: int, n_llm_w: int) -> torch.Tensor:
171
172
class DeepseekV4VLImageProcessor:
173
"""Per-image transform (the PIL-input equivalent of the reference
176
- ``load_image``).
177
- """
174
+ ``load_image``)."""
175
176
def __init__(self, config: DeepseekV41Config) -> None:
177
super().__init__()
vllm/models/deepseek_v41/nvidia/flashinfer_sparse.py
+1
-2
@@ -54,8 +54,7 @@ def _get_flashinfer_dsv4_workspace(device: torch.device) -> torch.Tensor:
54
def _packed_block_span(pool: torch.Tensor) -> int:
55
"""Per-block stride of ``pool`` in tokens (``stride(0)//stride(-2)``): ==
56
block_size for unpacked KV, larger when packed (#44577). Raises if not
57
- token-aligned.
58
- """
57
+ token-aligned."""
58
block_stride = pool.stride(0)
59
token_stride = pool.stride(-2)
60
if block_stride % token_stride != 0:
vllm/models/deepseek_v41/nvidia/model.py
+2
-4
@@ -1179,8 +1179,7 @@ class DeepseekV41LLMForCausalLM(
1179
@property
1180
def token_lookback_depth(self) -> int:
1181
"""Tokens before a chunk start the engram hash needs; the model runner
1182
- passes them as `lookback_token_ids`.
1183
- """
1182
+ passes them as `lookback_token_ids`."""
1183
engram_hash = self.model.engram_hash
1184
return engram_hash.lookback_depth if engram_hash is not None else 0
1185
@@ -1204,8 +1203,7 @@ class DeepseekV41LLMForCausalLM(
1203
def get_mtp_target_hidden_states(self) -> torch.Tensor | None:
1204
"""Pre-collapse residual stream buffer (max_num_batched_tokens,
1205
hc_mult * hidden_size) for the MTP draft model. Populated by
1207
- forward(); valid after each target step.
1208
- """
1206
+ forward(); valid after each target step."""
1207
return getattr(self.model, "_mtp_hidden_buffer", None)
1208
1209
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
vllm/models/deepseek_v41/nvidia/vl_model.py
+1
-2
@@ -209,8 +209,7 @@ class DeepseekV41ForCausalLM(nn.Module, SupportsMultiModal, SupportsPP, Supports
209
self, image_embeds: torch.Tensor, types: torch.Tensor
210
) -> torch.Tensor:
211
"""Full image span: aligner rows at IMAGE slots, the learned
212
- delimiter vectors at IMAGE_START/IMAGE_NEW_LINE/IMAGE_END.
213
- """
212
+ delimiter vectors at IMAGE_START/IMAGE_NEW_LINE/IMAGE_END."""
213
types = types.to(image_embeds.device)
214
span = image_embeds.new_empty(types.numel(), image_embeds.shape[-1])
215
dtype = image_embeds.dtype
vllm/models/glm5next/amd/ops/kpool_compress.py
+1
-2
@@ -98,8 +98,7 @@ def _kpool_softmax_rotate_write_cache_kernel(
98
BLOCK_D: tl.constexpr,
99
):
100
"""One program per pool. softmax(slot_score+ape)-weighted sum of slot_k ->
101
- Hadamard-128 -> per-vector fp8 absmax quant -> write to cache at ``loc``.
102
- """
101
+ Hadamard-128 -> per-vector fp8 absmax quant -> write to cache at ``loc``."""
102
row = tl.program_id(0)
103
do_write = True
104
if HAS_WRITE_MASK:
vllm/models/glm5next/common/kda.py
+2
-4
@@ -130,8 +130,7 @@ def _resolve_kda_prefill_backend(
130
"""Pick the chunked-prefill kernel: FlashKDA (fused CUDA, ~2-4x faster on
131
SM90/SM10x/SM12x for bf16, head_dim 128 and a bounded gate) or the Triton
132
``chunk_kda_with_fused_gate`` path. ``backend`` comes from
133
- ``additional_config.kda_prefill_backend`` (auto / triton / flashkda).
134
- """
133
+ ``additional_config.kda_prefill_backend`` (auto / triton / flashkda)."""
134
if backend not in ("auto", "triton", "flashkda"):
135
raise ValueError(f"Unsupported KDA prefill backend: {backend}")
136
capability = current_platform.get_device_capability()
@@ -369,8 +368,7 @@ class Glm5NextLinearAttention(GatedDeltaNetAttention):
368
bounded gate ``lower_bound * sigmoid(exp(A_log) * (g + dt_bias))``,
369
matching ``chunk_kda_with_fused_gate(..., safe_gate=True)``. Writes the
370
attention output into ``out`` (a workspace buffer when ``None``) and
372
- returns ``(out, final_state)``.
373
- """
371
+ returns ``(out, final_state)``."""
372
assert self._flashkda_buffer_specs is not None
373
final_state, workspace, workspace_out = (
374
current_workspace_manager().get_simultaneous(*self._flashkda_buffer_specs)
vllm/models/glm5next/common/multimodal.py
+1
-2
@@ -720,8 +720,7 @@ class Glm5NextMultiModalProcessor(Glm4vMultiModalProcessor):
720
(image token repeat, video frame/timestamp structure) is owned by vLLM's
721
prompt-update machinery — the inherited ``_get_prompt_updates`` builds
722
the replacement content and the placeholder scan validates against
723
- exactly that.
724
- """
723
+ exactly that."""
724
725
def _hf_processor_applies_updates(
726
self,
vllm/models/glm5next/common/sparse_indexer.py
+2
-4
@@ -138,8 +138,7 @@ def _gather_workspace_shapes(
138
"""Return ((values_shape, values_dtype), (scales_shape, scales_dtype)) for
139
the K-gather workspace. FP8 path: (T, head_dim) fp8 + (T, 4) uint8 fp32
140
scales. MXFP4 path: (T, head_dim // 2) uint8 packed mxfp4 +
141
- (T, head_dim // MXFP4_BLOCK_SIZE) uint8 ue8m0 scales.
142
- """
141
+ (T, head_dim // MXFP4_BLOCK_SIZE) uint8 ue8m0 scales."""
142
if use_fp4_cache:
143
return (
144
((total_seq_lens, head_dim // 2), torch.uint8),
@@ -157,8 +156,7 @@ def kv_cache_as_quant_view(
156
use_fp4_cache: bool,
157
) -> torch.Tensor:
158
"""4D ``[num_blocks, block_size, 1, head_width]`` view expected by
160
- DeepGEMM, from the 3D indexer kv-cache allocation.
161
- """
159
+ DeepGEMM, from the 3D indexer kv-cache allocation."""
160
if use_fp4_cache:
161
assert kv_cache.ndim == 3 and kv_cache.dtype == torch.uint8
162
num_blocks, block_size, _ = kv_cache.shape
vllm/models/glm5next/nvidia/ops/fused_eh_norm.py
+1
-2
@@ -31,8 +31,7 @@ def _fused_eh_norm_kernel(
31
):
32
"""MTP input fusion: zero embeds at position 0, RMSNorm(embeds) with enorm
33
and RMSNorm(prev_hidden) with hnorm, written side-by-side into ``out``
34
- ([N, 2H]) ready for the eh_proj GEMM. Replaces where + 2x RMSNorm + cat.
35
- """
34
+ ([N, 2H]) ready for the eh_proj GEMM. Replaces where + 2x RMSNorm + cat."""
35
tok = tl.program_id(0)
36
off = tl.arange(0, BLOCK)
37
mask = off < H
vllm/models/glm5next/nvidia/ops/kpool_compress.py
+1
-2
@@ -163,8 +163,7 @@ def _kpool_softmax_rotate_write_cache_kernel(
163
BLOCK_D: tl.constexpr,
164
):
165
"""One program per pool. softmax(slot_score+ape)-weighted sum of slot_k ->
166
- Hadamard-128 -> per-vector fp8 absmax quant -> write to cache at ``loc``.
167
- """
166
+ Hadamard-128 -> per-vector fp8 absmax quant -> write to cache at ``loc``."""
167
row = tl.program_id(0)
168
do_write = True
169
if HAS_WRITE_MASK:
vllm/models/inkling/amd/model.py
+1
-2
@@ -72,8 +72,7 @@ def _sconv_add_norm(
72
73
ROCm uses the portable collective path. The Lamport P2P implementation in
74
the NVIDIA model relies on CUDA GDC and CUDA-specific symmetric-memory
75
- publication semantics which cannot be linked into a gfx950 HSACO.
76
- """
75
+ publication semantics which cannot be linked into a gfx950 HSACO."""
76
norm_w = norm.weight if norm is not None else None
77
eps = norm.variance_epsilon if norm is not None else 0.0
78
vllm/models/inkling/amd/moe.py
+3
-6
@@ -192,8 +192,7 @@ def inkling_gate_select(
192
193
class InklingGate(nn.Module):
194
"""Sigmoid gate with selection bias, log-sigmoid renorm after top-k, and
195
- global scale (the served checkpoint's only configuration).
196
- """
195
+ global scale (the served checkpoint's only configuration)."""
196
197
def __init__(
198
self,
@@ -247,8 +246,7 @@ class InklingGate(nn.Module):
246
self, gating_output: torch.Tensor
247
) -> tuple[torch.Tensor, torch.Tensor]:
248
"""Full selection: (weights, ids) of [T, K + S]. The first K entries
250
- are the routed top-k; the S trailing entries are the sink gammas.
251
- """
249
+ are the routed top-k; the S trailing entries are the sink gammas."""
250
return inkling_gate_select(
251
gating_output,
252
self.n_total_experts,
@@ -269,8 +267,7 @@ class InklingGate(nn.Module):
267
def _inkling_moe_ep_size() -> int:
268
"""EP size the MoERunner layer will run with (mirrors
269
FusedMoEParallelConfig.make: experts shard over tp * dp * pcp when
272
- expert parallelism is enabled).
273
- """
270
+ expert parallelism is enabled)."""
271
parallel_config = get_current_vllm_config().parallel_config
272
if not parallel_config.enable_expert_parallel:
273
return 1
vllm/models/inkling/amd/mtp.py
+3
-6
@@ -166,8 +166,7 @@ class InklingMultiTokenPredictor(nn.Module):
166
) -> torch.Tensor:
167
"""Draft-prefill embedding: fused gather + backbone embed_norm, then
168
the target's tower embeddings scattered in unnormed (the backbone
169
- convention — MM embeds are merged after embed_norm).
170
- """
169
+ convention — MM embeds are merged after embed_norm)."""
170
norm = self.backbone_embed_norm
171
embeds = embed_rmsnorm(
172
input_ids,
@@ -196,8 +195,7 @@ class InklingMultiTokenPredictor(nn.Module):
195
"""The depth layer's [rmsnorm(hidden) | embed_norm(embed)] input in one
196
launch: embedding row gather + the backbone embed_norm + the depth
197
embed_norm chain on one side, hidden_norm on the other, written
199
- straight into the cat buffer.
200
- """
198
+ straight into the cat buffer."""
199
hidden_w = layer.hidden_norm.weight
200
embed_w = layer.embed_norm.weight
201
eps = layer.hidden_norm.variance_epsilon
@@ -329,8 +327,7 @@ class InklingMTP(nn.Module, SupportsMultiModalEmbeddings):
327
"""Greedy draft tokens via rank-local argmax + tiny (value, index)
328
reduction — no full-vocab logits all-gather. The muP divisor is a
329
positive scalar, so the argmax is invariant and the scaling is
332
- skipped entirely.
333
- """
330
+ skipped entirely."""
331
return self.logits_processor.get_top_tokens(self.lm_head, hidden_states)
332
333
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
vllm/models/inkling/amd/ops/norm.py
+2
-4
@@ -238,8 +238,7 @@ def embed_rmsnorm(
238
embedding-table gather.
239
``chain_weight`` additionally emits ``rmsnorm(out, chain_weight)`` (the
240
first decoder layer's pre-attention norm) as a second output, still one
241
- launch. Bit-exact vs the unfused module sequence.
242
- """
241
+ launch. Bit-exact vs the unfused module sequence."""
242
ids = input_ids.view(-1)
243
(T,) = ids.shape
244
n = embed_table.shape[1]
@@ -333,8 +332,7 @@ def embed_dual_rmsnorm_cat(
332
(draft decode steps) or precomputed ``embeds`` ([T, N], the target-merged
333
multimodal embeddings at draft prefill); ``pre_norm_weight`` chains the
334
backbone embed_norm in front of the depth embed_norm (bit-exact vs the
336
- unfused sequence). The concat copies collapse into direct writes.
337
- """
335
+ unfused sequence). The concat copies collapse into direct writes."""
336
T, n = hidden.shape
337
if embeds is not None:
338
assert embeds.shape == hidden.shape
vllm/models/inkling/nvidia/model.py
+1
-2
@@ -75,8 +75,7 @@ def _sconv_add_norm(
75
"""``h = hidden + sconv(TP-sum(delta)); y = rmsnorm(h)``.
76
77
The Lamport path performs reduce-scatter + shard sconv + all-gather +
78
- residual add + norm. The NCCL path handles unsupported configurations.
79
- """
78
+ residual add + norm. The NCCL path handles unsupported configurations."""
79
attn_metadata = get_forward_context().attn_metadata
80
m = (
81
attn_metadata.get(sconv.owner.prefix)
vllm/models/inkling/nvidia/moe.py
+3
-6
@@ -191,8 +191,7 @@ def inkling_gate_select(
191
192
class InklingGate(nn.Module):
193
"""Sigmoid gate with selection bias, log-sigmoid renorm after top-k, and
194
- global scale (the served checkpoint's only configuration).
195
- """
194
+ global scale (the served checkpoint's only configuration)."""
195
196
def __init__(
197
self,
@@ -244,8 +243,7 @@ class InklingGate(nn.Module):
243
self, gating_output: torch.Tensor
244
) -> tuple[torch.Tensor, torch.Tensor]:
245
"""Full selection: (weights, ids) of [T, K + S]. The first K entries
247
- are the routed top-k; the S trailing entries are the sink gammas.
248
- """
246
+ are the routed top-k; the S trailing entries are the sink gammas."""
247
return inkling_gate_select(
248
gating_output,
249
self.n_total_experts,
@@ -266,8 +264,7 @@ class InklingGate(nn.Module):
264
def _inkling_moe_ep_size() -> int:
265
"""EP size the FusedMoE layer will run with (mirrors
266
FusedMoEParallelConfig.make: experts shard over tp * dp * pcp when
269
- expert parallelism is enabled).
270
- """
267
+ expert parallelism is enabled)."""
268
parallel_config = get_current_vllm_config().parallel_config
269
if not parallel_config.enable_expert_parallel:
270
return 1
vllm/models/inkling/nvidia/mtp.py
+3
-6
@@ -166,8 +166,7 @@ class InklingMultiTokenPredictor(nn.Module):
166
) -> torch.Tensor:
167
"""Draft-prefill embedding: fused gather + backbone embed_norm, then
168
the target's tower embeddings scattered in unnormed (the backbone
169
- convention — MM embeds are merged after embed_norm).
170
- """
169
+ convention — MM embeds are merged after embed_norm)."""
170
norm = self.backbone_embed_norm
171
embeds = embed_rmsnorm(
172
input_ids,
@@ -196,8 +195,7 @@ class InklingMultiTokenPredictor(nn.Module):
195
"""The depth layer's [rmsnorm(hidden) | embed_norm(embed)] input in one
196
launch: embedding row gather + the backbone embed_norm + the depth
197
embed_norm chain on one side, hidden_norm on the other, written
199
- straight into the cat buffer.
200
- """
198
+ straight into the cat buffer."""
199
hidden_w = layer.hidden_norm.weight
200
embed_w = layer.embed_norm.weight
201
eps = layer.hidden_norm.variance_epsilon
@@ -329,8 +327,7 @@ class InklingMTP(nn.Module, SupportsMultiModalEmbeddings):
327
"""Greedy draft tokens via rank-local argmax + tiny (value, index)
328
reduction — no full-vocab logits all-gather. The muP divisor is a
329
positive scalar, so the argmax is invariant and the scaling is
332
- skipped entirely.
333
- """
330
+ skipped entirely."""
331
return self.logits_processor.get_top_tokens(self.lm_head, hidden_states)
332
333
def load_weights(self, weights: Iterable[tuple[str, torch.Tensor]]) -> set[str]:
vllm/models/inkling/nvidia/ops/mm_towers.py
+2
-4
@@ -60,8 +60,7 @@ def dmel_embed_sum_norm(
60
eps: float,
61
) -> torch.Tensor:
62
"""``rmsnorm(sum_b weight[b * VOCAB + idx[:, b]])`` in one launch (no
63
- [T, NB, D] intermediate).
64
- """
63
+ [T, NB, D] intermediate)."""
64
T, nb = dmel_idx.shape
65
D = weight.shape[1]
66
assert weight.shape[0] % nb == 0
@@ -152,8 +151,7 @@ def rmsnorm_gelu(
151
) -> torch.Tensor:
152
"""Fused ``gelu(rmsnorm(x))`` (or plain rmsnorm); multiple rows per block
153
when D is small. With ``fold``, x must be [N, T, H, W, D] and the output
155
- comes back as ``fold_timespace_to_depth(result, *fold)``.
156
- """
154
+ comes back as ``fold_timespace_to_depth(result, *fold)``."""
155
D = x.shape[-1]
156
flat = x.reshape(-1, D)
157
assert flat.stride(1) == 1 and flat.stride(0) == D
vllm/models/inkling/nvidia/ops/norm.py
+2
-4
@@ -238,8 +238,7 @@ def embed_rmsnorm(
238
embedding-table gather.
239
``chain_weight`` additionally emits ``rmsnorm(out, chain_weight)`` (the
240
first decoder layer's pre-attention norm) as a second output, still one
241
- launch. Bit-exact vs the unfused module sequence.
242
- """
241
+ launch. Bit-exact vs the unfused module sequence."""
242
ids = input_ids.view(-1)
243
(T,) = ids.shape
244
n = embed_table.shape[1]
@@ -333,8 +332,7 @@ def embed_dual_rmsnorm_cat(
332
(draft decode steps) or precomputed ``embeds`` ([T, N], the target-merged
333
multimodal embeddings at draft prefill); ``pre_norm_weight`` chains the
334
backbone embed_norm in front of the depth embed_norm (bit-exact vs the
336
- unfused sequence). The concat copies collapse into direct writes.
337
- """
335
+ unfused sequence). The concat copies collapse into direct writes."""
336
T, n = hidden.shape
337
if embeds is not None:
338
assert embeds.shape == hidden.shape
vllm/models/kimi_k3/nvidia/mla.py
+1
-2
@@ -745,8 +745,7 @@ class MultiHeadLatentAttention(nn.Module, AttentionLayerBase):
745
slot_mapping: torch.Tensor,
746
) -> torch.Tensor:
747
"""Fused decode query-concat + latent cache insert, dispatched by cache
748
- dtype (same policy as prefill: fp8 cache -> fp8 query).
749
- """
748
+ dtype (same policy as prefill: fp8 cache -> fp8 query)."""
749
if self.kv_cache_dtype == "fp8_ds_mla":
750
cache = self.kv_cache
751
if cache.dtype != torch.uint8:
vllm/models/minimax_m3/amd/model.py
+1
-2
@@ -334,8 +334,7 @@ def _aiter_moe_fused_shared_experts_enabled(
334
335
class MiniMaxM3MoE(nn.Module):
336
"""Sigmoid-routed MoE block with a routing-bias correction and a shared
337
- expert.
338
- """
337
+ expert."""
338
339
def __init__(
340
self,
vllm/models/minimax_m3/common/indexer.py
+2
-4
@@ -173,8 +173,7 @@ class MiniMaxM3IndexerPrefillMetadata:
173
@dataclass
174
class MiniMaxM3IndexerDecodeMetadata:
175
"""Per-decode state (cudagraph-safe). ``decode_query_len`` is the uniform
176
- per-request query length (1, or 1 + num_speculative_tokens).
177
- """
176
+ per-request query length (1, or 1 + num_speculative_tokens)."""
177
178
seq_lens: torch.Tensor # [num_decodes] int32
179
block_table: torch.Tensor
@@ -207,8 +206,7 @@ class MiniMaxM3IndexerMetadataBuilder(
206
AttentionMetadataBuilder[MiniMaxM3IndexerMetadata]
207
):
208
"""Abstract base: shared setup only. The Triton and MSA builders are
210
- parallel subclasses that each own their full ``build`` (no shared code).
211
- """
209
+ parallel subclasses that each own their full ``build`` (no shared code)."""
210
211
# Full cudagraphs for uniform decode batches (incl. spec-decode verify).
212
_cudagraph_support: ClassVar[AttentionCGSupport] = AttentionCGSupport.UNIFORM_BATCH
vllm/models/minimax_m3/common/sparse_attention.py
+1
-2
@@ -203,8 +203,7 @@ class MiniMaxM3SparsePrefillMetadata:
203
@dataclass
204
class MiniMaxM3SparseDecodeMetadata:
205
"""Per-decode state (cudagraph-safe). ``decode_query_len`` is the uniform
206
- per-request query length (1, or 1 + num_speculative_tokens).
207
- """
206
+ per-request query length (1, or 1 + num_speculative_tokens)."""
207
208
seq_lens: torch.Tensor # [num_decodes] int32
209
block_table: torch.Tensor
vllm/models/minimax_m3/nvidia/indexer_msa.py
+2
-4
@@ -85,8 +85,7 @@ class MiniMaxM3IndexerMSAPrefillMetadata:
85
class MiniMaxM3IndexerMSAMetadata(MiniMaxM3IndexerMetadata):
86
"""Decode reuses the inherited base ``decode`` field (the Triton decode
87
metadata); ``prefill_msa`` carries the fmha score plan for the prefill side
88
- (the base ``prefill`` field is unused on this path).
89
- """
88
+ (the base ``prefill`` field is unused on this path)."""
89
90
prefill_msa: MiniMaxM3IndexerMSAPrefillMetadata | None = None
91
# Per-forward view (``[:num_tokens]``) of the builder's persistent unified
@@ -112,8 +111,7 @@ class MiniMaxM3IndexerMSAMetadata(MiniMaxM3IndexerMetadata):
111
112
class MiniMaxM3IndexerMSAMetadataBuilder(MiniMaxM3IndexerMetadataBuilder):
113
"""Decode metadata is the cudagraph-safe Triton decode metadata; the prefill
115
- fmha plan is built eagerly (prefill batches are not captured).
116
- """
114
+ fmha plan is built eagerly (prefill batches are not captured)."""
115
116
_cudagraph_support: ClassVar[AttentionCGSupport] = AttentionCGSupport.UNIFORM_BATCH
117
vllm/models/minimax_m3/nvidia/model.py
+2
-4
@@ -190,8 +190,7 @@ class MiniMaxM3MLP(nn.Module):
190
191
class MiniMaxM3MoE(nn.Module):
192
"""Sigmoid-routed MoE block with a routing-bias correction and a shared
193
- expert.
194
- """
193
+ expert."""
194
195
def __init__(
196
self,
@@ -783,8 +782,7 @@ class MiniMaxM3DecoderLayer(nn.Module):
782
@property
783
def ffn_all_reduce_deferred(self) -> bool:
784
"""This layer's FFN output is left un-reduced; the caller fuses the
786
- all-reduce into the next RMSNorm.
787
- """
785
+ all-reduce into the next RMSNorm."""
786
if self.is_moe_layer:
787
return self.block_sparse_moe.experts.moe_config.skip_final_all_reduce
788
return not self.mlp.down_proj.reduce_results
vllm/multimodal/cache.py
+2
-4
@@ -606,8 +606,7 @@ class ShmObjectStoreSenderCache(BaseMultiModalProcessorCache):
606
@override
607
def touch_sender_cache_item(self, mm_hash: str) -> None:
608
"""Touch the item in shared memory cache to prevent eviction.
609
- Increments writer_flag on sender side.
610
- """
609
+ Increments writer_flag on sender side."""
610
self._shm_cache.touch(mm_hash)
611
612
@override
@@ -822,8 +821,7 @@ class ShmObjectStoreReceiverCache(BaseMultiModalReceiverCache):
821
mm_item: MultiModalKwargsItem | None = None,
822
) -> None:
823
"""Touch the item in shared memory cache to prevent eviction.
825
- Increments reader_count on receiver side.
826
- """
824
+ Increments reader_count on receiver side."""
825
assert mm_item is not None
826
if "address" in mm_item:
827
address = cast(int, mm_item["address"].data)
vllm/multimodal/image.py
+1
-2
@@ -38,8 +38,7 @@ def rgba_to_rgb(
38
39
def _has_transparency(image: Image.Image) -> bool:
40
"""Detect whether an image carries transparency data (RGBA, LA, PA,
41
- or tRNS chunk in P/L/RGB PNGs).
42
- """
41
+ or tRNS chunk in P/L/RGB PNGs)."""
42
if image.mode in ("RGBA", "LA", "PA"):
43
return True
44
return "transparency" in getattr(image, "info", {})
vllm/multimodal/inputs.py
+1
-2
@@ -295,8 +295,7 @@ def _is_dense(t: torch.Tensor) -> bool:
295
"""Whether `t`'s elements fill a contiguous storage range, possibly
296
permuted (e.g. a transposed matrix). Such layouts can be copied with
297
pitched cudaMemcpy2D/3DAsync directly from pinned memory, whereas
298
- gapped layouts (e.g. strided slices) stage through a pageable temp.
299
- """
298
+ gapped layouts (e.g. strided slices) stage through a pageable temp."""
299
if not t.is_contiguous():
300
expected_stride = 1
301
for stride, size in sorted(zip(t.stride(), t.shape)):
vllm/multimodal/utils.py
+1
-2
@@ -220,8 +220,7 @@ def strip_covered_mm_data(
220
so the workers never consume the payload fields. M-RoPE models keep
221
CPU-side metadata fields used to compute positions. SHM address items
222
are also kept so workers can balance the sender's reference count. The
223
- scheduler-side ``Request`` keeps the full features.
224
- """
223
+ scheduler-side ``Request`` keeps the full features."""
224
if not mm_features or num_computed_tokens == 0:
225
return mm_features
226
vllm/parser/engine/incremental_lexer.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Incremental text lexer that converts text chunks into terminal
4
-tokens, with prefix-match buffering for ambiguous boundaries.
5
-"""
4
+tokens, with prefix-match buffering for ambiguous boundaries."""
5
6
from __future__ import annotations
7
vllm/parser/engine/streaming_parser_engine.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Streaming parser engine that orchestrates token ID scanning,
4
-incremental lexing, and state-machine-driven semantic event emission.
5
-"""
4
+incremental lexing, and state-machine-driven semantic event emission."""
5
6
from __future__ import annotations
7
vllm/parser/engine/token_id_scanner.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Scan delta token IDs for special tokens and split the stream into
4
-pre-lexed terminals and plain text chunks.
5
-"""
4
+pre-lexed terminals and plain text chunks."""
5
6
from __future__ import annotations
7
vllm/parser/inkling.py
+1
-2
@@ -67,8 +67,7 @@ _WS = " \t\r\n"
67
68
def _scan_json_value(raw: str, start: int) -> int | None:
69
"""Return the end index (exclusive) of the JSON object starting at
70
- ``raw[start]``, or ``None`` when the object is still unterminated.
71
- """
70
+ ``raw[start]``, or ``None`` when the object is still unterminated."""
71
depth = 0
72
in_string = False
73
escape = False
vllm/platforms/cuda.py
+1
-2
@@ -62,8 +62,7 @@ def _cuda_device_count_stateless(cuda_visible_devices: str | None = None) -> int
62
CUDA_VISIBLE_DEVICES has already been set to the desired value.
63
64
# This can be removed and simply replaced with torch.cuda.get_device_count
65
- # after https://github.com/pytorch/pytorch/pull/122815 is released.
66
- """
65
+ # after https://github.com/pytorch/pytorch/pull/122815 is released."""
66
# Note: cuda_visible_devices is not used, but we keep it as an argument for
67
# LRU Cache purposes.
68
vllm/platforms/interface.py
+1
-2
@@ -42,8 +42,7 @@ def set_assigned_physical_gpu_ids(ids: list[int]) -> None:
42
Idempotent: a second call with the same value is a no-op.
43
Raises RuntimeError if called again with a different value.
44
45
- This is expected to run during single-threaded worker initialization.
46
- """
45
+ This is expected to run during single-threaded worker initialization."""
46
global _assigned_physical_gpu_ids
47
if _assigned_physical_gpu_ids is not None:
48
if _assigned_physical_gpu_ids != ids:
vllm/platforms/rocm.py
+2
-4
@@ -91,8 +91,7 @@ def _rocm_device_count_stateless(cuda_visible_devices: str | None = None) -> int
91
CUDA_VISIBLE_DEVICES has already been set to the desired value.
92
93
# This can be removed and simply replaced with torch.cuda.get_device_count
94
- # after https://github.com/pytorch/pytorch/pull/122815 is released.
95
- """
94
+ # after https://github.com/pytorch/pytorch/pull/122815 is released."""
95
# Note: cuda_visible_devices is not used, but we keep it as an argument for
96
# LRU Cache purposes.
97
@@ -127,8 +126,7 @@ def _get_wsl_kernel_version() -> tuple[int, ...] | None:
126
127
def _sync_hip_cuda_env_vars():
128
"""Ensure HIP_VISIBLE_DEVICES and CUDA_VISIBLE_DEVICES are consistent.
130
- Treats empty string as unset. Raises on genuine conflicts.
131
- """
129
+ Treats empty string as unset. Raises on genuine conflicts."""
130
hip_val = os.environ.get("HIP_VISIBLE_DEVICES") or None
131
cuda_val = os.environ.get("CUDA_VISIBLE_DEVICES") or None
132
vllm/profiler/wrapper.py
+1
-2
@@ -98,8 +98,7 @@ class WorkerProfiler(ABC):
98
99
def step(self) -> None:
100
"""Update the profiler state at each worker step,
101
- to handle delayed starts and max iteration limits.
102
- """
101
+ to handle delayed starts and max iteration limits."""
102
if not self._active:
103
return
104
vllm/renderers/base.py
+1
-2
@@ -377,8 +377,7 @@ class BaseRenderer(ABC, Generic[_T]):
377
378
async def clear_mm_cache_async(self) -> None:
379
"""Serialize clear_mm_cache through the multimodal executor to avoid
380
- races with concurrent process_inputs on the mm_processor_cache.
381
- """
380
+ races with concurrent process_inputs on the mm_processor_cache."""
381
await self._clear_mm_cache_async()
382
383
def shutdown(self) -> None:
vllm/renderers/hf.py
+2
-4
@@ -103,8 +103,7 @@ _TOKENIZE_OVERRIDE_WARNING: Final[str] = (
103
104
def _ensure_prompt_embeds_placeholder_token(tokenizer: HfTokenizer) -> int:
105
"""Register `PROMPT_EMBEDS_PLACEHOLDER_TOKEN` as a special token and return
106
- its token ID.
107
- """
106
+ its token ID."""
107
cached = _PROMPT_EMBEDS_PLACEHOLDER_TOKEN_ID_CACHE.get(tokenizer)
108
if cached is not None:
109
return cached
@@ -193,8 +192,7 @@ def _build_mixed_prompt_embeds(
192
positions: list[tuple[int, int]],
193
) -> tuple[torch.Tensor, list[bool]]:
194
"""Build the full-length `prompt_embeds` tensor and the `is_token_ids`
196
- mask aligned to `token_ids`.
197
- """
195
+ mask aligned to `token_ids`."""
196
total_len = len(token_ids)
197
hidden_size = prompt_embeds_tensors[0].shape[1]
198
dtype = prompt_embeds_tensors[0].dtype
vllm/renderers/online_derenderer.py
+1
-2
@@ -616,8 +616,7 @@ def _convert_chat_logprobs_to_completion_logprobs(
616
logprobs: ChatCompletionLogProbs,
617
) -> CompletionLogProbs:
618
"""Convert ChatCompletionLogProbs (per-token objects) to CompletionLogProbs
619
- (parallel flat lists) as required by the /v1/completions response schema.
620
- """
619
+ (parallel flat lists) as required by the /v1/completions response schema."""
620
if logprobs.content is None:
621
return CompletionLogProbs()
622
vllm/sampling_params.py
+1
-2
@@ -800,8 +800,7 @@ class SamplingParams(
800
"""Number of sample logprobs to return per output token, or `None` if
801
no sample logprobs were requested. Takes `logprob_token_ids` into
802
account: when `logprobs` is unset but `logprob_token_ids` is set,
803
- returns `len(logprob_token_ids)`.
804
- """
803
+ returns `len(logprob_token_ids)`."""
804
if self.logprobs is not None:
805
return self.logprobs
806
return len(self.logprob_token_ids) if self.logprob_token_ids else None
vllm/tool_parsers/hermes_tool_parser.py
+1
-2
@@ -219,8 +219,7 @@ class Hermes2ProToolParser(ToolParser):
219
220
Returns a ``DeltaMessage`` containing either plain content (for
221
text preceding any tool call) or one or more ``DeltaToolCall``
222
- entries, or ``None`` if there is nothing new to send yet.
223
- """
222
+ entries, or ``None`` if there is nothing new to send yet."""
223
try:
224
# Extract any content before tool calls.
225
content = self._extract_content(current_text)
vllm/tool_parsers/lfm2_tool_parser.py
+1
-2
@@ -114,8 +114,7 @@ class Lfm2ToolParser(ToolParser):
114
"""Drop any orphan <|tool_call_end|> (and the preceding text) from
115
trailing content. LFM2 occasionally echoes the call body after the
116
first end token and caps it with a second end token; everything
117
- through the last such orphan is model garbage, not user content.
118
- """
117
+ through the last such orphan is model garbage, not user content."""
118
last_orphan = raw_after.rfind(TOOL_CALL_END)
119
if last_orphan != -1:
120
return raw_after[last_orphan + len(TOOL_CALL_END) :]
vllm/tool_parsers/utils.py
+1
-2
@@ -426,8 +426,7 @@ def get_json_schema_from_tools(
426
427
class UnexpectedAstError(Exception):
428
"""Raised when the AST structure does not match the expected
429
- pythonic tool call format.
430
- """
429
+ pythonic tool call format."""
430
431
pass
432
vllm/transformers_utils/config.py
+2
-4
@@ -539,8 +539,7 @@ def register_config_parser(config_format: str):
539
540
def set_default_rope_theta(config: PretrainedConfig, default_theta: float) -> None:
541
"""Some models may have no rope_theta in their config but still use RoPE.
542
- This function sets a default rope_theta if it's missing.
543
- """
542
+ This function sets a default rope_theta if it's missing."""
543
if getattr(config, "rope_parameters", None) is None:
544
config.rope_parameters = {"rope_type": "default"}
545
if "rope_theta" not in config.rope_parameters:
@@ -549,8 +548,7 @@ def set_default_rope_theta(config: PretrainedConfig, default_theta: float) -> No
548
549
def patch_legacy_rope_type(rope_parameters: dict[str, Any] | None) -> None:
550
"""Patch legacy RoPE type fields for backwards compatibility with
552
- older custom models which would otherwise fail to load.
553
- """
551
+ older custom models which would otherwise fail to load."""
552
# No RoPE parameters to patch
553
if rope_parameters is None:
554
return
vllm/transformers_utils/configs/extract_hidden_states.py
+1
-2
@@ -1,8 +1,7 @@
1
# SPDX-License-Identifier: Apache-2.0
2
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
3
"""Config definitions for ExtractHiddenStatesModel, to be used with
4
-the extract_hidden_states spec decoding method.
5
-"""
4
+the extract_hidden_states spec decoding method."""
5
6
import os
7
vllm/transformers_utils/processor.py
+3
-6
@@ -37,8 +37,7 @@ def _transformers_v4_compatibility_import():
37
subset of `ProcessorChatTemplateKwargs` as defined in Transformers v4.
38
In Transformers v5 these were merged into `ProcessorChatTemplateKwargs` and
39
`ChatTemplateLoadKwargs` was removed. For backward compatibility, we add an alias
40
- for `ChatTemplateLoadKwargs` if it doesn't exist.
41
- """
40
+ for `ChatTemplateLoadKwargs` if it doesn't exist."""
41
old_import = getattr(processing_utils, "ChatTemplateLoadKwargs", None)
42
new_import = getattr(processing_utils, "ProcessorChatTemplateKwargs", None)
43
if old_import is None and new_import is not None:
@@ -53,8 +52,7 @@ def _transformers_v4_compatibility_init() -> Any:
52
processor instance before calling the original `ProcessorMixin.__init__`.
53
54
This can be removed if `Molmo2ForConditionalGeneration` is upstreamed to
56
- Transformers.
57
- """
55
+ Transformers."""
56
if hasattr(ProcessorMixin.__init__, "_vllm_patched"):
57
return
58
@@ -397,8 +395,7 @@ def get_feature_extractor(
395
**kwargs: Any,
396
):
397
"""Load an audio feature extractor for the given model name
400
- via HuggingFace.
401
- """
398
+ via HuggingFace."""
399
try:
400
processor_name = convert_model_repo_to_path(processor_name)
401
feature_extractor = AutoFeatureExtractor.from_pretrained(
vllm/transformers_utils/processors/cohere_asr.py
+1
-2
@@ -537,8 +537,7 @@ class CohereASRFeatureExtractor(SequenceFeatureExtractor):
537
538
class CohereASRProcessor(ProcessorMixin):
539
"""HF-compatible processor combining CohereASRFeatureExtractor and a
540
- tokenizer.
541
- """
540
+ tokenizer."""
541
542
feature_extractor_class = "CohereASRFeatureExtractor"
543
tokenizer_class = "AutoTokenizer"
vllm/transformers_utils/processors/glm5next.py
+2
-4
@@ -261,8 +261,7 @@ def _resize_or_pad(
261
allow_upscale: bool = False,
262
) -> torch.Tensor:
263
"""Resize onto the aligned canvas, or keep the aspect ratio and
264
- zero-pad the right/bottom sides (``resize_mode="pad"``).
265
- """
264
+ zero-pad the right/bottom sides (``resize_mode="pad"``)."""
265
height, width = stacked_images.shape[-2:]
266
267
if resize_mode == "resize":
@@ -308,8 +307,7 @@ def _pixel_budget(
307
) -> tuple[int, int]:
308
"""(min_pixels, max_pixels) from the token bounds of
309
``processor_config.json``; one vision token covers
311
- ``temporal_patch_size * (patch_size * merge_size) ** 2`` pixels.
312
- """
310
+ ``temporal_patch_size * (patch_size * merge_size) ** 2`` pixels."""
311
if min_image_tokens is None or max_image_tokens is None:
312
raise ValueError(
313
"min_image_tokens and max_image_tokens must be provided by "
vllm/transformers_utils/utils.py
+1
-2
@@ -116,8 +116,7 @@ def parse_safetensors_file_metadata(path: str | PathLike) -> dict[str, Any]:
116
117
def convert_model_repo_to_path(model_repo: str) -> str:
118
"""When VLLM_USE_MODELSCOPE is True convert a model
119
- repository string to a Path str.
120
- """
119
+ repository string to a Path str."""
120
if not envs.VLLM_USE_MODELSCOPE or Path(model_repo).exists():
121
return model_repo
122
from modelscope.utils.file_utils import get_model_cache_root
vllm/utils/cpu_resource_utils.py
+1
-2
@@ -274,8 +274,7 @@ def get_visible_memory_node() -> list[int]:
274
def _synthesize_cpu_list() -> list[LogicalCPUInfo]:
275
"""Synthesize a flat CPU list: each logical CPU is its own core on
276
NUMA node 0. Used when lscpu output is unavailable or unparsable
277
- (e.g. macOS, RISC-V).
278
- """
277
+ (e.g. macOS, RISC-V)."""
278
cpu_count = os.cpu_count()
279
assert cpu_count
280
return [LogicalCPUInfo(i, i, 0) for i in range(cpu_count)]
vllm/utils/deep_gemm.py
+1
-2
@@ -704,8 +704,7 @@ def fp8_fp4_paged_mqa_logits(
704
705
def has_deep_gemm_sparse_mqa() -> bool:
706
"""Whether the installed DeepGEMM provides the sparse-indexer kernels
707
- (``fp8_fp4_(paged_)sparse_mqa_logits``, added in DeepGEMM 2.8, SM100-only).
708
- """
707
+ (``fp8_fp4_(paged_)sparse_mqa_logits``, added in DeepGEMM 2.8, SM100-only)."""
708
_lazy_init()
709
return (
710
_fp8_fp4_sparse_mqa_logits_impl is not None
vllm/utils/gpu_sync_debug.py
+2
-4
@@ -72,8 +72,7 @@ _sync_filter_head: tuple | None = None
72
73
def _sync_warning_hook(message, category, filename, lineno, file=None, line=None):
74
"""Turn torch's sync warning into an error, but only on a thread that is
75
- being checked and is outside any allow region.
76
- """
75
+ being checked and is outside any allow region."""
76
if _TORCH_SYNC_WARNING in str(message):
77
mode = _checking.get()
78
if mode is None or _allow_depth.get():
@@ -252,8 +251,7 @@ def _is_dense(t: torch.Tensor) -> bool:
251
"""Whether `t`'s elements fill a contiguous storage range, possibly
252
permuted (e.g. a transposed matrix). Such layouts can be copied with
253
pitched cudaMemcpy2D/3DAsync directly from/to pinned memory, whereas
255
- gapped layouts (e.g. strided slices) stage through a pageable temp.
256
- """
254
+ gapped layouts (e.g. strided slices) stage through a pageable temp."""
255
if t.is_contiguous():
256
# The common case, answered by a memoized TensorImpl flag.
257
return True
vllm/utils/platform_utils.py
+1
-2
@@ -29,8 +29,7 @@ def cuda_get_device_properties(
29
device, names: Sequence[str], init_cuda=False
30
) -> tuple[Any, ...]:
31
"""Get specified CUDA device property values without initializing CUDA in
32
- the current process.
33
- """
32
+ the current process."""
33
if init_cuda or cuda_is_initialized():
34
props = torch.cuda.get_device_properties(device)
35
return tuple(getattr(props, name) for name in names)
vllm/utils/torch_utils.py
+1
-2
@@ -230,8 +230,7 @@ def _cgroup_cpu_limit() -> float | None:
230
231
def available_cpu_count() -> int:
232
"""CPUs actually usable by this process: scheduling affinity capped by
233
- the cgroup CPU quota (unlike `os.cpu_count()`, which is quota-blind).
234
- """
233
+ the cgroup CPU quota (unlike `os.cpu_count()`, which is quota-blind)."""
234
if sys.platform != "linux":
235
return os.cpu_count() or 1
236
count = len(os.sched_getaffinity(0))
vllm/v1/attention/backend.py
+2
-4
@@ -365,8 +365,7 @@ class AttentionBackend(ABC):
365
@classmethod
366
def supported_kv_cache_layouts(cls) -> tuple[KVCacheLayout, ...] | None:
367
"""Layouts this backend's kernels can consume, most preferred first, or
368
- None when the kernels consume any layout and express no preference.
369
- """
368
+ None when the kernels consume any layout and express no preference."""
369
return None
370
371
@classmethod
@@ -558,8 +557,7 @@ M = TypeVar("M")
557
class AttentionCGSupport(Enum):
558
"""Constants for the cudagraph support of the attention backend
559
Here we do not consider the cascade attention, as currently
561
- it is never cudagraph supported.
562
- """
560
+ it is never cudagraph supported."""
561
562
ALWAYS = 3
563
"""Cudagraph always supported; supports mixed-prefill-decode"""
vllm/v1/attention/backends/cpu_attn.py
+1
-2
@@ -84,8 +84,7 @@ class CPUAttentionBackend(AttentionBackend):
84
@classmethod
85
def supports_attn_type(cls, attn_type: str) -> bool:
86
"""CPU attention supports decoder,
87
- encoder-only and encoder-decoder attention.
88
- """
87
+ encoder-only and encoder-decoder attention."""
88
return attn_type in (
89
AttentionType.DECODER,
90
AttentionType.ENCODER,
vllm/v1/attention/backends/flashinfer.py
+1
-2
@@ -398,8 +398,7 @@ class FlashInferBackend(AttentionBackend):
398
@classmethod
399
def customize_spec(cls, spec: "AttentionSpec") -> "AttentionSpec":
400
"""NVFP4 stores K and V as separate per-head slots of packed fp4 data
401
- plus fp8 block scales.
402
- """
401
+ plus fp8 block scales."""
402
if spec.state_content_bytes is not None or not spec.kv_quant_mode.is_nvfp4:
403
return spec
404
hs_k = nvfp4_kv_cache_full_dim(spec.head_size)
vllm/v1/attention/backends/mla/amx_mla.py
+1
-2
@@ -63,8 +63,7 @@ _SPLIT_OCCUPANCY_MULTIPLIER = 2
63
64
def _compute_num_kv_splits(max_seq_len: int, num_threads: int) -> int:
65
"""Mirrors TritonMLAImpl's _compute_num_kv_splits, using the CPU thread
66
- count in place of SM count.
67
- """
66
+ count in place of SM count."""
67
ideal_splits = 1
68
while ideal_splits < max(1, max_seq_len // _MIN_WORK_PER_SPLIT):
69
ideal_splits *= 2
vllm/v1/attention/backends/mla/flashmla_sparse.py
+1
-2
@@ -847,8 +847,7 @@ class FlashMLASparseImpl(SparseMLACommonImpl[FlashMLASparseMetadata]):
847
prefill_meta: "FlashMLASparseMetadata.FP8SeparatePrefillDecode.Prefill",
848
) -> tuple[torch.Tensor, torch.Tensor, torch.Tensor]:
849
"""All-gather this rank's upconverted KV shard so the chunk's rows attend
850
- the whole context, and map their top-k onto the rank-major result.
851
- """
850
+ the whole context, and map their top-k onto the rank-major result."""
851
shard_rows = int(chunk.chunk_tot_seqlen)
852
assert self.gathered_kv_workspace is not None
853
gathered_kv = self.gathered_kv_workspace[: self.dcp_world_size * shard_rows]
vllm/v1/attention/backends/mla/indexer.py
+1
-2
@@ -1118,8 +1118,7 @@ class DeepseekV32IndexerMetadataBuilder(AttentionMetadataBuilder):
1118
1119
def _prefill_split_seq_lens(self, seq_lens_cpu: torch.Tensor) -> torch.Tensor:
1120
"""Per-request KV lengths the prefill chunker budgets logits with;
1121
- subclasses whose logits rows are wider than the context override.
1122
- """
1121
+ subclasses whose logits rows are wider than the context override."""
1122
return seq_lens_cpu
1123
1124
@staticmethod
vllm/v1/attention/backends/mla/prefill/base.py
+1
-2
@@ -70,8 +70,7 @@ class MLAPrefillBackend(ABC):
70
def supports_quant_output(self, quant_key: "QuantKey") -> bool:
71
"""Whether `run_prefill_new_tokens` can write quantized output
72
directly (fused) for the given quant key, skipping the post-quant
73
- pass. Overridden by backends that support it.
74
- """
73
+ pass. Overridden by backends that support it."""
74
return False
75
76
def supports_out(self) -> bool:
vllm/v1/attention/backends/rocm_aiter_unified_attn.py
+1
-2
@@ -110,8 +110,7 @@ class RocmAiterUnifiedAttentionBackend(RocmAttentionBackend):
110
@classmethod
111
def customize_spec(cls, spec: AttentionSpec) -> AttentionSpec:
112
"""Keep K and V packed in the content dim, unlike the native HIP
113
- kernels the base class targets.
114
- """
113
+ kernels the base class targets."""
114
# block_size == 1 is the per-token page-size probe (see
115
# Platform.get_page_size_bytes); real blocks must be gatherable in
116
# 16-token units by the ROCm kernel.
vllm/v1/attention/backends/rocm_attn.py
+1
-2
@@ -244,8 +244,7 @@ class RocmAttentionBackend(AttentionBackend):
244
@classmethod
245
def customize_spec(cls, spec: AttentionSpec) -> AttentionSpec:
246
"""K and V as two head groups so the native HIP kernels address each side
247
- as one contiguous region (x-packed interior applied in split_kv_cache).
248
- """
247
+ as one contiguous region (x-packed interior applied in split_kv_cache)."""
248
if spec.state_content_bytes is not None:
249
return spec
250
assert spec.head_size == spec.head_size_v, (
vllm/v1/attention/backends/triton_attn.py
+1
-2
@@ -275,8 +275,7 @@ class TritonAttentionBackend(AttentionBackend):
275
@classmethod
276
def customize_spec(cls, spec: "AttentionSpec") -> "AttentionSpec":
277
"""Per-token-head modes pack inline fp32 scales after each head's
278
- data, so the content is (data + one scale) per K/V side.
279
- """
278
+ data, so the content is (data + one scale) per K/V side."""
279
mode = spec.kv_quant_mode
280
if spec.state_content_bytes is not None or not mode.is_per_token_head:
281
return spec
vllm/v1/attention/ops/turboquant_soa/triton_turboquant_store.py
+1
-2
@@ -45,8 +45,7 @@ def _store_quantized_value(
45
BLOCK_GRP: tl.constexpr,
46
):
47
"""Uniform quantization of values to VQB bits, pack, and store with
48
- scale/zero in the per-block SoA metadata region (Opt#3 layout).
49
- """
48
+ scale/zero in the per-block SoA metadata region (Opt#3 layout)."""
49
if VQB == 3:
50
val_vec = tl.load(Value_ptr + base + d_offs, mask=d_mask, other=0.0).to(
51
tl.float32
vllm/v1/core/kv_cache_coordinator.py
+1
-2
@@ -461,8 +461,7 @@ class KVCacheCoordinator(ABC):
461
) -> tuple[tuple[list[KVCacheBlock], ...], int, int]:
462
"""Returns the per-group hit blocks, the hit length, and the number of
463
``num_uncached_common_prefix_tokens`` (a shared prefix that a
464
- sparse-retention group has not cached yet; 0 unless hybrid).
465
- """
464
+ sparse-retention group has not cached yet; 0 unless hybrid)."""
465
pass
466
467
def new_step_starts(self) -> None:
vllm/v1/core/kv_cache_manager.py
+1
-2
@@ -856,8 +856,7 @@ class KVCacheManager:
856
self, request_id: str, start_token: int, end_token: int
857
) -> list[int]:
858
"""The request's block ids covering [start_token, end_token), from
859
- the groups whose new blocks are zeroed by the worker.
860
- """
859
+ the groups whose new blocks are zeroed by the worker."""
860
ids: list[int] = []
861
for mgr in self.coordinator.single_type_managers:
862
if mgr.records_new_block_ids:
vllm/v1/core/sched/interface.py
+2
-4
@@ -178,8 +178,7 @@ class SchedulerInterface(ABC):
178
179
def has_unfinished_requests(self) -> bool:
180
"""Returns True if there are unfinished requests in the scheduler's
181
- internal queue.
182
- """
181
+ internal queue."""
182
return self.get_num_unfinished_requests() > 0
183
184
@abstractmethod
@@ -199,8 +198,7 @@ class SchedulerInterface(ABC):
198
199
def has_requests(self) -> bool:
200
"""Returns True if there are unfinished requests, or finished requests
202
- not yet returned in SchedulerOutputs.
203
- """
201
+ not yet returned in SchedulerOutputs."""
202
return self.has_unfinished_requests() or self.has_finished_requests()
203
204
@property
vllm/v1/core/sched/request_queue.py
+3
-6
@@ -43,8 +43,7 @@ class RequestQueue(ABC):
43
@abstractmethod
44
def prepend_requests(self, requests: "RequestQueue") -> None:
45
"""Prepend all requests from another queue to the front of this
46
- queue.
47
- """
46
+ queue."""
47
pass
48
49
@abstractmethod
@@ -161,16 +160,14 @@ class PriorityRequestQueue(RequestQueue):
160
"""Add a request to the queue according to priority policy.
161
162
Note: In a priority queue, there is no concept of prepending to the
164
- front. Requests are ordered by (priority, arrival_time).
165
- """
163
+ front. Requests are ordered by (priority, arrival_time)."""
164
self.add_request(request)
165
166
def prepend_requests(self, requests: RequestQueue) -> None:
167
"""Add all requests from another queue according to priority policy.
168
169
Note: In a priority queue, there is no concept of prepending to the
172
- front. Requests are ordered by (priority, arrival_time).
173
- """
170
+ front. Requests are ordered by (priority, arrival_time)."""
171
for request in requests:
172
self.add_request(request)
173
vllm/v1/engine/async_llm.py
+1
-2
@@ -871,8 +871,7 @@ class AsyncLLM(EngineClient):
871
) -> None:
872
"""Submit a pre-aborted request so the connector's request_finished
873
hook runs to free any pre-admission KV-transfer resources (e.g. NIXL
874
- prefill blocks pinned on the P node).
875
- """
874
+ prefill blocks pinned on the P node)."""
875
request = EngineCoreRequest(
876
request_id=request_id,
877
prompt_token_ids=[0],
vllm/v1/engine/core.py
+3
-6
@@ -598,8 +598,7 @@ class EngineCore:
598
599
def _should_throttle_prefills(self) -> bool:
600
"""Whether to defer new prefills this step (DP prefill balancing).
601
- Overridden by the DP engine core; never throttles otherwise.
602
- """
601
+ Overridden by the DP engine core; never throttles otherwise."""
602
return False
603
604
def step(self) -> tuple[dict[int, EngineCoreOutputs], bool]:
@@ -1623,8 +1622,7 @@ class EngineCoreProc(EngineCore):
1622
@staticmethod
1623
def _convert_msgspec_args(method, args):
1624
"""If a provided arg type doesn't match corresponding target method
1626
- arg type, try converting to msgspec object.
1627
- """
1625
+ arg type, try converting to msgspec object."""
1626
if not args:
1627
return args
1628
arg_types = signature(method).parameters.values()
@@ -2006,8 +2004,7 @@ class EngineCoreProc(EngineCore):
2004
2005
class DPEngineCoreProc(EngineCoreProc):
2006
"""ZMQ-wrapper for running EngineCore in background process
2009
- in a data parallel context.
2010
- """
2007
+ in a data parallel context."""
2008
2009
def __init__(
2010
self,
vllm/v1/engine/core_client.py
+7
-14
@@ -248,8 +248,7 @@ class EngineCoreClient(ABC):
248
249
def dp_engines_running(self) -> bool:
250
"""Returns True if data parallel engines are collectively in a
251
- running state.
252
- """
251
+ running state."""
252
raise NotImplementedError
253
254
async def commit_elastic_ep(self) -> None:
@@ -446,8 +445,7 @@ class InprocClient(EngineCoreClient):
445
@dataclass
446
class BackgroundResources:
447
"""Used as a finalizer for clean shutdown, avoiding
449
- circular reference back to the client object.
450
- """
448
+ circular reference back to the client object."""
449
450
ctx: zmq.Context
451
# If CoreEngineProcManager, it manages local engines;
@@ -801,8 +799,7 @@ class MPClient(EngineCoreClient):
799
800
def _apply_ready_response(self, payload: bytes) -> None:
801
"""Decode an EngineCoreReadyResponse and sync any post-initialization
804
- config changes (e.g. auto-fitted max_model_len) back to the frontend.
805
- """
802
+ config changes (e.g. auto-fitted max_model_len) back to the frontend."""
803
vllm_config = self.vllm_config
804
response = (
805
msgspec.msgpack.decode(payload, type=EngineCoreReadyResponse)
@@ -1333,8 +1330,7 @@ class AsyncMPClient(MPClient):
1330
1331
class DPAsyncMPClient(AsyncMPClient):
1332
"""Asyncio-compatible client for multi-proc, multi-engine (data parallel)
1336
- EngineCore. Assumes external load-balancing by default.
1337
- """
1333
+ EngineCore. Assumes external load-balancing by default."""
1334
1335
def __init__(
1336
self,
@@ -1518,8 +1514,7 @@ class DPAsyncMPClient(AsyncMPClient):
1514
1515
class DPLBAsyncMPClient(DPAsyncMPClient):
1516
"""Asyncio-compatible client for multi-proc, multi-engine (data parallel)
1521
- EngineCore. Load-balances between multiple engine processes.
1522
- """
1517
+ EngineCore. Load-balances between multiple engine processes."""
1518
1519
def __init__(
1520
self,
@@ -1827,8 +1822,7 @@ class DPLBAsyncMPClient(DPAsyncMPClient):
1822
num_redundant_experts: int,
1823
) -> None:
1824
"""Prepare scale up by creating new engine cores and reconfiguring
1830
- existing ones.
1831
- """
1825
+ existing ones."""
1826
self._setup_elastic_ep_reconfig_bootstrap()
1827
1828
# Phase 1: Send reconfig messages to existing engines
@@ -1920,8 +1914,7 @@ class DPLBAsyncMPClient(DPAsyncMPClient):
1914
1915
async def _commit_scale_down_elastic_ep(self, new_data_parallel_size: int) -> None:
1916
"""Scale down the data parallel size by shutting down and
1923
- reconfiguring existing engine cores.
1924
- """
1917
+ reconfiguring existing engine cores."""
1918
cur_data_parallel_size = len(self.core_engines)
1919
1920
self.eep_scaling_cache = ElasticScalingCache(
vllm/v1/engine/detokenizer.py
+1
-2
@@ -147,8 +147,7 @@ class BaseIncrementalDetokenizer(IncrementalDetokenizer, ABC):
147
148
def get_next_output_text(self, finished: bool, delta: bool) -> str:
149
"""If delta is True, only new text since the last call to
150
- this method is returned
151
- """
150
+ this method is returned"""
151
# We return the full output text if the sequence is finished.
152
buffer_length = 0 if finished else self.stop_buffer_length
153
if not delta:
vllm/v1/engine/utils.py
+1
-2
@@ -1041,8 +1041,7 @@ def get_engine_zmq_addresses(
1041
1042
Set ``defer_api_server_ports=False`` only when the consumer cannot
1043
report a bound port back (e.g. the Rust front-end). IPC paths are
1044
- unaffected.
1045
- """
1044
+ unaffected."""
1045
parallel_config = vllm_config.parallel_config
1046
local_engine_count = parallel_config.data_parallel_size_local
1047
local_start_index = parallel_config.data_parallel_rank_local
vllm/v1/executor/abstract.py
+1
-2
@@ -284,8 +284,7 @@ class Executor(ABC):
284
@abstractmethod
285
def check_health(self) -> None:
286
"""Checks if the executor is healthy. If not, it should raise an
287
- exception.
288
- """
287
+ exception."""
288
raise NotImplementedError
289
290
def shutdown(self) -> None:
vllm/v1/executor/multiproc_executor.py
+4
-8
@@ -384,8 +384,7 @@ class MultiprocExecutor(Executor):
384
ec_output_aggregator: ECOutputAggregator | None = None,
385
) -> Any:
386
"""Returns single result if unique_reply_rank and/or an output
387
- aggregator is provided, otherwise list.
388
- """
387
+ aggregator is provided, otherwise list."""
388
assert self.rpc_broadcast_mq is not None, (
389
"collective_rpc should not be called on follower node"
390
)
@@ -452,8 +451,7 @@ class MultiprocExecutor(Executor):
451
def _ensure_worker_termination(worker_procs: list[BaseProcess]):
452
"""Ensure that all worker processes are terminated. Assumes workers have
453
received termination requests. Waits for processing, then sends
455
- termination and kill signals if needed.
456
- """
454
+ termination and kill signals if needed."""
455
456
def wait_for_termination(procs, timeout):
457
if not time:
@@ -854,8 +852,7 @@ class WorkerProc:
852
@staticmethod
853
def worker_main(*args, **kwargs):
854
"""Worker initialization and execution loops.
857
- This runs a background process
858
- """
855
+ This runs a background process"""
856
# Signal handler used for graceful termination.
857
# SystemExit exception is only raised once to allow this and worker
858
# processes to terminate without error
@@ -1099,8 +1096,7 @@ class WorkerProc:
1096
def set_multiprocessing_worker_envs(local_world_size: int = 1):
1097
"""Set up environment variables that should be used when there are workers
1098
in a multiprocessing environment. This should be called by the parent
1102
- process before worker processes are created
1103
- """
1099
+ process before worker processes are created"""
1100
_maybe_force_spawn()
1101
1102
if current_platform.is_cpu() or "OMP_NUM_THREADS" in os.environ:
vllm/v1/executor/ray_utils.py
+1
-2
@@ -55,8 +55,7 @@ try:
55
56
class RayWorkerWrapper(WorkerWrapperBase):
57
"""Ray wrapper for vllm.worker.Worker, allowing Worker to be
58
- lazily initialized after Ray sets CUDA_VISIBLE_DEVICES.
59
- """
58
+ lazily initialized after Ray sets CUDA_VISIBLE_DEVICES."""
59
60
def __init__(self, *args, **kwargs) -> None:
61
super().__init__(*args, **kwargs)
vllm/v1/kv_cache_interface.py
+1
-2
@@ -1252,8 +1252,7 @@ class UniformTypeKVCacheSpecs(KVCacheSpec):
1252
1253
def get_max_layers_per_page_size(self) -> int:
1254
"""Max number of layers sharing a page size. For a balanced bucket
1255
- this equals the number of repetitions of the layer pattern.
1256
- """
1255
+ this equals the number of repetitions of the layer pattern."""
1256
return Counter(
1257
spec.page_size_bytes for spec in self.kv_cache_specs.values()
1258
).most_common(1)[0][1]
vllm/v1/kv_cache_layout.py
+1
-2
@@ -49,8 +49,7 @@ class KVCacheLayout(Enum):
49
@property
50
def is_block_compact(self) -> bool:
51
"""True when each page's [H, N, C] bytes form one contiguous run; i.e.
52
- the L and B dimensions are outermost.
53
- """
52
+ the L and B dimensions are outermost."""
53
return set(self.value[:2]) == {_DIM_L, _DIM_B}
54
55
@property
vllm/v1/kv_offload/base.py
+2
-4
@@ -472,8 +472,7 @@ class CopyRun:
472
"""A strided byte correspondence between this worker's physical page and
473
a canonical page: for i in range(num_fragments), fragment i spans
474
[local_offset + i * local_stride, +fragment_size) in the worker's page and
475
- [canonical_offset + i * canonical_stride, +fragment_size) canonically.
476
- """
475
+ [canonical_offset + i * canonical_stride, +fragment_size) canonically."""
476
477
local_offset: int
478
canonical_offset: int
@@ -554,8 +553,7 @@ class TransferResult:
553
class OffloadingWorker(ABC):
554
"""Runs in the worker process. Performs async KV transfers for ONE
555
offloaded medium (e.g. CPU). Direction is explicit via submit_store /
557
- submit_load, so there is no (src_medium, dst_medium) routing.
558
- """
556
+ submit_load, so there is no (src_medium, dst_medium) routing."""
557
558
@abstractmethod
559
def submit_store(
vllm/v1/kv_offload/cpu/gpu_worker.py
+7
-14
@@ -126,8 +126,7 @@ def compute_sub_block_ptrs(
126
class CopyPlan(NamedTuple):
127
"""Precomputed fragment-copy template for one data ref under the canonical
128
CPU layout, unrolled from the ref's mapped runs. Offsets are relative to
129
- the per-block base pointers on each side.
130
- """
129
+ the per-block base pointers on each side."""
130
131
frag_offsets_src: np.ndarray
132
frag_offsets_dst: np.ndarray
@@ -165,8 +164,7 @@ def _canonical_page_ids(
164
) -> np.ndarray:
165
"""Global canonical page ids matching compute_sub_block_ptrs' enumeration.
166
These identify canonical pages consistently across ranks, so they key
168
- CanonicalPageMapping.is_writer rotation.
169
- """
167
+ CanonicalPageMapping.is_writer rotation."""
168
if blocks_per_chunk == 1:
169
return block_ids[:count]
170
flat = (
@@ -179,8 +177,7 @@ def _canonical_block_sizes(
177
layer_refs_per_group: list[list[CanonicalKVCacheRef]], num_tensors: int
178
) -> list[int]:
179
"""Canonical CPU bytes per GPU block for each tensor, taken from the refs'
182
- mappings. Requires every ref to carry a mapping.
183
- """
180
+ mappings. Requires every ref to carry a mapping."""
181
canonical_bytes_per_block = [0] * num_tensors
182
for layer_refs in layer_refs_per_group:
183
for ref in layer_refs:
@@ -343,8 +340,7 @@ class SingleDirectionOffloadingHandler:
340
"""Upper bound on the number of copy descriptors for a transfer.
341
342
Exact for the direct layout. The canonical path may fill fewer:
346
- writer rotation later drops the blocks this rank does not write.
347
- """
343
+ writer rotation later drops the blocks this rank does not write."""
344
num_copy_ops = 0
345
for g_idx, (group_size, layer_refs) in enumerate(
346
zip(group_sizes, self.layer_refs_per_group)
@@ -373,8 +369,7 @@ class SingleDirectionOffloadingHandler:
369
"""Fill one group's copy descriptors for the direct (worker-private)
370
layout: one whole-page copy per (block, ref).
371
376
- Returns (op_idx past the filled descriptors, bytes added).
377
- """
372
+ Returns (op_idx past the filled descriptors, bytes added)."""
373
num_bytes = 0
374
for data_ref in self.layer_refs_per_group[g_idx]:
375
t_idx = data_ref.tensor_idx
@@ -417,8 +412,7 @@ class SingleDirectionOffloadingHandler:
412
scatter each block through the ref's precomputed CopyPlan, keeping
413
only the blocks this rank writes.
414
420
- Returns (op_idx past the filled descriptors, bytes added).
421
- """
415
+ Returns (op_idx past the filled descriptors, bytes added)."""
416
assert self._canonical_copy_plans is not None
417
# Zero-copy reinterpretation for pointer arithmetic: uint64 and the
418
# buffers' int64 are bit-equivalent for addresses
@@ -505,8 +499,7 @@ class SingleDirectionOffloadingHandler:
499
) -> tuple[np.ndarray, np.ndarray]:
500
"""Keep only the blocks this rank writes: replicated ranks take turns
501
writing shared canonical pages, keyed by the rank-consistent CPU-side
508
- canonical page id.
509
- """
502
+ canonical page id."""
503
cpu_page_ids = _canonical_page_ids(
504
group_dst,
505
self.dst_blocks_per_chunk,
vllm/v1/kv_offload/cpu/spec.py
+2
-4
@@ -28,8 +28,7 @@ def _all_workers_barrier() -> None:
28
"""Block until every worker rank has reached this point (gloo cpu group).
29
30
A superset of the node-local mmap openers suffices: once the barrier
31
- releases, every worker sharing the region file has mapped it.
32
- """
31
+ releases, every worker sharing the region file has mapped it."""
32
from vllm.distributed.parallel_state import (
33
get_inner_dp_world_group,
34
get_world_group,
@@ -162,8 +161,7 @@ class CPUOffloadingSpec(OffloadingSpec):
161
162
def _uses_shared_region(self) -> bool:
163
"""Whether the worker CPU buffer is the shared mmap region (vs a private
165
- per-rank tensor); replicated-layout dedup is gated on this being True.
166
- """
164
+ per-rank tensor); replicated-layout dedup is gated on this being True."""
165
return current_platform.is_cuda_alike()
166
167
def create_worker(self, kv_caches: CanonicalKVCaches) -> CPUOffloadingWorker:
vllm/v1/kv_offload/tiering/async_lookup.py
+1
-2
@@ -216,8 +216,7 @@ class AsyncLookupManager(ABC):
216
def mark_miss(self, keys: Collection[OffloadKey]) -> None:
217
"""Force the cached verdict for ``keys`` to False after a failed load, so
218
the scheduler stops re-issuing the doomed promotion (livelock, #49176).
219
- Keys with no cached entry are skipped.
220
- """
219
+ Keys with no cached entry are skipped."""
220
for key in keys:
221
state = self._lookup_state.get(key)
222
if state is not None:
vllm/v1/kv_offload/tiering/example/manager.py
+1
-2
@@ -168,8 +168,7 @@ class ExampleSecondaryTierManager(SecondaryTierManager):
168
@override
169
def drain_jobs(self) -> None:
170
"""Synchronous tier — submit_*() returns only after the operation
171
- completes, so there is nothing to wait for.
172
- """
171
+ completes, so there is nothing to wait for."""
172
return
173
174
def get_num_chunks(self) -> int:
vllm/v1/kv_offload/tiering/fs/io.py
+1
-2
@@ -139,8 +139,7 @@ def _load_block(
139
) -> None:
140
"""Read one KV block from disk; remove the file only on a provable short
141
read (a too-short file is genuine corruption) and leave it untouched on any
142
- other error.
143
- """
142
+ other error."""
143
fd: int | None = None
144
view_slice = view.cast("B")[offset : offset + block_size]
145
o_direct = O_DIRECT if use_o_direct else 0
vllm/v1/kv_offload/tiering/fs/manager.py
+1
-2
@@ -269,8 +269,7 @@ class FileSystemTierManager(SecondaryTierManager):
269
@override
270
def get_finished_jobs(self) -> Iterable[JobResult]:
271
"""Collect finished jobs; a failed promotion marks only its failed keys
272
- as a miss here (scheduler thread).
273
- """
272
+ as a miss here (scheduler thread)."""
273
results = []
274
for job_id, success, transfer_time in self._pool.get_finished():
275
if self.events is not None:
vllm/v1/kv_offload/tiering/manager.py
+1
-2
@@ -143,8 +143,7 @@ class CPUPrimaryTierOffloadingManager(CPUOffloadingManager):
143
144
class _SecondaryTierFacingParent(ParentManager):
145
"""Wrapper that implements ParentManager by delegating to the
146
- TieringOffloadingManager with exclude_tier_idx set to the origin tier.
147
- """
146
+ TieringOffloadingManager with exclude_tier_idx set to the origin tier."""
147
148
__slots__ = ("_m", "_origin_idx")
149
vllm/v1/kv_offload/tiering/obj/manager.py
+2
-4
@@ -308,8 +308,7 @@ class ObjectStoreSecondaryTierManager(SecondaryTierManager):
308
309
def _poll_active_transfers(self) -> None:
310
"""Poll all in-flight transfers once; move newly-completed (success or
311
- failure) into ``_pending_results`` and release their NIXL handles.
312
- """
311
+ failure) into ``_pending_results`` and release their NIXL handles."""
312
for job_id, entry in list(self._transfers.items()):
313
try:
314
state = self._agent.check_xfer_state(entry.xfer_handle)
@@ -364,8 +363,7 @@ class ObjectStoreSecondaryTierManager(SecondaryTierManager):
363
364
def get_finished_jobs(self) -> Iterable[JobResult]:
365
"""Poll transfers; a failed promotion marks its cached verdicts False
367
- here (scheduler thread).
368
- """
366
+ here (scheduler thread)."""
367
self._poll_active_transfers()
368
results = self._pending_results
369
self._pending_results = []
vllm/v1/kv_offload/tiering/p2p/manager.py
+2
-4
@@ -134,8 +134,7 @@ class P2PDestInfo:
134
135
def _parse_source(kv_params: dict | None) -> P2PSourceInfo | None:
136
"""Parse the consumer sub-dict (PD ``remote_prefiller`` or symmetric
137
- ``remote_kv_source``) into a ``P2PSourceInfo``, or None if absent/incomplete.
138
- """
137
+ ``remote_kv_source``) into a ``P2PSourceInfo``, or None if absent/incomplete."""
138
role = _remote_prefiller_params(kv_params)
139
do_probe = False
140
if role is None:
@@ -156,8 +155,7 @@ def _parse_source(kv_params: dict | None) -> P2PSourceInfo | None:
155
156
def _parse_dest(kv_params: dict | None) -> P2PDestInfo | None:
157
"""Parse the producer ``remote_decoder`` sub-dict into a ``P2PDestInfo``,
159
- or None if the block is absent (not a remote-decode request).
160
- """
158
+ or None if the block is absent (not a remote-decode request)."""
159
role = _remote_decoder_params(kv_params)
160
if role is None:
161
return None
vllm/v1/kv_offload/tiering/spec.py
+1
-2
@@ -414,8 +414,7 @@ class TieringOffloadingSpec(CPUOffloadingSpec):
414
"""Require a mapping on every ref and record layer portability.
415
416
Fails loudly rather than persist direct-layout bytes under a
417
- canonical format identity.
418
- """
417
+ canonical format identity."""
418
all_refs = [
419
ref for group_refs in kv_caches.group_data_refs for ref in group_refs
420
]
vllm/v1/metrics/loggers.py
+1
-2
@@ -91,8 +91,7 @@ def load_stat_logger_plugin_factories() -> list[StatLoggerFactory]:
91
92
class AggregateStatLoggerBase(StatLoggerBase):
93
"""Abstract base class for loggers that
94
- aggregate across multiple DP engines.
95
- """
94
+ aggregate across multiple DP engines."""
95
96
@abstractmethod
97
def __init__(self, vllm_config: VllmConfig, engine_indexes: list[int]): ...
vllm/v1/metrics/perf.py
+1
-2
@@ -1820,8 +1820,7 @@ def get_required(obj: object, attr: str):
1820
1821
def getattr_from_list(obj: object, attrs: list[str], default: object = None):
1822
"""Try to get the first attr that exists in the object
1823
- from a list of attrs. Otherwise return None.
1824
- """
1823
+ from a list of attrs. Otherwise return None."""
1824
for attr in attrs:
1825
if hasattr(obj, attr):
1826
return getattr(obj, attr)
vllm/v1/metrics/ray_wrappers.py
+3
-6
@@ -82,8 +82,7 @@ class RayPrometheusMetric:
82
83
class RayGaugeWrapper(RayPrometheusMetric):
84
"""Wraps around ray.util.metrics.Gauge to provide same API as
85
- prometheus_client.Gauge
86
- """
85
+ prometheus_client.Gauge"""
86
87
def __init__(
88
self,
@@ -117,8 +116,7 @@ class RayGaugeWrapper(RayPrometheusMetric):
116
117
class RayCounterWrapper(RayPrometheusMetric):
118
"""Wraps around ray.util.metrics.Counter to provide same API as
120
- prometheus_client.Counter
121
- """
119
+ prometheus_client.Counter"""
120
121
def __init__(
122
self,
@@ -143,8 +141,7 @@ class RayCounterWrapper(RayPrometheusMetric):
141
142
class RayHistogramWrapper(RayPrometheusMetric):
143
"""Wraps around ray.util.metrics.Histogram to provide same API as
146
- prometheus_client.Histogram
147
- """
144
+ prometheus_client.Histogram"""
145
146
def __init__(
147
self,
vllm/v1/sample/logits_processor/builtin.py
+2
-4
@@ -129,8 +129,7 @@ class LogitBiasLogitsProcessor(LogitsProcessor):
129
130
def is_argmax_invariant(self) -> bool:
131
"""Logit bias can rebalance token probabilities and change the
132
- outcome of argmax in greedy sampling.
133
- """
132
+ outcome of argmax in greedy sampling."""
133
return False
134
135
def update_state(self, batch_update: BatchUpdate | None):
@@ -189,8 +188,7 @@ class MinTokensLogitsProcessor(LogitsProcessor):
188
189
def is_argmax_invariant(self) -> bool:
190
"""By censoring stop tokens, min-tokens can change the outcome
192
- of the argmax operation in greedy sampling.
193
- """
191
+ of the argmax operation in greedy sampling."""
192
return False
193
194
@staticmethod
vllm/v1/sample/logits_processor/state.py
+1
-2
@@ -69,8 +69,7 @@ class BatchUpdateBuilder:
69
@property
70
def removed(self) -> list[RemovedRequest]:
71
"""Removed request indices sorted in
72
- descending order
73
- """
72
+ descending order"""
73
self._ensure_removed_sorted()
74
return self._removed
75
vllm/v1/serial_utils.py
+2
-4
@@ -90,8 +90,7 @@ def _typestr(val: Any) -> tuple[str, str] | None:
90
91
def _encode_type_info_recursive(obj: Any) -> Any:
92
"""Recursively encode type information for nested structures of
93
- lists/dicts.
94
- """
93
+ lists/dicts."""
94
if obj is None:
95
return None
96
if type(obj) is list:
@@ -105,8 +104,7 @@ def _decode_type_info_recursive(
104
type_info: Any, data: Any, convert_fn: Callable[[Sequence[str], Any], Any]
105
) -> Any:
106
"""Recursively decode type information for nested structures of
108
- lists/dicts.
109
- """
107
+ lists/dicts."""
108
if type_info is None:
109
return data
110
if isinstance(type_info, dict):
vllm/v1/simple_kv_offload/manager.py
+3
-6
@@ -259,8 +259,7 @@ class SimpleCPUOffloadScheduler:
259
gpu_config: "KVCacheConfig", cpu_capacity_bytes: int
260
) -> "KVCacheConfig":
261
"""Derive a CPU KVCacheConfig from the GPU config.
262
- Same kv_cache_groups, num_blocks scaled by CPU/GPU memory ratio.
263
- """
262
+ Same kv_cache_groups, num_blocks scaled by CPU/GPU memory ratio."""
263
# Import here to avoid potential circular imports
264
from vllm.v1.kv_cache_interface import KVCacheTensor
265
@@ -315,8 +314,7 @@ class SimpleCPUOffloadScheduler:
314
315
def bind_gpu_block_pool(self, gpu_block_pool: BlockPool) -> None:
316
"""Bind GPU block pool so that we can touch blocks during stores.
318
- Called by Scheduler after kv_cache_manager is ready.
319
- """
317
+ Called by Scheduler after kv_cache_manager is ready."""
318
self._gpu_block_pool = gpu_block_pool
319
320
def get_num_new_matched_tokens(
@@ -1131,8 +1129,7 @@ class SimpleCPUOffloadScheduler:
1129
block_ids: list[int],
1130
) -> tuple[bool, dict[str, Any] | None]:
1131
"""Always returns (False, None). GPU blocks are protected by ref_cnt,
1134
- so the scheduler can free blocks immediately.
1135
- """
1132
+ so the scheduler can free blocks immediately."""
1133
req_id = request.request_id
1134
1135
# Release any temp CPU hit pin from get_num_new_matched_tokens()
vllm/v1/spec_decode/extract_hidden_states.py
+1
-2
@@ -396,8 +396,7 @@ class ExtractHiddenStatesProposer:
396
397
def validate_same_kv_cache_group(self, kv_cache_config: KVCacheConfig) -> None:
398
"""Validate all drafting layers belong to the same KV cache group
399
- and record the group index for common_attn_metadata selection.
400
- """
399
+ and record the group index for common_attn_metadata selection."""
400
assert len(self.attn_layer_names) == 1
401
layer = self.attn_layer_names[0]
402
for gid, group in enumerate(kv_cache_config.kv_cache_groups):
vllm/v1/spec_decode/gemma4.py
+2
-4
@@ -221,8 +221,7 @@ class Gemma4Proposer(SpecDecodeBaseProposer):
221
def validate_same_kv_cache_group(self, kv_cache_config: KVCacheConfig) -> None:
222
"""Draft layers span multiple KV cache groups (sliding + full
223
attention with different head dimensions), so skip the base
224
- class single-group assertion.
225
- """
224
+ class single-group assertion."""
225
226
def initialize_attn_backend(
227
self,
@@ -230,8 +229,7 @@ class Gemma4Proposer(SpecDecodeBaseProposer):
229
kernel_block_sizes: list[int] | None = None,
230
) -> None:
231
"""Create separate AttentionGroup objects per KV cache spec
233
- so that each head-dim variant gets its own metadata builder.
234
- """
232
+ so that each head-dim variant gets its own metadata builder."""
233
all_attn_layers = get_layers_from_vllm_config(
234
self.vllm_config,
235
AttentionLayerBase, # type: ignore[type-abstract]
vllm/v1/spec_decode/llm_base_proposer.py
+1
-2
@@ -785,8 +785,7 @@ class SpecDecodeBaseProposer:
785
block_size: int,
786
) -> torch.Tensor:
787
"""Update positions, slot mappings, and sequence metadata for the
788
- next draft step. Returns the updated positions tensor.
789
- """
788
+ next draft step. Returns the updated positions tensor."""
789
positions_1d = positions[0] if self.uses_mrope else positions
790
if self.uses_mrope:
791
out_pos = self.mrope_positions[0, :batch_size]
vllm/v1/spec_decode/utils.py
+1
-2
@@ -847,6 +847,5 @@ def update_num_computed_tokens_for_batch_change(
847
848
def unconditional_to_conditional_rates(rates: list[float]) -> list[float]:
849
"""Convert per-position unconditional rates to per-position conditional
850
- rates for the early-terminating rejection loop (c_i = p_i / p_{i-1}).
851
- """
850
+ rates for the early-terminating rejection loop (c_i = p_i / p_{i-1})."""
851
return [p / q if q > 0.0 else 0.0 for p, q in zip(rates, [1.0, *rates[:-1]])]
vllm/v1/utils.py
+4
-8
@@ -144,8 +144,7 @@ class CpuGpuBuffer:
144
145
def copy_to_cpu(self, n: int | None = None) -> torch.Tensor:
146
"""NOTE: Because this method is non-blocking, explicit synchronization
147
- is needed to ensure the data is copied to CPU.
148
- """
147
+ is needed to ensure the data is copied to CPU."""
148
if n is None:
149
return self.cpu.copy_(self.gpu, non_blocking=True)
150
return self.cpu[:n].copy_(self.gpu[:n], non_blocking=True)
@@ -159,8 +158,7 @@ def get_engine_client_zmq_addr(
158
"""Return an IPC path (``local_only=True``) or ``tcp://host:port``.
159
160
``port=0`` lets the kernel assign the port at ``bind()`` time; the
162
- caller must recover it via ``getsockopt(zmq.LAST_ENDPOINT)``.
163
- """
161
+ caller must recover it via ``getsockopt(zmq.LAST_ENDPOINT)``."""
162
if local_only:
163
return get_open_zmq_ipc_path()
164
return get_tcp_uri(host, port)
@@ -265,8 +263,7 @@ class APIServerProcessManager:
263
) -> tuple[list[str], list[str]]:
264
"""Return (inputs, outputs) reported by each child, indexed by
265
``client_index``. Raises ``RuntimeError`` on timeout or premature
268
- child exit.
269
- """
266
+ child exit."""
267
n = len(self._address_pipes)
268
inputs: list[str | None] = [None] * n
269
outputs: list[str | None] = [None] * n
@@ -427,8 +424,7 @@ class RustFrontendProcessManager:
424
425
class _SubprocessWrapper:
426
"""Wraps subprocess.Popen to provide the BaseProcess-like interface
430
- needed by wait_for_completion_or_failure.
431
- """
427
+ needed by wait_for_completion_or_failure."""
428
429
def __init__(self, proc, name: str):
430
self._proc = proc
vllm/v1/worker/encoder_cudagraph.py
+1
-2
@@ -76,8 +76,7 @@ class EncoderCudaGraphManager:
76
model: SupportsEncoderCudaGraph,
77
):
78
"""Initialize CUDA graph manager with provided token budgets
79
- and max batch size.
80
- """
79
+ and max batch size."""
80
self.vllm_config = vllm_config
81
self.device = device
82
self.dtype = dtype
vllm/v1/worker/gpu/cudagraph_utils.py
+4
-8
@@ -62,8 +62,7 @@ class AttentionState(NamedTuple):
62
@dataclass(frozen=True)
63
class BatchExecutionDescriptor:
64
"""Describes the shape of the batch and CG mode to run; this is used to make shape
65
- matches between the capture and runtime.
66
- """
65
+ matches between the capture and runtime."""
66
67
cg_mode: CUDAGraphMode
68
num_tokens: int
@@ -91,8 +90,7 @@ def make_cudagraph_stats(
90
class CreateForwardFn(Protocol):
91
"""Factory that prepares inputs (OUTSIDE the graph) and returns a
92
forward_fn. Called with warmup=True for the warmup pass and warmup=False
94
- for the captured pass.
95
- """
93
+ for the captured pass."""
94
95
def __call__(
96
self,
@@ -955,8 +953,7 @@ def profile_cudagraph_memory(runner: "GPUModelRunner") -> int:
953
def _extrapolate_full_graph_memory(mem_samples: list[int], total_graphs: int) -> int:
954
"""Extrapolate the total FULL capture cost from samples of the largest
955
graphs. The first capture allocates the pool baseline; later graphs mostly
958
- reuse it, so the second sample is taken as the per-graph cost.
959
- """
956
+ reuse it, so the second sample is taken as the per-graph cost."""
957
if not mem_samples:
958
return 0
959
first_capture = mem_samples[0]
@@ -993,8 +990,7 @@ def _init_minimal_kv_cache_for_profiling(runner: "GPUModelRunner") -> None:
990
991
def _teardown_profiling_state(runner: "GPUModelRunner") -> None:
992
"""Release the profiling KV cache and captured graphs while keeping model
996
- weights, so the real ``initialize_kv_cache`` starts from a clean slate.
997
- """
993
+ weights, so the real ``initialize_kv_cache`` starts from a clean slate."""
994
torch.accelerator.synchronize()
995
if hasattr(runner.model_state, "_mamba_ctx"):
996
runner.model_state._mamba_ctx = None
vllm/v1/worker/gpu/model_runner.py
+1
-2
@@ -2228,8 +2228,7 @@ class GPUModelRunner(LoRAModelRunnerMixin):
2228
2229
def shutdown(self) -> None:
2230
"""Release GPU tensors (model weights, KV caches, workspace) so that
2231
- memory is reclaimable when running in the same process.
2232
- """
2231
+ memory is reclaimable when running in the same process."""
2232
torch.accelerator.synchronize()
2233
self.cudagraph_manager = None
2234
self.fast_prefill = None
vllm/v1/worker/gpu/model_states/interface.py
+1
-2
@@ -144,8 +144,7 @@ class ModelState(ABC):
144
) -> None:
145
"""Hook run on real batches before the forward pass (after block tables
146
are gathered). Used by mamba "align" prefix caching to pre-copy state
147
- across block boundaries. No-op by default.
148
- """
147
+ across block boundaries. No-op by default."""
148
return None
149
150
def postprocess_state(
vllm/v1/worker/gpu/pp_utils.py
+2
-4
@@ -38,8 +38,7 @@ def compute_need_sampled_mask(input_batch: InputBatch) -> np.ndarray | None:
38
"""Return a bool array of shape `[input_batch.num_reqs]` marking requests
39
that produce a sampled token this step, and therefore must have that token
40
(and the draft block proposed from it) propagated to the earlier PP stages.
41
- Returns None if no request in the batch produces a sample.
42
- """
41
+ Returns None if no request in the batch produces a sample."""
42
old_computed = input_batch.num_computed_tokens_np
43
prefill_len = input_batch.prefill_len_np
44
# Exclude non-final prefill chunks (they don't produce a sample).
@@ -179,8 +178,7 @@ class PPHandler:
178
179
def receive(self, input_batch: InputBatch) -> bool:
180
"""Returns True iff sampled tokens need to be gathered from *all*
182
- requests in the batch.
183
- """
181
+ requests in the batch."""
182
assert not self.is_last_rank
183
need_sampled_mask = compute_need_sampled_mask(input_batch)
184
if need_sampled_mask is None:
vllm/v1/worker/gpu/sample/output.py
+1
-2
@@ -76,8 +76,7 @@ MAX_COMPACT_SUPPORT = 2048
76
77
class SamplingMaskTensors(NamedTuple):
78
"""Device-side masks pending async D2H: compact ids, plus the bitmask as
79
- the exact fallback for rows wider than ``max_num_kept``.
80
- """
79
+ the exact fallback for rows wider than ``max_num_kept``."""
80
81
# [num_requests, max_num_kept]
82
token_ids: torch.Tensor
vllm/v1/worker/gpu/sample/sampler.py
+1
-2
@@ -107,8 +107,7 @@ class Sampler:
107
self, idx_mapping_np: np.ndarray, include_token_ids: bool = True
108
) -> tuple[int, int] | None:
109
"""(num_logprobs, max_per_req_token_ids) for the given requests, or
110
- None when none of them want logprobs.
111
- """
110
+ None when none of them want logprobs."""
111
max_num_logprobs = self.sampling_states.max_num_logprobs(idx_mapping_np)
112
max_token_ids = (
113
self.logprob_token_ids_state.max_num_token_ids(idx_mapping_np)
vllm/v1/worker/gpu/spec_decode/adaptive_verification.py
+2
-4
@@ -190,8 +190,7 @@ class AdaptiveVerificationManager:
190
"""Dummy-run kwargs whose step timings seed the cost tables.
191
192
Run these inside StepTimingCollector.collect(), then hand the block's
193
- timings to set_initial_cost_curves.
194
- """
193
+ timings to set_initial_cost_curves."""
194
max_num_tokens = self.req_states.max_num_batched_tokens
195
size = self._cudagraph_limit = capture_sizes[-1] if capture_sizes else 0
196
# Also profile beyond the capture limit: real steps run there
@@ -261,8 +260,7 @@ class AdaptiveVerificationManager:
260
input_batch: "InputBatch",
261
) -> None:
262
"""Publish this step's raw confidences for the ranking kernel and start
264
- copying them to the CPU, where a later step's budget reads them.
265
- """
263
+ copying them to the CPU, where a later step's budget reads them."""
264
num_reqs = input_batch.num_reqs
265
ready_idx = self._stale_idx ^ 1
266
with gpu_sync_allowed():
vllm/v1/worker/gpu/spec_decode/dflash/cudagraph.py
+1
-2
@@ -72,8 +72,7 @@ def _prepare_dflash_inputs_to_capture(
72
73
class DFlashCudaGraphManager(CudaGraphManager):
74
"""DFlash CudaGraphManager for the parallel-drafting query forward,
75
- building its own attention metadata from scratch.
76
- """
75
+ building its own attention metadata from scratch."""
76
77
def capture(
78
self,
vllm/v1/worker/gpu/spec_decode/eagle/utils.py
+1
-2
@@ -28,8 +28,7 @@ def _should_share(eagle: nn.Module, flag: str, draft, target) -> bool:
28
29
def get_target_lm_head(target_model: nn.Module, target_language_model: nn.Module):
30
"""The target's lm_head — from get_language_model() for
31
- *ForConditionalGeneration targets, else the top-level module.
32
- """
31
+ *ForConditionalGeneration targets, else the top-level module."""
32
return getattr(target_language_model, "lm_head", None) or getattr(
33
target_model, "lm_head", None
34
)
vllm/v1/worker/gpu/spec_decode/speculator.py
+1
-2
@@ -268,8 +268,7 @@ class DraftModelSpeculator(BaseSpeculator):
268
@property
269
def attn_vllm_config(self) -> VllmConfig:
270
"""Config for the draft's attention metadata builders. Overridden by
271
- speculators whose attention mode differs from the target's.
272
- """
271
+ speculators whose attention mode differs from the target's."""
272
return self.vllm_config
273
274
def set_attn(
vllm/v1/worker/gpu_model_runner.py
+5
-10
@@ -481,8 +481,7 @@ class AsyncGPUPoolingModelRunnerOutput(AsyncModelRunnerOutput):
481
482
class ExecuteModelState(NamedTuple):
483
"""Ephemeral cached state transferred between execute_model() and
484
- sample_tokens(), after execute_model() returns None.
485
- """
484
+ sample_tokens(), after execute_model() returns None."""
485
486
scheduler_output: "SchedulerOutput"
487
logits: torch.Tensor
@@ -1072,8 +1071,7 @@ class GPUModelRunner(
1071
first scheduled token (column j is position start - 1 - j); -1 where
1072
the position is before the prompt or already past it. Generated
1073
positions are left to the model: under async scheduling the CPU token
1075
- table holds placeholders for them.
1076
- """
1074
+ table holds placeholders for them."""
1075
buf = self.lookback_token_ids
1076
assert buf is not None
1077
buf.np.fill(-1)
@@ -3206,8 +3204,7 @@ class GPUModelRunner(
3204
3205
def _get_encoder_output_from_cache(self, mm_hash: str) -> torch.Tensor | None:
3206
"""Return a cached encoder output for multimodal
3209
- embedding gather.
3210
- """
3207
+ embedding gather."""
3208
return self.encoder_cache.get(mm_hash, None)
3209
3210
def _gather_mm_embeddings(
@@ -4179,8 +4176,7 @@ class GPUModelRunner(
4176
4177
This is true when `discard_request_mask` is set for every scheduled
4178
request (e.g., for chunked prefill requests that are not the last
4182
- prefill chunk).
4183
- """
4179
+ prefill chunk)."""
4180
num_reqs = self.input_batch.num_reqs
4181
return bool(self.discard_request_mask.np[:num_reqs].all())
4182
@@ -6573,8 +6569,7 @@ class GPUModelRunner(
6569
6570
def shutdown(self) -> None:
6571
"""Release GPU tensors (model weights, KV caches, workspace) so that
6576
- memory is reclaimable when running in the same process.
6577
- """
6572
+ memory is reclaimable when running in the same process."""
6573
from vllm.model_executor.layers.rotary_embedding import _ROPE_DICT
6574
from vllm.v1.worker.workspace import reset_workspace_manager
6575
vllm/v1/worker/gpu_worker.py
+1
-2
@@ -336,8 +336,7 @@ class Worker(WorkerBase):
336
def _scoped_allocator_max_split(self, max_split_size_mb: int):
337
"""Temporarily set max_split_size_mb to reduce allocator fragmentation at the
338
cost of more cudaMalloc calls (negligible in practice). Restores the original
339
- value on exit.
340
- """
339
+ value on exit."""
340
if not current_platform.is_cuda():
341
yield
342
return
vllm/v1/worker/startup_plan.py
+3
-6
@@ -77,8 +77,7 @@ def compute_plan_fingerprint(
77
def _plan_path(fingerprint: str) -> str:
78
"""Plans are regenerable derived state, so they live under the standard
79
vLLM cache root (like the torch.compile cache) and relocate with
80
- ``VLLM_CACHE_ROOT`` instead of needing a location knob of their own.
81
- """
80
+ ``VLLM_CACHE_ROOT`` instead of needing a location knob of their own."""
81
# VLLM_CACHE_ROOT is already user-expanded by envs.py.
82
return os.path.join(
83
envs.VLLM_CACHE_ROOT, "startup_plan", f"startup_plan_{fingerprint}.json"
@@ -135,8 +134,7 @@ def _applicable_kv_cache_memory_bytes(
134
def maybe_apply_startup_plan(worker: "Worker") -> None:
135
"""If enabled and ``--kv-cache-memory`` was not set explicitly, apply a
136
persisted plan by setting ``worker.cache_config.kv_cache_memory_bytes``.
138
- No-op unless ``VLLM_ENABLE_STARTUP_PLAN=1``.
139
- """
137
+ No-op unless ``VLLM_ENABLE_STARTUP_PLAN=1``."""
138
if (
139
not envs.VLLM_ENABLE_STARTUP_PLAN
140
or worker.cache_config.kv_cache_memory_bytes is not None
@@ -169,8 +167,7 @@ def maybe_apply_startup_plan(worker: "Worker") -> None:
167
def maybe_save_startup_plan(worker: "Worker", kv_cache_memory_bytes: int) -> None:
168
"""Atomically persist this boot's profiling result for future boots.
169
No-op unless ``VLLM_ENABLE_STARTUP_PLAN=1``; failures are logged,
172
- never raised.
173
- """
170
+ never raised."""
171
if not envs.VLLM_ENABLE_STARTUP_PLAN:
172
return
173
fingerprint = compute_plan_fingerprint(
vllm/v1/worker/worker_base.py
+1
-2
@@ -128,8 +128,7 @@ class WorkerBase:
128
129
def synchronize_device(self) -> None:
130
"""Block until in-flight device work completes; backends outside
131
- ``torch.accelerator`` must override with their own wait.
132
- """
131
+ ``torch.accelerator`` must override with their own wait."""
132
if torch.accelerator.is_available():
133
torch.accelerator.synchronize()
134