深入解析 Ruff 的版本管理策略:自定义版本方案、Preview 模式与稳定化机制
2026/9/12 2:30:44 网站建设 项目流程

深入解析 Ruff 的版本管理策略:自定义版本方案、Preview 模式与稳定化机制

【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff

导读

Ruff 是一款用 Rust 编写的极速 Python 静态检查工具(linter)与代码格式化工具(formatter)。在其 API 尚未稳定之前,Ruff 采用了一套自定义的版本方案:用minor 版本号承载破坏性变更、用patch 版本号承载 bug 修复,并配套 Preview(预览)模式、规则与修复的稳定化流程,以及一套服务于 VS Code 扩展的独立版本区分规则。本文以仓库官方文档 docs/versioning.md 为骨架,结合源码逐一拆解这套版本策略的每一项约定,帮助你准确判断某个升级是否可能破坏现有配置、理解新规则与新修复的引入节奏,以及正确使用 preview 模式参与社区反馈。


一、总体设计:为什么 Ruff 不直接使用语义化版本

Ruff 目前采用自定义版本方案,核心约定是:

  • minor(次版本号):用于引入破坏性变更(breaking changes);
  • patch(修订号):用于修复 bug和向后兼容的增量改进;
  • major(主版本号):尚未使用。Ruff 目前没有稳定的 API,一旦 API 稳定,将切换到完整的语义化版本(SemVer)方案。

也就是说,在当前阶段,0.x.y中的x(minor)承担了传统语义化版本中 major 的角色——升级 minor 版本时应当预期可能发生破坏性变化,而升级 patch 版本通常可以安全进行。

二、Crate 版本策略:哪些 crate 遵循正常策略

Ruff 以 Cargo workspace 形式组织代码(见 Cargo.toml 中的[workspace][workspace.dependencies]配置),各 crate 独立发布。根据官方策略,只有以下三个 crate 遵循 Ruff 的正常版本策略:

  • ruff(对应 crates/ruff)
  • ruff_linter(对应 crates/ruff_linter)
  • ruff_wasm(对应 crates/ruff_wasm)

需要特别注意:即使这三个 crate 遵循正常版本号,其 Rust 接口也遵循语义化版本。也就是说,依赖这些 crate 的 Rust 程序,无法通过版本号判断 API 是否兼容。

其余随 Ruff 一起发布的 crate(如ruff_python_parserruff_python_astruff_python_formatterruff_diagnosticsruff_text_size等)不提供任何稳定性保证

  • 它们的 Rust 接口被视为内部实现、不稳定;
  • 它们统一以0.0.x版本发布;
  • 每发布一次 Ruff 版本,这些 crate 的 patch 号就递增一次,无论 crate 本身是否有任何改动

在 Cargo.toml 的[workspace.dependencies]中可以观察到这一现象:当前仓库中ruffruff_linter的版本为0.16.6,而ruff_cacheruff_dbruff_diagnosticsruff_python_parser等大量内部 crate 均为0.0.12

三、Minor 版本:何时会发生破坏性变更

官方明确列出,以下情况将触发minor 版本号提升

  1. 移除某个已废弃(deprecated)的选项或特性;
  2. 配置发生向后不兼容的变化——文档特别说明:在1.0.0之前,这类变更"可能"出现在 minor 版本中,但一般应尽量避免;
  3. 对某类新文件类型的支持被提升为稳定(stable);
  4. 停止支持某个已进入生命周期终点(EOL)的 Python 版本;
  5. Linter 相关:
    • 某条规则被提升为稳定;
    • 某条稳定规则的行为被改变,包括:
      • 稳定规则的作用范围被显著扩大;
      • 规则的意图(intent)发生变化;
      • 注意:遵循规则原始意图的 bug 修复不属于此类;
    • 稳定规则被加入默认启用集合(default set);
    • 稳定规则被从默认启用集合中移除;
    • 某条规则的 safe fix 被提升为稳定;
    • 某条规则被废弃(deprecated);
  6. Formatter 相关:
    • 稳定格式化风格(stable style)发生变化;
  7. Language server 相关:
    • 移除某个已有能力(capability);
    • 移除某个已废弃的 server 设置。

简而言之:升级 minor 版本前,务必阅读 changelog 与迁移指南。仓库根目录的 BREAKING_CHANGES.md 以及 CHANGELOG.md、changelogs 目录下的分版本 changelog(如 0.16.x 等各系列)都可用于核对每个版本的实际变更。

四、Patch 版本:哪些变化是安全的

