Ruff 的版本号规则怎么理解:minor 版本引入哪些不兼容变更
【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff
如果你把项目的 Ruff 从0.15.x升到0.16.0,发现 lint 结果和之前不一样,先别急着回滚:Ruff 不是按语义化版本(semver)发布的。它的minor 版本号专门用来承载不兼容变更,patch 版本只修 bug。理解这条规则后,升级前的判断路径就清楚了:minor 版本要逐条核对变更说明,patch 版本一般可以放心跟随。
Ruff 目前还没有稳定 API;官方文档明确说明,等 API 稳定后会改用 major 版本号加语义化版本。在这之前,以下规则就是判断"这个版本升级会不会影响我"的依据(见 docs/versioning.md)。
Ruff 的版本号怎么分
Ruff 使用自定义的版本号方案:
- minor 版本(
0.x.0的x):用于不兼容变更,如移除已弃用的选项、配置语义变化、规则行为变化、稳定格式风格变化等。 - patch 版本(
0.x.y的y):用于 bug 修复,包括那些会改变行为的 bug 修复。 - major 版本:目前不使用。API 稳定后才启用 semver。
另外,Ruff 以0.0.x版本发布的其余 crate 没有任何稳定性保证,它们的 Rust 接口被视为内部实现,每次发布都会递增 patch 版本。而ruff、ruff_linter、ruff_wasm三个 crate 跟随 Ruff 的正常版本策略,但它们的 Rust 接口同样不遵循语义化版本。也就是说,如果你把 Ruff 当 Rust 依赖用,不能按 semver 的预期来依赖这些接口。
minor 版本会引入哪些不兼容变更
docs/versioning.md 给出的 minor 版本变更清单如下,这也是你升级 minor 版本前应该逐条对照的内容:
- 已弃用的选项或功能被移除;
- 配置以向后不兼容的方式变化(文档说明:在
1.0.0之前这类变更可能出现在 minor 版本中,但通常会尽量避免); - 新文件类型的支持从 preview 转为稳定;
- 放弃对某个已 EOL 的 Python 版本的支持;
- Linter 侧:
- 规则从 preview 提升为稳定;
- 稳定规则的行为发生变化(包括稳定规则的适用范围显著扩大、规则意图变化,但不包括遵循原意图的 bug 修复);
- 稳定规则被加入或移出默认规则集;
- 某条规则的 safe fix 被提升为稳定;
- 规则被弃用;
- Formatter 侧:稳定格式风格(stable style)发生变化;
- Language server 侧:已有能力被移除、已弃用的 server 设置被移除。
对照来看,以下情况只会出现在patch 版本中,不会造成上面的破坏:bug 修复(包括修复 bug 带来的行为变化)、向后兼容的新配置项、新增 Python 版本支持、新文件类型进入 preview、选项或功能被弃用(注意:弃用本身是 patch,移除是 minor)、preview 规则的增删改、preview 样式变化,以及 language server 新增能力或设置。
一个容易踩坑的细节:修复的适用级别(fix applicability)只有三级——Display(仅展示不应用)、Unsafe(需显式 opt-in 才应用)、Safe(自动应用)。降低某个修复的适用级别不算破坏性变更,所以你在 minor 或 patch 版本里都可能遇到"某条修复不再自动应用"的情况,这在版本规则上是被允许的。
preview 规则与稳定化节奏:为什么变化集中在 minor 版本
docs/versioning.md 的 "Rule stabilization" 一节解释了变更节奏:
- 新规则一律先进 preview 模式;
- 新规则至少在 preview 中停留一个 minor 发布后才可能被提升为稳定(文档举例:如果某规则在 patch 版本
0.6.1中加入,则到0.8.0之前不具备稳定资格,注意这里跨过了0.7.0); - 稳定规则的行为不会在 patch 版本中发生重大变化;
- 规则提升为稳定可能会被刻意"攒"到同一个 minor 版本里批量发布,也不是所有 preview 规则都会在同一个 minor 版本中被提升。
因此"规则被提升为稳定"这一类破坏性变更只会落在 minor 版本上,且往往一次集中出现。preview 模式本身的边界也要清楚(见 docs/preview.md):Ruff 保留对任何 preview 门禁行为做修改的权利,包括直接移除 preview 功能或规则。preview 模式可以通过--preview标志或配置文件中preview = true开启,且 lint 和 format 可以分别配置,例如:
[tool.ruff.lint] preview = true开启 preview 后,若希望逐条显式选择 preview 规则而不是按前缀整类启用,可以加上explicit-preview-rules = true。另外,在 preview 模式下被弃用的规则会被禁用,若你在配置中显式选择了某个已弃用规则,会直接报错——这是升级后配置可能失效的一个具体信号。
真实例子:最近几个 minor 版本改了什么
仓库根目录的 BREAKING_CHANGES.md 按版本记录了每次 minor 版本的不兼容变更。挑选几个有代表性的条目,帮助你对号入座:
0.16.0
- 默认规则集大幅扩大:默认启用的规则从 59 条增加到 413 条,同时移除了其中 18 条争议较大的
E/F规则(E401、E402、E701、E702、E703、E711、E712、E713、E714、E721、E731、E741、E742、E743、F403、F405、F406、F722); - Markdown 文件中的 Python 代码块默认参与格式化;
check和format --check的输出中开始展示修复 diff;format --check支持与 linter 相同的输出格式(如github、gitlab);- JSON 输出中的
filename、location等字段可能为null而不是空字符串——如果你的 CI 在解析 JSON 输出,这是要重点核对的一条。
0.15.0
- formatter 改为按 2026 style guide 输出;
- linter 支持块级抑制注释(
# ruff: disable[N803]/# ruff: enable[N803]); ppc64(64 位大端 PowerPC)二进制不再随发布包提供。
0.14.0
- 未显式配置 Python 版本时,默认目标版本从 3.9 变为 3.10;
- 未配置 Python 版本时做语法错误检查,默认使用最新受支持版本(3.14),而应用 lint 规则时仍按最低受支持版本处理。
0.13.0
- first-party import 判定改为校验完整模块路径在磁盘上存在;
- 已弃用规则必须用精确规则代码选择,不再能通过分组名或前缀激活;
- macOS 上
~/Library/Application Support/ruff/ruff.toml的用户级配置回退路径被移除(该回退自 v0.5 起弃用,XDG 路径~/.config/ruff/ruff.toml继续有效); - 规则
PD901和UP038被移除。
更早的版本还有类似模式:0.9.0 采用 2025 style guide(文档示例);0.8.0 默认 Python 从 3.8 改为 3.9、standalone 安装脚本改为安装到 XDG 目录($XDG_BIN_HOME、$XDG_DATA_HOME/../bin或~/.local/bin,按此顺序);0.7.0 移除了lint.allow-unused-imports设置(改用lint.pyflakes.allow-unused-imports)。这些条目覆盖了"默认值变化、配置项移除、规则移除、安装行为变化"四类最常见的破坏点,升级时按同类思路排查即可。
升级时如何核对版本与验证结果
以下是文档中实际出现的检查方式,可以组成一条连续的验证路径:
确认当前版本。
ruff --version(等价于-V,CLI 帮助中列为Print version)打印当前版本。docs/integrations.md 的 GitLab CI 配置就是把ruff --version放在before_script中,作为流水线的第一步:ruff --version对照变更清单。打开 BREAKING_CHANGES.md,定位你即将升到的那个 minor 版本(如
## 0.16.0)的条目,逐条判断是否命中你的项目:是否用了默认规则集、是否依赖 JSON 输出的固定字段、是否配置了目标 Python 版本、是否解析format --check的退出码等。跑一遍检查与格式核对。
format --check只报告不修改文件,适合在升级前建立基线:ruff format --check .0.16.0 起该命令会直接展示修复 diff(文档示例,实际内容以你的项目为准):
❯ ruff format --check . unformatted: File would be reformatted --> try.md:1:1 | 1 | ```python - import math 2 + import math 3 | ``` | 1 file would be reformatted需要只格式化而不改代码时,
ruff format --diff(docs/integrations.md 中的 CI 示例用法)同样适合做只读对比。验证配置没有被破坏。若你的
pyproject.toml或ruff.toml中引用了被移除的选项(如 0.1.0 移除的format输出格式设置、0.7.0 移除的lint.allow-unused-imports)或在 preview 下显式选择了已弃用规则,运行ruff check时会直接报错,而不是静默忽略。报错信息指出的配置项就是需要清理的位置。
两个版本相关的边界
- 从源码编译时的 MSRV:编译 Ruff 所需的最低 Rust 版本写在 Cargo.toml 的
[workspace.package]段的rust-version键中(当前为1.96)。该值可能在任意发布(minor 或 patch)中变化,但文档承诺它永远不会比最新稳定版 Rust 新超过 N-2 个版本(例如最新稳定版是 1.85 时,最低支持版本至多 1.83)。这仅影响从源码构建的用户;通过 Python 包索引安装通常拿到的是预编译二进制,不需要 Rust 工具链。 - VS Code 扩展的版本号:由于 VS Code 不支持扩展的 pre-release 标签,Ruff 扩展用 minor 位的奇偶区分发布通道:偶数为稳定版(
2024.30.0、2024.32.0、2024.34.0),奇数为 preview 版(2024.31.0、2024.33.0、2024.35.0)。如果你通过扩展间接使用 Ruff,扩展版本的奇偶决定了你拿到的是稳定还是 preview 行为。
综合来看,处理 Ruff 版本兼容性的操作路径是固定的:用ruff --version确认当前版本,到 BREAKING_CHANGES.md 查目标 minor 版本的条目,评估每条变更是否命中你的配置、默认规则集用法或输出解析逻辑,再用ruff format --check ./ruff check做只读验证。patch 版本升级不需要这套流程,但要注意"修复 bug 带来的行为变化"也属于 patch 版本范畴这一条,当某次 patch 升级后结果变化时,先查 CHANGELOG.md 对应版本条目。
【免费下载链接】ruffAn extremely fast Python linter and code formatter, written in Rust.项目地址: https://gitcode.com/GitHub_Trending/ru/ruff
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考