Ruff v0.3.0 现已发布!您可以从 PyPI 或您选择的包管理器进行安装。

pip install --upgrade ruff

提醒:Ruff 是一个用 Rust 编写的极速 Python 代码检查工具和格式化工具。 Ruff 可以替代 Black、Flake8(以及数十个插件)、isort、pydocstyle、pyupgrade 等,其执行速度比任何单个工具快数十倍甚至数百倍。

去年十月,我们发布了 Ruff 格式化工具的生产就绪测试版。此后,我们一直致力于提高代码检查工具和格式化工具之间的兼容性,修复与 Black 的偏差,并实现了 Ruff 的 2024.2 格式化风格。本次发布将格式化工具提升为稳定版,并随之推出了 Ruff 的 2024.2 风格指南。

Ruff 2024.2 风格指南

新的风格指南遵循 Ruff 旨在作为 Black 的直接替代品的原则。它深受 Black 2024 稳定风格指南(作为 Black 24.1.0 的一部分发布)的启发。我们衷心感谢 Black 维护者在引领代码风格讨论和定义新风格指南方面所做的出色工作。

本节的其余部分将介绍 Ruff 新风格指南的重点。有关所有风格更改的详细列表,请参阅 发布说明

优先折行赋值值

直到现在,Ruff 更倾向于在赋值目标处断行而不是在赋值值处。新风格则倾向于在赋值目标或其类型注解之前折行赋值值。

# 2023
query_settings[
    "base_backup"
] = f"S3('{base_backup}/{shard}', '{aws_key}', '{aws_secret}')"

# 2024
query_settings["base_backup"] = (
    f"S3('{base_backup}/{shard}', '{aws_key}', '{aws_secret}')"
)

with 语句中为多个上下文管理器加括号

此前,Ruff 会将 with 语句中的上下文管理器格式化为单行,即使它们超出了配置的行长。现在,当针对 Python 3.9 或更高版本时,Ruff 会为长的上下文管理器添加括号,并将其折行显示在多行上。

# 2023, or when targeting Python < 3.9
with make_context_manager1() as cm1, make_context_manager2() as cm2, make_context_manager3() as cm3, make_context_manager4() as cm4:
    pass

# 2024 when targeting Python 3.9+
with (
    make_context_manager1() as cm1,
    make_context_manager2() as cm2,
    make_context_manager3() as cm3,
    make_context_manager4() as cm4,
):
	pass

带空主体函数和类更紧凑的格式化

新风格通过将省略号(...)折叠到同一行来减少空实现的垂直空间。空函数定义之间的空行现在也变为可选。

# 2023
@overload
def f():
    ...


def f(a: int | None):
    ...


class Test:
    ...

# 2024
@overload
def f(): ...
def f(a:  int | None): ...


class Test: ...

改进的多行字符串格式化

在 2023 年风格指南中,Ruff 总是会缩进多行字符串,即使它们是函数调用的唯一参数。新的风格指南在调用开括号和字符串引号在同一行时,避免缩进多行字符串,从而减少垂直空间。

# Input
textwrap.dedent("""
    This is a
    multiline string
""")

# 2023
textwrap.dedent(
    """
    This is a
    multiline string
"""
)

# 2024
textwrap.dedent("""
    This is a
    multiline string
""")

范围格式化

Ruff v0.2.1 添加了对范围格式化的支持。IDE 使用范围格式化将格式化限制在选定范围(在 VS Code 中称为格式化选择)或根据版本控制信息限制在已修改的行

将格式化限制在已修改的行特别有用,如果

  • 您的项目正在逐步采用格式化工具;或者,
  • 您正在处理一个不使用标准化格式的项目,但您希望使用 Ruff 格式化您已修改的特定代码区域。

用户向现有函数调用添加了一个新参数。VS Code 在保存时使用 Ruff 重新格式化文件以格式化该调用表达式。

在上面的视频中,VS Code 重新格式化了修改后的函数调用,但保留了 __init__ 函数定义未被修改,因为它没有被用户更改。

要在 VS Code 中启用已修改行的格式化,请将 editor.formatOnSaveMode 设置为 "modificationsIfAvailable"

f-string 占位符格式化

Ruff v0.2.2 添加了对 f-string 内(在 --preview 模式下)格式化的支持。您不再需要手动格式化占位符内的表达式;Ruff 可以为您处理。

  console.print(f"[red]Error!: {e}[/]")
  console.print(
-    f"[yellow]Restart with `--start-from {processed_issues+start_from}` to continue.[/]"
+    f"[yellow]Restart with `--start-from {processed_issues + start_from}` to continue.[/]"
  )

我们正在与 Black 合作,以定义 f-string 格式化的标准化风格。请分享您的反馈,帮助我们塑造未来的 f-string 格式化。

检查无效的格式化工具抑制注释

Ruff 的格式化工具对格式化工具抑制注释的放置有比 Black 更严格的要求,这是为了实现可预测的格式化。

然而,这种差异让用户感到困惑,因为不清楚 Ruff 为什么会忽略 Black 不忽略的特定抑制注释。Ruff v0.3.0 附带了新的检查规则 RUF028,该规则用于识别无效的格式化工具抑制注释;即 Ruff 的格式化工具不遵循的 # fmt: off 注释。

def fmt_off_between_lists():
    test_list = [
        # fmt: off
        1,
        2,
        3,
    ]

RUF028 会对上述代码片段中使用 # fmt: off 生成诊断信息,因为 Ruff(与 Black 不同)不支持在表达式内部使用 # fmt: off

RUF028.py:3:9: RUF028 This suppression comment is invalid because it cannot be in an expression, pattern, argument list, or other non-statement
  |
1 | def fmt_off_between_lists():
2 |     test_list = [
3 |         # fmt: off
  |         ^^^^^^^^^^ RUF028
4 |         1,
5 |         2,
  |
  = help: Remove this comment

感谢!

感谢所有就格式化工具和 Ruff --preview 模式中包含的其他更改提供反馈的人,尤其感谢我们的贡献者。与您一起构建 Ruff 是我们的荣幸!


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

了解更多关于 Astral — Ruff 背后的公司。