以下情况触发patch 版本号提升,这类升级通常不会破坏既有配置:

  1. 修复 bug,包括为修复 bug 而改变行为(这类"行为修正"被明确允许在 patch 中发生);
  2. 以向后兼容的方式新增配置选项(不产生格式化变化,也不产生新的 lint 错误);
  3. 新增对某个 Python 版本的支持;
  4. 在 preview 模式下新增对某类文件类型的支持;
  5. 废弃(deprecate)某个选项或特性(注意:废弃与移除不同,移除属于 minor 变更);
  6. Linter 相关:
    • 为规则新增 unsafe fix;
    • 在 preview 模式下为规则新增 safe fix;
    • 在 preview 模式下扩大规则的作用范围;
    • 降低某个 fix 的适用性(applicability);
    • 在 preview 模式下新增规则;
    • 改变某条 preview 规则的行为;
  7. Formatter 相关:
    • 稳定风格发生变化,但仅限于修复以下问题:防止生成无效语法、改变程序语义,或删除注释;
    • preview 风格发生变化;
  8. Language server 相关:
    • 新增对某个新能力的支持;
    • 新增 server 设置;
    • 废弃某个 server 设置。

由此可见,patch 升级中"行为变化"的空间被严格限定:要么是 bug 修复,要么是 preview 模式下的实验性调整,要么是保证语义等价与注释安全的格式化修正。这与第一节的总体设计完全一致。

五、最低支持的 Rust 版本(MSRV)

编译 Ruff 所需的最低 Rust 版本(MSRV)记录在仓库根目录 Cargo.toml 的[workspace.package]段落的rust-version键中,该值可能在任意一次发布(minor 或 patch)中变化。当前仓库中该值为:

[workspace.package] edition = "2024" rust-version = "1.96"

官方对 MSRV 的约束是:永远不会比最新稳定 Rust 版本新出超过 2 个版本。即如果最新稳定 Rust 是1.85,则 Ruff 的 MSRV 至多为1.83(公式:MSRV ≤ N-2,N 为最新稳定版本)。

这一点只对从源码构建 Ruff 的用户有意义。从 Python 包索引(PyPI)安装 Ruff 通常安装的是预编译二进制,不需要本机编译 Rust。因此普通用户一般无需关注 MSRV;只有自行执行cargo build --release等源码构建流程时,才需要确保本机 Rust 工具链版本满足要求。Rust 工具链版本由仓库根目录的 rust-toolchain.toml 约束。

六、Preview 模式:提前体验不稳定能力

6.1 设计意图

Ruff 提供了preview(预览)模式,用于启用新的、尚未稳定的规则与特性(例如对某类新文件类型的支持)。官方文档明确了 preview 模式的两个定位:

  • 目的:收集社区反馈,确认改动是净收益(net-benefit);
  • 定位边界:它不是用来限制"未完成的工作"或"我们很可能移除的特性"。

但官方同时保留了重要权利:可以更改任何由 preview 模式门控的行为,包括直接移除 preview 特性或规则。这意味着 preview 模式下的任何规则、修复或风格都不具备稳定性承诺,升级时可能随时变动。

6.2 配置入口与源码实现

在配置中,preview是一个布尔开关。从 crates/ruff_workspace/src/configuration.rs 的源码可以看到:

  • 配置解析后映射到PreviewMode枚举(定义于 crates/ruff_linter/src/settings/types.rs),取值为Enabled/Disabled
  • preview既可以在全局层级配置(self.preview),也可以在lintformatanalyze等子配置块中单独覆盖,子配置未设置时回退到全局值(如lint.preview.unwrap_or(global_preview));
  • 全局 preview 开启时,还会联动影响文件包含/排除模式的默认集合(INCLUDE_PREVIEW),并在规则表解析、格式化器 preview 风格、analyze 的 preview 行为等多个环节生效。

典型的启用方式(以pyproject.toml为例):

[tool.ruff] preview = true

若只想让 linter 或 formatter 单独启用预览,可以分别在对应子块设置:

[tool.ruff.lint] preview = true [tool.ruff.format] preview = true

此外,源码中大量以is_*_enabled(settings)命名的辅助函数(见 crates/ruff_linter/src/preview.rs)为每条具体规则独立判断 preview 是否生效。该文件的文档注释说明了一个设计巧思:这些命名函数便于在规则从 preview 提升到 stable 时直接删除函数,然后让 Rust 编译器指出所有需要清理的调用点。

七、规则稳定化(Rule Stabilization)流程

官方对新规则与既有规则的处理,遵循以下指导原则:

  1. 新规则必须先在 preview 模式下引入
  2. 新规则至少要在 preview 模式中停留一个 minor 版本,才能被提升为 stable。文档给出的关键示例:
    • 若规则在 patch 版本0.6.1加入,则最早要到0.8.0才具备稳定化资格(因为0.6.1的下一个 minor 是0.7.0,而0.6.1所在 minor 序列的"下一 minor"计数规则要求跳过0.7.0直接看0.8.0);
  3. 稳定规则的行为不应在 patch 版本中被显著改变
  4. 规则的稳定化可能被延迟,以便将多条规则"打包"进同一次 minor 发布(批量提升);
  5. 并非所有 preview 规则都必须在某次 minor 发布中完成提升。

