DEBUG.WIKI
V.PS:让项目靠近用户,亚太、欧洲、北美 KVM VPS
IPPeak:从目标地区访问网页,住宅代理、SEO 监测、广告验证
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国

mypy 2.4 对 cast("None", x) 报 valid-type,核对 AST 序列化组件

mypy 2.4 的字符串类型序列化回归会误拒 cast("None", x)。在同一工具环境采用已修复的 ast-serialize,保留原代码并复查实际包版本。

原来能通过的 cast("None", x),升级 mypy 2.4.0 后报 Invalid type comment or annotation [valid-type],不一定是项目突然用了非法类型。这个最小例子涉及字符串类型解析中的一个遗漏分支:

from typing import Any, cast

def f(x: Any) -> None:
    return cast("None", x)

在相同代码上,mypy 2.3.1 可以通过,2.4.0 出现误报。原问题没有披露 Python、操作系统或当时具体安装的 ast-serialize 版本,因此不能根据版本号补出一个完整环境组合。

新解析组件处理字符串类型时,会先解析里面的表达式。"None" 得到的是 NoneLiteral 节点,不是普通名字。旧序列化路径没有把这个节点纳入字符串类型的合法分支,结果按原始表达式表示送给后续检查,而不是表达类型的 UnboundType("None")。

正式 ast-serialize 0.12.1 补上这个分支,同时保留原字符串及字符串回退类型信息。它与 mypy 2.4.0 声明的组件版本范围兼容。需要处理这条回归时,应在运行 mypy 的同一个工具环境中明确选择组件:

python -m pip install "mypy==2.4.0" "ast-serialize==0.12.1"
python -c "from importlib.metadata import version; print(version('mypy'), version('ast-serialize'))"
python -m mypy repro.py

把上面的 Python 例子保存为 repro.py 再运行。使用项目锁文件、独立工具环境或 CI 缓存时,也要同步这份选择;只升级另一个终端里的包,不能改变实际执行的解析器。已有约束若不允许所选组件,需要先整理兼容的工具依赖,而不是忽略解析冲突。

验收保留 cast("None", x) 原样,确认这条 valid-type 误报消失。随后检查项目原来的类型错误是否仍然报告。把所有相关行加上宽泛 type: ignore,会同时掩盖真正的注解问题,无法证明解析器已经恢复。

这里的 cast 是静态类型提示,不会在运行时把任意值变成 None,也不会检查值是否真的为空。修复解析并不保证函数输入满足应用语义;如果业务需要检查空值,应另写运行时判断。

这项补丁也不意味着任意字符串表达式都能作类型。若失败的是 cast(type(None), x)、未定义名字或不合法的类型表达式,应保留对应最小例单独分析。当前修补确认的是字符串 None 节点的序列化,不应把相近报错文案当成同一原因。