Files
wehub-resource-sync 7ce4c8e27e
pre-commit / pre-run-check (push) Has been cancelled
pre-commit / pre-commit (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:55:37 +08:00

188 lines
5.5 KiB
Python
Executable File

# SPDX-License-Identifier: Apache-2.0
# SPDX-FileCopyrightText: Copyright contributors to the vLLM project
"""
Run mypy on changed files.
This script is designed to be used as a pre-commit hook. It runs mypy
on files that have been changed. It groups files into different mypy calls
based on their directory to avoid import following issues.
Usage:
python tools/pre_commit/mypy.py <python_version> <changed_files...>
Args:
python_version: Python version to use (e.g., "3.10") or "local" to use
the local Python version.
changed_files: List of changed files to check.
"""
import subprocess
import sys
import regex as re
# After fixing errors resulting from changing follow_imports
# from "skip" to "silent", remove its directory from SEPARATE_GROUPS.
SEPARATE_GROUPS = [
"tests",
"tests/benchmarks",
"tests/compile/correctness_e2e",
"tests/config",
"tests/compile",
"tests/compile/fullgraph",
"tests/compile/fusions_e2e",
"tests/compile/passes",
"tests/distributed",
"tests/entrypoints/anthropic",
"tests/entrypoints/generate",
"tests/entrypoints/llm",
"tests/entrypoints/multimodal",
"tests/entrypoints/openai",
"tests/entrypoints/pooling",
"tests/entrypoints/serve",
"tests/entrypoints/speech_to_text",
"tests/entrypoints/tool_parsers",
"tests/entrypoints/unit_tests",
"tests/entrypoints/weight_transfer",
"tests/kernels",
"tests/kernels/attention",
"tests/kernels/core",
"tests/kernels/helion",
"tests/kernels/mamba",
"tests/kernels/moe",
"tests/kernels/quantization",
"tests/lora",
"tests/model_executor",
"tests/model_executor/layers",
"tests/model_executor/model_loader",
"tests/models",
"tests/models/test_initialization.py",
"tests/models/language",
"tests/models/multimodal",
"tests/models/quantization",
"tests/multimodal",
"tests/parser",
"tests/plugins_tests/gguf",
"tests/plugins_tests/lora_resolvers",
"tests/plugins/bge_m3_sparse_plugin",
"tests/plugins/prithvi_io_processor_plugin",
"tests/plugins/vllm_add_dummy_platform",
"tests/plugins/vllm_add_dummy_stat_logger",
"tests/plugins_tests",
"tests/quantization",
"tests/reasoning",
"tests/renderers",
"tests/samplers",
"tests/spec_decode",
"tests/tokenizers_",
"tests/tool_parsers",
"tests/tool_use",
"tests/transformers_utils",
"tests/utils_",
"tests/v1",
"tests/v1/attention",
"tests/v1/core",
"tests/v1/cudagraph",
"tests/v1/determinism",
"tests/v1/distributed",
"tests/v1/e2e",
"tests/v1/ec_connector",
"tests/v1/engine",
"tests/v1/executor",
"tests/v1/kv_connector",
"tests/v1/kv_offload",
"tests/v1/logits_processors",
"tests/v1/metrics",
"tests/v1/sample",
"tests/v1/shutdown",
"tests/v1/simple_kv_offload",
"tests/v1/spec_decode",
"tests/v1/streaming_input",
"tests/v1/structured_output",
"tests/v1/worker",
]
# TODO(woosuk): Include the code from Megatron and HuggingFace.
EXCLUDE = [
"vllm/model_executor/models",
"vllm/model_executor/layers/fla/ops",
]
def group_files(changed_files: list[str]) -> dict[str, list[str]]:
"""
Group changed files into different mypy calls.
Args:
changed_files: List of changed files.
Returns:
A dictionary mapping file group names to lists of changed files.
"""
exclude_pattern = re.compile(f"^{'|'.join(EXCLUDE)}.*")
file_groups = {"": []}
file_groups.update({k: [] for k in SEPARATE_GROUPS})
for changed_file in changed_files:
# Skip files which should be ignored completely
if exclude_pattern.match(changed_file):
continue
# Group files by mypy call
for directory in SEPARATE_GROUPS:
if re.match(f"^{directory}.*", changed_file):
file_groups[directory].append(changed_file)
break
else:
if changed_file.startswith(("vllm/", "tests/")):
file_groups[""].append(changed_file)
return file_groups
def mypy(
targets: list[str],
python_version: str | None,
follow_imports: str | None,
file_group: str,
) -> int:
"""
Run mypy on the given targets.
Args:
targets: List of files or directories to check.
python_version: Python version to use (e.g., "3.10") or None to use
the default mypy version.
follow_imports: Value for the --follow-imports option or None to use
the default mypy behavior.
file_group: The file group name for logging purposes.
Returns:
The return code from mypy.
"""
args = ["mypy"]
if python_version is not None:
args += ["--python-version", python_version]
if follow_imports is not None:
args += ["--follow-imports", follow_imports]
print(f"$ {' '.join(args)} {file_group}")
return subprocess.run(args + targets, check=False).returncode
def main():
python_version = sys.argv[1]
file_groups = group_files(sys.argv[2:])
if python_version == "local":
python_version = f"{sys.version_info.major}.{sys.version_info.minor}"
returncode = 0
for file_group, changed_files in file_groups.items():
follow_imports = None if file_group == "" else "skip"
if changed_files:
returncode |= mypy(
changed_files, python_version, follow_imports, file_group
)
return returncode
if __name__ == "__main__":
sys.exit(main())