这套流程解释了为什么 Ruff 的 changelog 中经常出现"将若干规则从 preview 提升为 stable"的批量条目——这正是第 4 条策略的体现。结合上一节的 preview 机制,规则的生命周期可以概括为:新增(preview)→ 至少一个 minor 版本观察 → (可批量)提升为 stable

八、修复稳定化(Fix Stabilization):三级适用性

Ruff 的自动修复(fix)分为三个适用性级别:

级别含义何时应用
Display(显示)永不应用,仅展示给用户仅作为提示展示
Unsafe(不安全)需要用户显式选择加入后才应用可能不是用户本意,或可能改变运行时行为 / 删除注释
Safe(安全)可以自动应用确定符合用户意图,或保持代码语义不变

这套模型在源码中有精确对应:Applicability枚举定义于 crates/ruff_diagnostics/src/fix.rs(第 14–32 行),三个变体DisplayOnlyUnsafeSafe的文档注释与上表语义一致,并且Fix::applies通过self.applicability >= applicability的比较来决定某级别下该修复是否生效。

关于修复稳定化的版本约定:

  • 修复可以以较低适用性引入,随后提升到更高适用性(如 Unsafe → Safe);
  • 降低某个修复的适用性不构成破坏性变更(因此出现在 patch 升级的合法变更清单中);
  • 某个修复的适用性可能因preview 模式开启与否而变化。

对照第三节、第四节的清单可以看到:为规则新增 unsafe fix、在 preview 下新增 safe fix、降低 fix 适用性都属于 patch 变更;而将某个 safe fix 提升为 stable 则属于 minor 变更。

九、VS Code 扩展的特殊版本方案

VS Code 官方对扩展的 pre-release(预发布)支持存在限制(具体见 VS Code 扩展发布文档中关于 prerelease extensions 的说明)。为了在不依赖 pre-release 标签的情况下区分稳定版与预览版,Ruff 采用了"偶数/奇数 minor 版本号"方案:

  • 稳定版:minor 版本号使用偶数,例如2024.30.02024.32.02024.34.0……;
  • 预览版:minor 版本号使用奇数,例如2024.31.02024.33.02024.35.0……。

这与 Ruff 主程序0.x.y的版本号体系相互独立,仅用于 VS Code 扩展的发布渠道管理。对于希望在 VS Code 中优先体验新规则/新特性的用户,可以选择奇数 minor 的扩展版本。

十、实践要点小结

结合本文的全部约定,面向不同角色的使用建议可以归纳为:

  1. 普通用户(通过 pip/uv/Homebrew 等安装预编译包)

    • 升级patch版本通常安全,但仍建议阅读 changelog,因为"修复 bug 的行为变化"被允许在 patch 中发生;
    • 升级minor版本前,重点核对 BREAKING_CHANGES.md 与对应版本的 changelogs,确认是否存在配置变更、稳定规则行为改变或 EOL Python 版本停止支持等破坏性变更;
    • 不需要关心 MSRV,除非从源码自行编译。
  2. 希望提前验证新规则的开发者:在配置中开启preview = true,但需要接受 preview 规则/行为随时可能变动甚至被移除的事实,不要将其作为长期依赖。

  3. 规则与修复的贡献者:新规则一律从 preview 引入;修复按 Display → Unsafe → Safe 的适用性阶梯推进,Safe 的提升属于 minor 变更;规则稳定化至少等待一个 minor 版本并可批量进行。

  4. VS Code 用户:偶数 minor 为稳定渠道、奇数 minor 为预览渠道,按需选择。

通过理解这套版本约定,你就能把 Ruff 的每次升级风险控制在可预期的范围内,并充分利用 preview 模式参与到新特性的反馈与验证中。


参考文档与源码路径

  • 本文主体依据:docs/versioning.md
  • MSRV 定义:Cargo.toml([workspace.package].rust-version,当前为1.96
  • 版本号信息生成:crates/ruff/src/version.rs(VersionInfo与 git 提交信息格式化)
  • Preview 配置解析:crates/ruff_workspace/src/configuration.rs、crates/ruff_linter/src/settings/types.rs
  • Preview 门控辅助函数:crates/ruff_linter/src/preview.rs
  • Fix 适用性枚举:crates/ruff_diagnostics/src/fix.rs
  • 历史变更记录:CHANGELOG.md、changelogs、BREAKING_CHANGES.md

【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询