友情提醒: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 条规则,并且每个版本都在不断添加新规则。如果您错过了,今年我们已经发布了一些令人兴奋的功能:
- 支持 Jupyter notebook
- 支持 Python 3.12 f-string 语法
- 支持 Python 3.12 类型别名和泛型语法
- 词法分析器性能提升 2-3 倍
- Ruff playground 的改进
我们还发布了一个与 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-fixes
和 extend-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 上查看完整的变更日志。