执行摘要
- 一句话:升级 mypy 至 1.20.2,简化 CI 配置
- 推荐动作:该 PR 适合所有开发者关注,尤其是对 pre-commit 速度敏感或参与 CI 配置的工程师。值得精读的点:my.py 脚本参数简化、pre-commit 钩子合并的模式,以及如何利用版本升级契机清理过时文档。对于日常开发影响较小,但体现了维护者对工具链质量的持续改进。
功能与动机
作者 Harry Mellor 在 PR body 中指出,本地 mypy 运行速度因版本升级和 import follow skipping 的移除而显著提升,同时 mypy 在 CI 和本地不再有不同的行为,因此需要更新脚本、文档和配置以反映这一变化。
实现拆解
-
升级 mypy 版本与依赖:在 .pre-commit-config.yaml 中,将所有 mypy 钩子的 additional_dependencies 从 "mypy[faster-cache]==1.19.1" 改为 "mypy==1.20.2",移除 faster-cache 可选依赖。
-
移除 ci 参数:在 tools/pre_commit/mypy.py 中,删除了 ci 命令行参数(原为 sys.argv[2]),脚本不再区分 CI/本地模式;同时更新了文档字符串和注释。
-
合并钩子配置:在 .pre-commit-config.yaml 中,删除了独立的 mypy-local 钩子(原用于本地),并使 mypy-3.10 同时覆盖本地和 CI(移除了 stages 限制),其他 Python 版本(3.11/3.12/3.13)的钩子也移除了 stages: [manual] 前的参数。
-
修复类型注解与 None 保护:针对 mypy 1.20.2 更严格的检查,在 vllm/model_executor/layers/fused_moe/experts/trtllm_mxint4_moe.py 中为 __init__ 新增了 max_num_tokens 和 num_dispatchers 参数(保持向后兼容);在 vllm/model_executor/model_loader/tensorizer.py 中将 **tensorizer_config.serialization_kwargs 改为 **(tensorizer_config.serialization_kwargs or {}) 以防止 None;在 tests/models/language/pooling/test_colbert.py 中为字典变量添加了显式类型注解。
-
清理 CI 文档:在 .github/mergify.yml 中移除了关于“mypy 在 CI 中运行方式不同”的过时提示。
-
其他文档调整:AGENTS.md 和 docs/contributing/README.md 修正了可能受 mypy 版本影响的文字或格式(具体变动极小)。
关键文件:
.pre-commit-config.yaml(模块 预提交配置;类别 config;类型 configuration): 核心配置文件,整合了 mypy 钩子,移除了过时的本地/CI 区分,升级了依赖版本,是本次变更的主要载体。
tools/pre_commit/mypy.py(模块 工具脚本;类别 source;类型 core-logic): 脚本核心,移除了 ci 参数,简化了调用接口,更新了文档注释。
.github/mergify.yml(模块 CI 配置;类别 infra;类型 infrastructure): 移除了过时的 mypy CI 提示,保持文档准确
vllm/model_executor/layers/fused_moe/experts/trtllm_mxint4_moe.py(模块 MoE 专家层;类别 source;类型 data-contract;符号 max_num_tokens, num_dispatchers): 为满足 mypy 1.20.2 的签名检查,新增可选参数,保持向前兼容
vllm/model_executor/model_loader/tensorizer.py(模块 模型序列化;类别 source;类型 data-contract;符号 serialize_vllm_model): 修复 mypy 检测到的 serialization_kwargs 可能为 None 的问题
tests/models/language/pooling/test_colbert.py(模块 ColBERT 测试;类别 test;类型 test-coverage;符号 COLBERT_MODELS): 添加缺失的类型注解以通过 mypy 检查
tests/compile/test_graph_partition.py(模块 图分区测试;类别 test;类型 test-coverage): 为 mypy 新版本添加导入(可能),属于测试配套调整
AGENTS.md(模块 文档;类别 docs;类型 documentation): 文档小修正
docs/contributing/README.md(模块 贡献文档;类别 docs;类型 documentation): 文档小修正
关键符号:main, group_files, mypy
关键源码片段
.pre-commit-config.yaml
核心配置文件,整合了 mypy 钩子,移除了过时的本地/CI 区分,升级了依赖版本,是本次变更的主要载体。
# 预提交配置文件:merge 了本地和 CI 的 mypy 钩子
# 移除了独立的 mypy-local 条目,将 mypy-3.10 同时用于本地 pre-commit
- id: mypy-3.10 # 适用于 Python 3.10
name: Run mypy for Python 3.10
# entry 不再传 ci 参数(原为 "0" 或 "1")
entry: python tools/pre_commit/mypy.py "3.10"
language: python
types_or: [python, pyi]
require_serial: true
# mypy 版本从 1.19.1 升至 1.20.2,移除 faster-cache 可选依赖
additional_dependencies: ["mypy==1.20.2", regex, types-cachetools, types-setuptools, types-PyYAML, types-requests, types-torch, pydantic]
tools/pre_commit/mypy.py
脚本核心,移除了 ci 参数,简化了调用接口,更新了文档注释。
# 工具脚本:运行 mypy 检查变更文件
# 移除了 ci 参数,因为本地和 CI 行为现已一致
# 现在直接通过 sys.argv[1] 获取 python_version
import subprocess
import sys
import regex as re
SEPARATE_GROUPS = ["tests", "vllm/lora"]
EXCLUDE = [
"vllm/model_executor/models",
"vllm/model_executor/layers/fla/ops",
"vllm/benchmarks",
]
def group_files(changed_files: list[str]) -> dict[str, list[str]]:
# 原有分组逻辑不变,此处省略具体实现
return {}
def mypy(
targets: list[str],
python_version: str | None,
follow_imports: str | None,
file_group: str,
) -> int:
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():
# 变更:使用 sys.argv[1] 作为 python_version(Originally was sys.argv[2])
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())
评论区精华
该 PR 未引发实质性讨论。两位维护者(DarkLight1337、Isotr0py)直接审批通过。Claude bot 自动评论了但未触发审核。
风险与影响
- 风险:兼容性风险低:mypy 1.20.2 为小版本升级,破坏性变更极微。PR 中已修复了已知类型警告(如 None 传播、参数缺失)。开发者本地的 pre-commit 环境会根据
.pre-commit-config.yaml 自动拉取新版本,无需手动干预。潜在问题:若有人直接调用 tools/pre_commit/mypy.py 脚本并传入旧的 ci 参数,脚本会因参数位置偏移出错(但 pre-commit 调用的 entry 均已更新,外部直接调用概率低)。性能影响:仅影响开发/CI 阶段的静态检查,对生产无影响。
- 影响:开发者:本地 pre-commit mypy 检查速度提升约 27%,体验更好;不再需要区分 CI 和本地环境,配置统一。CI 系统:CI mypy 步骤因版本升级可能略有提速,且不再有特殊行为(如
--follow-imports silent 仅用于 CI 的逻辑已被移除)。代码质量:类型注解更严格,部分代码通过显式处理 None 和添加参数签名提升了可维护性。影响范围限于开发工具链。
- 风险标记:预提交配置简化, mypy 版本升级, 参数位置调用风险(低)
关联脉络
参与讨论