内容提要
Ruff v0.0.283 发布,新增对 Python 3.12 PEP 695 类型参数语法的解析支持,并推出 UP040 规则自动转换类型别名。flake8-pyi 部分规则现适用于普通 .py 文件。默认目标 Python 版本改为 3.8。新增 PYI019、PYI051、PYI055 和 PLE1300 等规则,改进类型注解和格式化字符串检查。
延伸解读
PEP 695 支持与 UP040 规则
Ruff v0.0.283 新增对 Python 3.12 PEP 695 类型参数语法的解析支持,包括类型别名和泛型函数/类。同时引入 UP040 规则,可自动将旧式类型别名声明转换为新语法,但该规则仅在目标 Python 版本为 3.12+ 时启用。这有助于开发者平滑迁移到新语法,但需注意目标版本设置。
flake8-pyi 规则扩展至普通 .py 文件
此前 flake8-pyi 规则仅适用于 .pyi 类型存根文件,现在其中非存根特定的子集规则已启用,可在普通 .py 文件中检查类型注解误用。例如 PYI019、PYI051 等规则现在会作用于所有 Python 文件,帮助捕获类型注解问题。这扩大了 Ruff 的类型检查范围,但可能对现有代码产生新的告警。
默认目标 Python 版本变更
Ruff 的默认目标 Python 版本从 3.10 改为 3.8,以避免假设新特性的可用性。若未显式指定 target-python 或 project.requires-python,此变更可能引入破坏性影响,因为 Ruff 将基于更旧的版本进行规则检查。建议在配置中明确目标版本,以确保行为符合预期。
新增规则聚焦类型注解与格式化字符串
本次新增 PYI019、PYI051、PYI055 和 PLE1300 等规则。PYI019 建议用 typing.Self 替代自定义 TypeVar 返回类型,以改善子类类型推断;PYI051 和 PYI055 分别检查冗余的 Literal 联合和 type 联合;PLE1300 检查格式化字符串中的无效格式字符,避免运行时错误。这些规则有助于提升代码质量和类型安全。
Q&A
Ruff v0.0.283 新增了对 Python 3.12 的什么语法支持?
Ruff v0.0.283 新增了对 Python 3.12 PEP 695 类型参数语法的解析支持,包括新的类型别名声明和泛型类型参数语法。
UP040 规则有什么作用?启用条件是什么?
UP040 规则可以自动将类型别名声明转换为 PEP 695 的新语法,帮助过渡。该规则仅在目标 Python 版本为 3.12+ 时启用。
哪些 flake8-pyi 规则现在可以在普通 .py 文件中使用?
从 v0.0.283 开始,以下 flake8-pyi 规则现在会在所有 Python 文件中触发:PYI013、PYI016、PYI018、PYI019、PYI024、PYI025、PYI030、PYI032、PYI034、PYI036、PYI041、PYI042、PYI043、PYI045、PYI046、PYI047、PYI049、PYI050(Python ≥ 3.11)、PYI051、PYI056。
Ruff 默认的目标 Python 版本有什么变化?为什么?
默认目标 Python 版本从 3.10 改为 3.8。因为默认使用较旧的 Python 版本更安全,可以避免假设新特性的可用性。
PYI019 规则检查什么?为什么重要?
PYI019 规则检查方法是否使用自定义 TypeVar 作为返回类型注解,而不是使用 typing.Self。如果使用自定义 TypeVar,当类被继承时,类型检查器无法推断正确的返回类型。
PYI051 规则检查什么?为什么重要?
PYI051 规则检查联合类型中是否存在冗余的 Literal 类型和内置超类型。因为超类型比 Literal 类型更通用,联合是冗余的,例如 Literal["A"] | str 等价于 str。
PYI055 规则检查什么?为什么重要?
PYI055 规则检查联合类型中是否存在多个 type 使用。因为 type 内置函数接受联合类型,将其明确指定为单一类型更清晰,例如 type[int] | type[float] 应写成 type[int | float]。
PLE1300 规则检查什么?为什么重要?
PLE1300 规则检查格式化字符串中不支持的格式字符代码。无效的格式字符会在运行时导致错误,例如 "%z" % "1" 或 "{:z}".format("1") 会引发错误。