友情提醒:Ruff 是一个用 Rust 编写的、速度极快的 Python 代码检查工具。Ruff 可以替代 Flake8(及数十个插件)、isort、pydocstyle、pyupgrade 等工具,而且执行速度比任何单个工具都要快数十倍乃至数百倍。

Ruff 已被数万个开源项目以及大型企业用于生产环境。在过去一年中,我们一直致力于扩展 Ruff 的功能集,并提高其稳定性,以满足日常工作中依赖 Ruff 的用户需求。

今天,我们很高兴地宣布Ruff v0.1.0 已正式发布!本次发布专注于稳定性,并引入了全新的预览模式修复安全级别,以及一套正式的版本策略

请继续阅读以了解主要变更的讨论,查看本次发布中的100 多项变更,或者立即从PyPI 或您选择的包管理器安装 Ruff。

pip install --upgrade ruff

不断增长的功能集

今年早些时候,Charlie 回顾了Ruff 的前 200 个版本,当时它支持 376 条代码检查规则。Ruff 现在支持超过 700 条规则,并且每个版本都在不断添加新规则。如果您错过了,今年我们已经发布了一些令人兴奋的功能:

我们还发布了一个与 Black 兼容的代码格式化程序的 alpha 版本。预计很快会有更多相关消息!

引入预览模式

v0.0.289 版本中,我们添加了一个新的预览模式,以在使用 Ruff 时启用不稳定功能。

由于新规则通常需要一段试用期,我们希望能够分阶段发布它们。此前,我们使用了一个“孵化(nursery)”规则类别来实现这一点,这个概念借鉴自 Rust 的代码检查工具 Clippy。

然而,“孵化”机制要求用户使用精确的代码逐条选择启用每条规则,例如,如果您选择了 F 类别,而我们发布了一条不稳定的规则 F999,您就需要将您的选择更新为 [F, F999]。这种逐条选择的机制降低了新规则的曝光率,并且对用户来说更新起来可能很繁琐。此外,随着 Ruff 的发展,我们希望有一个全局的概念来使用不稳定功能——“孵化”概念无法扩展到规则选择之外。

预览模式将用于启用新规则、不稳定修复和实验性代码分析。发布这些功能,并将其限制给选择启用的用户,将使我们能够收集社区反馈,并确信这些变更是有益的。

预览模式可以通过每次调用时添加 --preview 标志或更新您的配置文件来启用。

[tool.ruff]
preview = true

查阅预览模式的文档并试用一下吧!

尊重修复安全性

Ruff 自动修复违规代码的能力是其最强大的功能之一。然而,考虑到 Python 的动态特性,并非总能保证修复是“安全”的。自五月以来,我们一直将 Ruff 的一部分修复标记为不安全。应用安全修复时,代码的含义和意图将保持不变;应用不安全修复时,含义可能会改变。

例如,unnecessary-iterable-allocation-for-first-element 是一条规则,用于检查 list(...)[0] 的潜在低效用法。此修复将这种模式替换为 next(iter(...)),这可以显著提高速度。

$ python -m timeit "head = list(range(99999999))[0]"
1 loop, best of 5: 1.69 sec per loop

$ python -m timeit "head = next(iter(range(99999999)))"
5000000 loops, best of 5: 70.8 nsec per loop

然而,当集合为空时,此修复会将引发的异常从 IndexError 更改为 StopIteration

$ python -c 'list(range(0))[0]'
Traceback (most recent call last):
File "<string>", line 1, in <module>
IndexError: list index out of range

$ python -c 'next(iter(range(0)))[0]'
Traceback (most recent call last):
File "<string>", line 1, in <module>
StopIteration

由于这可能会破坏错误处理,此修复被归类为不安全。

此前,修复的安全性仅是内部备注,但在 v0.1.0 版本中,Ruff 将默认仅使用安全修复,以增强应用修复时的信心,并突出显示需要额外审查的修复。

不安全修复可以通过将 --unsafe-fixes 标志传递给 ruff check 来启用。

# Show unsafe fixes
ruff check . --unsafe-fixes

# Apply unsafe fixes
ruff check . --fix --unsafe-fixes

或通过在配置文件中设置 unsafe-fixes 来启用。

[tool.ruff]
unsafe-fixes = true

当在 IDE 中使用 Ruff(通过我们的 LSP)时,我们将不再使用“全部修复(Fix all)”操作来应用不安全修复。相反,不安全修复可以通过“快速修复(Quick fix)”操作单独应用,从而允许对每个修复进行审查。如果您选择启用不安全修复,它们将在“全部修复”期间应用。更多详情请参阅 LSP 文档

可以通过 extend-safe-fixesextend-unsafe-fixes 设置,按规则调整修复的安全性,从而允许您根据自己的用例自定义安全级别。

有关修复安全性的更多详细信息,请参阅文档

Ruff 的版本策略

迄今为止,Ruff 的发布只涉及增加补丁版本号。这种版本方案存在一些核心问题:

  • 没有明确的文档化策略,也几乎没有制定有意义策略的空间
  • 大多数版本中都会添加新规则,导致用户在升级时出现大量新的违规
  • 用户无法确信在获取错误修复升级时无需进行其他额外工作
  • Ruff 被认为不稳定

随着升级到 v0.1.0,Ruff 可以采用一套有意义的版本规则,以确保用户了解每个版本的预期内容。通过引入次版本号,我们希望:

  • 减少大规模变更的频率
  • 在启用规则前给予其一段稳定期
  • 区分破坏性变更版本和非破坏性变更版本
  • 迈向更强的稳定性保证

随着 0.1.0 版本的发布,Ruff 包含了一套完整的版本策略。简而言之:

  • 次要版本将用于预览功能的稳定、稳定行为的变更以及破坏性变更。
  • 补丁版本将用于错误修复以及预览中规则或修复的任何变更。

有关该策略的完整说明,请查阅文档

Ruff 文档的新家

我们的文档已从 beta.ruff.rs/docs 迁移到 docs.astral.sh。我们很高兴能移除“测试版”标签,并将文档纳入我们不断发展的公司旗下。所有现有链接都将重定向到新域名,并且应继续正常工作。

感谢!

每天都有数千名社区成员访问我们的代码库,Ruff 令人难以置信的积极反馈持续激励着我们。与 282 位贡献者以及所有通过 Discord 或提交 Issue 等方式参与项目的人士共同构建这个项目,是我们的一项殊荣和乐趣。非常感谢所有参与这个出色社区的人。


GitHub 上查看完整的变更日志。

我们正在招聘!了解更多关于 Astral — Ruff 背后的公司。