Ruff v0.2.0 现已发布!您可以通过 PyPI 或您选择的包管理器进行安装
pip install --upgrade ruff
提醒:Ruff 是一个用 Rust 编写的超快速 Python 代码检查工具和格式化工具。 Ruff 可以替代 Black、Flake8(以及数十个插件)、isort、pydocstyle、pyupgrade 等工具,同时执行速度比任何单个工具快数十倍甚至数百倍。
回溯到 2023 年 10 月,我们发布了 Ruff v0.1.0,引入了新的版本策略和用于限制新功能的预览模式。自那时起,我们新增了 100 多条规则,这些规则仅对选择启用预览功能的用户开放。感谢所有就这些新规则的行为向我们提供反馈的用户——这些反馈对于我们确定稳定化方案至关重要。我们很高兴能在 Ruff v0.2.0 中将这些改进带给所有人。
继续阅读以了解主要变更的讨论,或者查阅更新日志以获取完整列表。
迁移到 v0.2.0 #
此版本包含极少的重大变更。在大多数情况下,用户只会遇到建议从已弃用功能迁移的警告。值得注意的重大变更与Nursery 规则选择(自 v0.1.0 起已弃用)和规则重新映射(可能会禁用先前已启用的规则)有关。
如果您正在使用预览模式,您将看到更多重大变更,因为在稳定版中被视为警告的某些行为将在预览版中报错。我们强烈建议阅读已弃用规则和输出格式部分。
您可以在 Dagster、FastAPI、LangChain、Zulip 和 Sphinx 中查看一些迁移的示例拉取请求。
已弃用规则 #
以下规则现已弃用
missing-type-self
(ANN101
)missing-type-cls
(ANN102
)
我们发现这些规则经常被用户禁用,并且它们的建议与类型检查器无关。
在未启用预览模式的情况下,明确选择已弃用规则(例如,--select ANN001
)会发出警告,但规则仍会启用。如果通过前缀选择(例如,ANN
),则不会发出警告。当启用预览模式时,明确选择将抛出错误,并且通过前缀选择时规则将被禁用。
规则重新映射 #
由于 Ruff 实现了许多代码检查工具的规则,我们偶尔需要处理重叠和重复的规则。以下规则已重新映射到新的代码
raise-without-from-inside-except
:TRY200
映射到B904
suspicious-eval-usage
:PGH001
映射到S307
logging-warn
:PGH002
映射到G010
static-key-dict-comprehension
:RUF011
映射到B035
runtime-string-union
:TCH006
映射到TCH010
使用已弃用代码进行选择将发出警告并自动映射到更新后的代码。如果您通过前缀选择规则(例如,TRY
),新规则将不会自动启用。要继续使用该规则,请使用其更新后的代码(例如,B904
)进行选择。
这些已弃用的规则代码将继续出现在文档中,并附带关于重新映射的说明。
Nursery 规则选择 #
“nursery”最初是新规则的存放地,但此后已被全局预览模式取代。自预览模式引入以来,Nursery 规则选择一直保留以实现向后兼容。现在,使用 Nursery 规则选择器将导致错误。
Nursery 中不稳定的规则不再能在没有预览标志的情况下被选择
❯ ruff check example.py --select RUF912
ruff failed
Cause: Selection of unstable rule `RUF912` without the `--preview` flag is not allowed.
同样,NURSERY
选择器也不再可用
❯ ruff check example.py --select NURSERY
ruff failed
Cause: The `NURSERY` selector was removed. Use the `--preview` flag instead.
已移除规则 #
预览规则 and-or-ternary
(PLR1706
) 已移除。此规则不符合我们的安全标准,针对的是 Python 2.x,并且在缺乏更强类型推断的情况下其有效性有限。
配置变更 #
现在 Ruff 包含了格式化工具,我们已将特定于代码检查工具的设置从顶级 Ruff 设置 (tool.ruff
) 移至专用的 tool.ruff.lint
部分。
例如,ruff.allowed-confusables
已移至 ruff.lint.allowed-confusables
。升级时,您将看到详细的警告,列举所有相关设置及其应移动到的位置。您可以在 v0.2.0 更新日志中查看重命名设置的完整列表。
以下顶级设置被视为全局设置,仍可在 ruff
顶级命名空间中使用,并且不应移动
ruff.builtins
ruff.cache-dir
ruff.exclude
ruff.extend
ruff.extend-exclude
ruff.extend-include
ruff.fix
ruff.fix-only
ruff.force-exclude
ruff.include
ruff.namespace-packages
ruff.preview
ruff.respect-gitignore
ruff.show-fixes
ruff.src
ruff.unsafe-fixes
输出格式 #
目前,当 Ruff 报告代码检查违规时,仅显示错误代码和消息。用户可以通过 --show-source
标志选择包含相关的源代码片段。Ruff 正在朝着将此设为默认行为的方向发展——我们认为违规的上下文很重要,并且包含源代码将使我们未来能够显示建议的修复方案。
为了支持此行为,我们正在添加两个新的输出格式选项
concise
(取代text
)full
(取代--show-source
)
--output-format=text
、--show-source
和 --no-show-source
标志已弃用。您可以继续使用它们,但会显示警告。
在预览模式下,默认输出格式已切换为 full
。要恢复以前的输出,您可以将输出格式设置为 concise
。
稳定版中的默认输出保持不变
❯ ruff check example.py --select RUF900
example.py:1:1: RUF900 Hey this is a stable test rule.
Found 1 error.
预览版中的新默认输出格式
❯ ruff check example.py --select RUF900 --preview
example.py:1:1: RUF900 Hey this is a stable test rule.
|
1 | # I'm just an example source file
| RUF900: Hey this is a stable test rule
2 | ruff = "v0.2.0"
|
Found 1 error.
使用旧的输出格式
❯ ruff check example.py --select RUF900 --preview --output-format concise
example.py:1:1: RUF900 Hey this is a stable test rule.
Found 1 error.
稳定化行为 #
module-import-not-at-top-of-file
(E402
) #
在文件顶部导入之间穿插 sys.path
修改是很常见的——这是 # noqa: E402
误报的常见原因。E402
已更新,在确定“导入边界”时会忽略此类修改。
例如,给定
from foo import Foo
sys.path.append(str(Path(__file__).parent / "extensions"))
from bar import Bar
Ruff 将不再对第二次导入引发 E402
违规。
reimplemented-container-builtin
(PIE807
) #
此前,PIE807
仅检查可被 list
内置函数替换的 lambda 表达式。现在,PIE807
还会标记可被 dict
内置函数替换的 lambda 表达式。
例如,给定
@dataclass
class Foo:
bar: dict[str, int] = field(default_factory=lambda: {})
Ruff 将建议
@dataclass
class Foo:
bar: dict[str, int] = field(default_factory=dict)
unnecessary-placeholder
(PIE790
) #
此前,PIE790
仅检查不必要的 pass
语句。现在,它还会检查不必要的省略号 (...
) 字面量。
例如,给定
def func():
"""Placeholder docstring."""
...
Ruff 将建议
def func():
"""Placeholder docstring."""
if-else-block-instead-of-dict-get
(SIM401
) #
此前,SIM401
仅检查可以被 dict.get()
替换的 if
表达式。现在,SIM401
还会建议用 dict.get()
调用替换 if-else
表达式。
例如,给定
value = foo["bar"] if "bar" in foo else 0
Ruff 将建议
value = foo.get("bar", 0)
稳定化规则 #
以下规则已稳定化,不再处于预览模式
trio-timeout-without-await
(TRIO100
)trio-sync-call
(TRIO105
)trio-async-function-with-timeout
(TRIO109
)trio-unneeded-sleep
(TRIO110
)trio-zero-sleep-call
(TRIO115
)unnecessary-escaped-quote
(Q004
)enumerate-for-loop
(SIM113
)zip-dict-keys-and-values
(SIM911
)timeout-error-alias
(UP041
)flask-debug-true
(S201
)tarfile-unsafe-members
(S202
)ssl-insecure-version
(S502
)ssl-with-bad-defaults
(S503
)ssl-with-no-version
(S504
)weak-cryptographic-key
(S505
)ssh-no-host-key-verification
(S507
)django-raw-sql
(S611
)mako-templates
(S702
)generator-return-from-iter-method
(PYI058
)runtime-string-union
(TCH006
)numpy2-deprecation
(NPY201
)quadratic-list-summation
(RUF017
)assignment-in-assert
(RUF018
)unnecessary-key-check
(RUF019
)never-union
(RUF020
)direct-logger-instantiation
(LOG001
)invalid-get-logger-argument
(LOG002
)exception-without-exc-info
(LOG007
)undocumented-warn
(LOG009
)
还有更多新规则仍在预览中。我们强烈建议您查看它们!您可以打开预览模式并逐个选择规则。
稳定化修复 #
以下规则的修复已稳定化,现已无需预览即可使用
triple-single-quotes
(D300
)non-pep604-annotation
(UP007
)dict-get-with-none-default
(SIM910
)in-dict-keys
(SIM118
)collapsible-else-if
(PLR5501
)if-with-same-arms
(SIM114
)useless-else-on-loop
(PLW0120
)unnecessary-literal-union
(PYI030
)unnecessary-spread
(PIE800
)error-instead-of-exception
(TRY400
)redefined-while-unused
(F811
)duplicate-value
(B033
)multiple-imports-on-one-line
(E401
)non-pep585-annotation
(UP006
)
以下规则的修复已从不安全状态提升至安全状态
unaliased-collections-abc-set-import
(PYI025
)
感谢! #
感谢所有就预览模式下新规则和其他变更行为向我们提供反馈的用户,也感谢自 v0.1.0 发布以来新增的 80 位贡献者(总计 362 位!),与你们一起构建 Ruff 是我们的荣幸!
在 GitHub 上查看完整的更新日志。