Ruff v0.12.0 现已发布!您可以从 PyPI,或者使用您选择的包管理器安装。

uv tool install ruff@latest

提醒一下:Ruff 是一个用 Rust 编写的极速 Python linter 和格式化工具。Ruff 可以替代 Black、Flake8(以及数十个插件)、isort、pydocstyle、pyupgrade 等工具,同时其执行速度比任何单个工具快数十甚至数百倍。

迁移到 v0.12

与大多数 Ruff 次要版本一样,v0.12 仅包含少量破坏性更改。大多数用户应该会顺利升级,无需更改其代码或配置。尽管如此,仍有一些更重要的更改值得详细介绍。

改进的语法错误检测

Ruff 现在除了能检测早期版本报告的解析错误外,还能检测 CPython 报告的另外两类语法错误。

Ruff 一直能够检测阻止解析的无效 Python 语法,例如不匹配的引号或缺失的冒号。然而,CPython 报告了另外两类语法错误:版本相关的语法错误,以及在 CPython 编译 Python 的不同阶段发出的语法错误。我们将依次介绍这些错误。

版本相关语法错误

顾名思义,这些语法错误与 Python 版本之间的语法变化有关。这些错误的常见例子包括在 Python 3.10 之前使用 match 语句或在 3.8 之前使用赋值表达式 (:=,即“海象运算符”)。Ruff 的解析器现在已具备版本感知能力,如果您使用了当前 Python 版本中不可用的任何语法,它将发出诊断信息。(有关 Ruff 如何尝试确定您当前 Python 版本的详细信息,请参阅我们的文档。)

您可以在跟踪问题中找到这些语法错误的完整列表。

如果您的项目不同部分支持不同的 Python 版本,您可以使用 per-file-target-version 设置覆盖全局目标版本。例如,如果您的项目根目录下有一个开发者 scripts/ 目录,您可以添加:

[per-file-target-version]
"scripts/*.py" = "py312"

到您的 ruff.toml 或等效的 tool.ruff.per-file-target-version 到您的 pyproject.toml

Python 编译器发出的语法错误

CPython 报告的下一类语法错误有所不同。这些错误并非由 Python(或 Ruff)解析器发出,而是由 CPython 的字节码编译器检测和报告。它们涵盖了广泛的错误,包括:

  • 不可反驳的 match 模式
    match 42:
        case x: ...  # SyntaxError: name capture 'x' makes remaining patterns unreachable
        case y: ...
  • 重复的函数参数名
    def foo(x, x): ...  # SyntaxError: duplicate argument 'x' in function definition
  • 函数外部的 yieldreturn
    yield 1   # SyntaxError: 'yield' outside function
    return 1  # SyntaxError: 'return' outside function

等等,您同样可以在跟踪问题中找到更多详情。

更好的默认 Python 版本处理

Ruff 在检查上一节中的语法错误时,将默认使用最新支持的 Python 版本,以减少对未配置 Python 版本的项目的干扰。

默认情况下,Ruff 会尝试从可用的配置文件中推断项目的目标 Python 版本,如文档的配置文件发现部分所述。如果未能发现 Python 版本,并且未通过其他方式(例如 --target-version CLI 选项)提供版本,Ruff 通常会回退到其支持的最旧 Python 版本,目前是 Python 3.9。这避免了像 pyupgrade (UP) 这样的规则出现误报,因为这些规则只在较新的 Python 版本上有效。然而,如果在解析 Python 时默认使用 3.9,则意味着会对 match 语句或 PEP-695 泛型等常见的新语法发出语法错误。在 v0.12 中,当未配置 Python 版本时,Ruff 对这些情况有两种独立的默认值:检测语法错误时使用“最新”版本 (3.13),而其他所有情况则使用“最旧”版本 (3.9)。

与早期版本中已有的默认行为类似,这个新的语法错误默认设置旨在优先减少误报,而不是捕捉所有问题。如果您想利用新的语法错误检测功能,请确保您的目标 Python 版本配置正确。

rust-toolchain.toml 不再包含在源代码分发中

Ruff 使用 rust-toolchain.toml 文件来指定用于开发和生成发布二进制文件的最新稳定 Rust 版本(目前为 1.87)。然而,根据我们的最低支持 Rust 版本 (MSRV) 策略,Ruff 也支持使用至少前两个稳定 Rust 版本(本例中为 1.85 和 1.86)进行构建。在之前的版本中,rust-toolchain.toml 文件被包含在源代码归档中。这导致源代码分发的用户会使用(并可能下载和安装)最新的稳定 Rust 版本进行构建,即使他们已有的工具链与 Ruff 的 MSRV 兼容。

这项更改不应影响大多数 Ruff 最终用户,但应该使从源代码构建 Ruff 变得更容易,尤其是在可用 Rust 工具链存在安全或其他限制的情况下。需要注意的是,如果您不在受限环境中,这也意味着 cargo 不会自动安装兼容的 Rust 工具链。在这种情况下,您可能需要运行类似以下的命令

rustup install 1.85

以获取 MSRV 兼容的工具链。

更新的 f-string 格式化

由于 CPython 语法发生变化,Ruff 现在以不同方式格式化带有格式说明符的多行 f-string。之前,Ruff 可以像这样格式化插值表达式:

f"This is some long string {
    x:d
} that is formatted across multiple lines"

然而,在 Python 3.13.4 及更高版本中,:d 格式说明符后面的换行符现在是一个语法错误。因此,Ruff 现在将 f-string 格式化为:

f"This is some long string {
    x:d} that is formatted across multiple lines"

规则稳定化

以下规则已稳定,不再处于预览模式

其他行为稳定化

本次发布还稳定了一些以前只在预览模式中可用的额外行为:

规则弃用

以下规则已被弃用,并将在未来版本中移除:

  • pandas-df-variable-name 已被弃用,因为它过于主观,并且在启用其他 PD 规则时并非总是可取。

规则移除

  • suspicious-xmle-tree-usage (S320) 已移除。它在 v0.10 中被弃用,因为其检查的 lxml 包中的问题已经解决。

有关其他较小的更改,请参阅 GitHub 上的完整更新日志。

感谢!

感谢所有对 Ruff 预览模式中包含的更改提供反馈的人,特别是我们的贡献者。与您一起构建 Ruff 是我们的荣幸!


GitHub 上查看完整更新日志。

了解更多关于 Astral — Ruff 背后的公司。

感谢 Micha Reiser 和 Alex Waygood 对本博客文章的贡献。