Ruff v0.1.8 现已发布,并支持可选地格式化文档字符串中的 Python 代码示例。可以从 PyPI 或您选择的包管理器安装。
pip install --upgrade ruff
提醒一下:Ruff 是一个用 Rust 编写的极速 Python linter 和格式化工具。 Ruff 可以替代 Black、Flake8(以及数十个插件)、isort、pydocstyle、pyupgrade 等,同时执行速度比任何单个工具快几十甚至几百倍。
在 GitHub 上查看完整的更新日志,或继续阅读亮点内容。
格式化文档字符串中的代码片段 #
我们最近发布了 Ruff 格式化工具,一个极速的 Python 代码格式化工具。
在 v0.1.8 中,格式化工具新增了格式化文档字符串中 Python 代码片段的能力,支持以下格式:
- Python doctest 格式。
- CommonMark 围栏式代码块,带有以下信息字符串:
python
、py
、python3
或py3
。没有信息字符串的围栏式代码块被认为是 Python 代码示例,因此也会被格式化。 - reStructuredText 字面块。尽管字面块可能包含 Python 之外的内容,但这旨在反映 Python 生态系统中长期以来的一个惯例,即字面块通常包含 Python 代码。
- reStructuredText
code-block
和sourcecode
指令。与 Markdown 一样,Python 识别的语言名称有python
、py
、python3
或py3
。
这是一个快速示例。首先,我们将创建一个内容如下的 ruff.toml
配置文件:
[format]
# Docstring formatting is opt-in. Enable it by setting this option to `true`.
docstring-code-format = true
其次,我们将创建一个 Python 文件 sample.py
。我们将在一个文档字符串中使用多种不同的格式来演示 ruff format
的广泛支持:
def f(x):
"""
Something about `f`. And an example in doctest format:
>>> f( '''can't fool me'''
... )
Markdown is also supported:
```py tab="plugin.py"
foo, bar, quux = this_is_a_long_line(lion, hippo, giraffe, zebra, penguin, lemur, bear)
```
Fenced code blocks without labels are assumed to be Python:
```
f( x )
```
As are reStructuredText literal blocks::
f( x )
And reStructuredText code blocks are also supported:
.. code-block:: python
:linenos:
def definitely_converges(n):
if n%2==0:
return n//2
else:
return 3*n+1
Code examples that aren't valid Python get skipped automatically::
println!( "Don't mistake me for Python" );
"""
pass
最后,我们通过 ruff format
运行它:
ruff format --config ruff.toml sample.py
完成后,sample.py
应该看起来像:
def f(x):
"""
Something about `f`. And an example in doctest format:
>>> f('''can't fool me''')
Markdown is also supported:
```py tab="plugin.py"
foo, bar, quux = this_is_a_long_line(
lion, hippo, giraffe, zebra, penguin, lemur, bear
)
```
Fenced code blocks without labels are assumed to be Python:
```
f(x)
```
As are reStructuredText literal blocks::
f(x)
And reStructuredText code blocks are also supported:
.. code-block:: python
:linenos:
def definitely_converges(n):
if n % 2 == 0:
return n // 2
else:
return 3 * n + 1
Code examples that aren't valid Python get skipped automatically::
println!( "Don't mistake me for Python" );
"""
pass
不是有效 Python 的代码片段将不会被格式化。同样,如果 ruff format
格式化后会生成一个无效的 Python 程序,那么它也会静默跳过该代码片段。
用户还可以配置用于格式化文档字符串中 Python 代码片段的行长度限制。默认的 dynamic
指示格式化工具遵循周围 Python 代码的行长度限制设置。dynamic
确保即使代码片段位于缩进的文档字符串内部,也会遵循为周围 Python 代码配置的行长度限制。
用户还可以为文档字符串中的代码片段配置固定的行长度限制,这对于确保生成文档中的代码片段遵循一致的行长度(无论原始源代码的缩进程度如何)非常有用。
例如,这将行长度限制设置为 20
:
[format]
docstring-code-format = true
docstring-code-line-length = 20
这是我们的 sample.py
来测试它:
def g(x):
"""
Another example demonstrating how long lines get wrapped.
>>> foo, bar, quux = this_is_a_long_line(lion, hippo, giraffe, zebra, penguin, lemur, bear)
"""
pass
现在再次运行 ruff format
:
ruff format --config ruff.toml sample.py
然后 sample.py
应该变成这样:
def g(x):
"""
Another example demonstrating how long lines get wrapped.
>>> (
... foo,
... bar,
... quux,
... ) = this_is_a_long_line(
... lion,
... hippo,
... giraffe,
... zebra,
... penguin,
... lemur,
... bear,
... )
"""
pass
文档字符串片段格式化目前是可选加入的,但在未来版本中将变为可选退出。
类型注解的自动引用 #
在之前的版本中,Ruff 获得了识别那些仅用于类型注解的导入绑定,并自动将这些导入移动到 if TYPE_CHECKING:
块中的能力。例如,请参阅 typing-only-third-party-import
。将导入移动到类型检查块是 Python 中避免循环导入和减少程序启动时间的常见模式。
迄今为止,这条规则一直受到 Python 要求大多数类型注解在运行时必须可访问的事实阻碍。例如,以下片段将在运行时失败,因为 Python 需要评估 Sequence[int]
才能将其添加到模块的 __annotations__
字段中:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
# Sequence is only available to type-checkers, and not at runtime...
from collections.abc import Sequence
# But Python needs to evaluate `Sequence[int]` here.
def func(value: Sequence[int]) -> None:
...
一个常见的解决方案是在文件顶部添加 from __future__ import annotations
,这指示 Python 延迟评估类型注解。然而,添加 from __future__ import annotations
是一个重要的语义变化,并可能导致其他问题。
在 v0.1.8 中,Ruff 获得了自动引用此类类型注解的能力,如果这样做可以使导入保留或移动到类型检查块中。例如,Ruff 现在可以自动将上述片段重写为:
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Sequence
def func(value: "Sequence[int]") -> None:
...
此行为通过 quote-annotations
设置可选加入,并且当存在 from __future__ import annotations
时无效。
[flake8-type-checking]
quote-annotations = true
贡献者 #
衷心感谢为本次发布做出贡献的人们: