Skip to content

The Ruff Formatter#

Ruff フォーマッタは、Blackの代用として設計された非常に高速な Python コードフォーマッタであり、ruff formatを介してruffCLI の一部として利用できます。

Ruff フォーマッタは、Ruffv0.1.2から入手できます。

ruff format#

ruff formatはフォーマッタへの主要なエントリーポイントです。これはファイルまたはディレクトリのリストを受け入れ、検出されたすべての Python ファイルをフォーマットします。:

ruff format                   # Format all files in the current directory.
ruff format path/to/code/     # Format all files in `path/to/code` (and any subdirectories).
ruff format path/to/file.py   # Format a single file.

Black と同様に、ruff format /path/to/file.pyを実行すると、指定されたファイルまたはディレクトリが所定の場所にフォーマットされます。一方、ruff format --check /path/to/file.pyを実行すると、フォーマットされたファイルが書き戻されることはなく、フォーマットされていないファイルが検出されると 0 以外のステータスコードで終了します。

サポートされているオプションの完全なリストについては、ruff format--helpを実行してください。

Note

Ruff v0.1.7では、ruff formatコマンドは現在の作業ディレクトリ(.)をformatへのデフォルトパスとして使用します。

詳細については、ファイル検出マニュアルを参照してください。

Philosophy#

Ruff フォーマッタの最初の目標は、コードスタイルを革新することではなく、むしろパフォーマンスを革新し、Ruff のリンタ、フォーマッタ、および将来のあらゆるツールにわたって統一されたツールチェーンを提供することです。

そのため、フォーマッタはBlackの代用として設計されていますが、パフォーマンスと Ruff との直接統合に過度に重点を置いています。Python エコシステム内での Black の人気を考えると、Black の互換性をターゲットにすることで、大多数のプロジェクトにとって、フォーマッタの採用による混乱を最小限に抑えることができます。

具体的には、このフォーマッタは、既存の black 形式のコードに対して実行した場合に、ほぼ同じ出力を出力することを目的としています。Django や Zulip などの広範な black 形式のプロジェクトに対して実行すると、99.9%を超える行が同じようにフォーマットされます(Black compatibilityを参照)。

このように Black との互換性に重点が置かれているため、フォーマッタはBlack's(stable)code styleに準拠しており、これは"一貫性、一般性、可読性、git の違いの低減"を目的としています。強制されたコードスタイルの意味を理解するために、次に例を示します。:

# Input
def _make_ssl_transport(
    rawsock, protocol, sslcontext, waiter=None,
    *, server_side=False, server_hostname=None,
    extra=None, server=None,
    ssl_handshake_timeout=None,
    call_connection_made=True):
    '''Make an SSL transport.'''
    if waiter is None:
      waiter = Future(loop=loop)

    if extra is None:
      extra = {}

    ...

# Ruff
def _make_ssl_transport(
    rawsock,
    protocol,
    sslcontext,
    waiter=None,
    *,
    server_side=False,
    server_hostname=None,
    extra=None,
    server=None,
    ssl_handshake_timeout=None,
    call_connection_made=True,
):
    """Make an SSL transport."""
    if waiter is None:
        waiter = Future(loop=loop)

    if extra is None:
        extra = {}

    ...

Black と同様に、Ruff フォーマッタは広範なコードスタイルの設定をサポートしていませんが、Black とは異なり、必要な引用スタイル、インデントスタイル、行末などの設定をサポートしています(Configurationを参照)。

このフォーマッタは Black の代替として設計されていますが、継続的に Black と同じ意味で使用されることを意図したものではありません。

一般的に、Black と Ruff の間の基礎となる実装の違いを考慮すると、差異は、Ruff の動作がより一貫しているか、サポートが大幅に簡単である(エンド・ユーザーへの影響は無視できる)と考えられる場合に限定されます。

今後、Ruff Formatter は、Ruff 独自のpreviewモードで Black のプレビュースタイルをサポートします。

Configuration#

Ruff Formatter は設定オプションの小さなセットを公開しており、その中には Black でもサポートされているもの(線幅など)もあれば、Ruff 独自のもの(引用符、インデントスタイル、docstring 内のコード例のフォーマットなど)もあります。

例えば、一重引用符の使用、docstring 内のサンプル・コードのフォーマット、100 行の線幅、およびタブのインデントを構成するには、構成ファイルに以下を追加します。:

[tool.ruff]
line-length = 100

[tool.ruff.format]
quote-style = "single"
indent-style = "tab"
docstring-code-format = true
line-length = 100

[format]
quote-style = "single"
indent-style = "tab"
docstring-code-format = true

サポートされている設定の完全なリストについては、Settingsを参照してください。pyproject.tomlを介した Ruff の設定の詳細については、Configuring Ruffを参照してください。

Black の互換性に重点が置かれているため(YAPR)のようなフォーマッタとは異なり)、Ruff は現在、他の設定オプションを公開していません。

Docstring formatting#

Ruff フォーマッタは、docstring 内の Python コード例を自動的にフォーマットするためのオプトイン機能を提供します。Ruff フォーマッタは現在、次のフォーマットのコード例を認識します。

  • Python のdoctest形式。
  • 次の情報文字列を持つ CommonMarkfenced code blocks:pythonpypython3、またはpy3。情報文字列を持たない fenced code blocks は、Python コード例であると見なされ、フォーマットもされます。
  • reStructuredTextliteral blocks。リテラルブロックには Python 以外のものが含まれる場合がありますが、これは、リテラルブロックに Python コードが含まれることが多い Python エコシステムにおける長年の慣例を反映することを目的としています。
  • reStructuredText[code-block and sourcecode directives]。Markdown と同様に、Python で認識される言語名はpythonpypython3、またはpy3です。

コード例が Python として認識されて処理される場合、Ruff フォーマッタは、コードが有効な Python として解析されない場合、または整形されたコードが無効な Python プログラムを生成する場合に、自動的にそれをスキップします。

ユーザーは、docstring 内の Python コード例を再フォーマットするために使用される行の長さの制限を設定することもできます。デフォルトは特別な値dynamicで、周囲の Python コードの行の長さの制限設定を尊重するようにフォーマッタに指示します。dynamic設定は、インデントされた docstring 内にコード例が見つかった場合でも、周囲の Python コードに設定された行の長さの制限を超えないようにします。ユーザーは、docstring 内のコード例に固定の行の長さの制限を設定することもできます。

たとえば、次の設定は、固定された行の長さ制限で docstring コードのフォーマットを有効にする方法を示しています。:

[tool.ruff.format]
docstring-code-format = true
docstring-code-line-length = 20
[format]
docstring-code-format = true
docstring-code-line-length = 20

上記の設定では、このコードは次のようになります。:

def f(x):
    '''
    Something about `f`. And an example:

    .. code-block:: python

        foo, bar, quux = this_is_a_long_line(lion, hippo, lemur, bear)
    '''
    pass

次のように再フォーマットされます(残りのオプションがデフォルトに設定されていると仮定します)::

def f(x):
    """
    Something about `f`. And an example:

    .. code-block:: python

        (
            foo,
            bar,
            quux,
        ) = this_is_a_long_line(
            lion,
            hippo,
            lemur,
            bear,
        )
    """
    pass

Format suppression#

Black と同様に、Ruff は# fmt: on# fmt: off#f mt: skipのプラグマコメントをサポートしており、これを使用して特定のコードブロックのフォーマットを一時的に無効にすることができます。

# fmt: onコメントと# fmt: offコメントは文レベルで適用されます。:

# fmt: off
not_formatted=3
also_not_formatted=4
# fmt: on

そのため、式の中に# fmt: onコメントと# fmt: offコメントを追加しても効果はありません。次の例では、# fmt: offがあるにもかかわらず、両方のリストエントリがフォーマットされます。:

[
    # fmt: off
    '1',
    # fmt: on
    '2',
]

代わりに、文全体に# fmt: offコメントを適用してください。:

# fmt: off
[
    '1',
    '2',
]
# fmt: on

Black のように、Ruff はYAF P#yapf:disable#yapf:enableの pragmacomments も認識し、それぞれ# fmt: off# fmt: onと同等に扱われます。

# fmt: skipコメントは、先行する文、case ヘッダ、デコレータ、関数定義、またはクラス定義の書式設定を抑制します。:

if True:
    pass
elif False: # fmt: skip
    pass

@Test
@Test2 # fmt: skip
def test(): ...

a = [1, 2, 3, 4, 5] # fmt: skip

def test(a, b, c, d, e, f) -> int: # fmt: skip
    pass

そのため、式の最後に# fmt: skipコメントを追加しても効果はありません。次の例では、# fmt: skipがあるにもかかわらず、リストエントリ'1'がフォーマットされます。:

a = call(
    [
        '1',  # fmt: skip
        '2',
    ],
    b
)

代わりに、文全体に# fmt: skipコメントを適用してください。:

a = call(
  [
    '1',
    '2',
  ],
  b
)  # fmt: skip

Conflicting lint rules#

Ruff のフォーマッタは、リンタと一緒に使用するように設計されています。ただし、リンタには、有効にするとフォーマッタとの競合を引き起こし、予期しない動作を引き起こす可能性のあるいくつかのルールが含まれています。適切に設定された場合、Ruff のフォーマッタとリンタの互換性の目標は、フォーマッタを実行しても新しいリントエラーが発生しないようにすることです。

Ruff をフォーマッタとして使用する場合は、次のリントルールを避けることをお勧めします。:

line-too-long(E501)ルールはフォーマッタと一緒に使用できますが、フォーマッタは設定されたline-lengthで行をラップしようとするだけです。そのため、フォーマットされたコードは行の長さを超える可能性があり、line-too-long(E501)エラーが発生します。

上記のいずれも、Ruff のデフォルト設定には含まれていません。ただし、これらのルールのいずれかまたはその親カテゴリ(Qなど)を有効にしている場合は、linter のlint.ignore設定を使用して無効にすることをお勧めします。

同様に、以下の isort 設定は避けることをお勧めします。これらの設定は、デフォルト以外の値に設定されている場合、インポート文のフォーマッタの処理と互換性がありません。:

これらの設定のいずれかをデフォルト以外の値に設定した場合は、Ruff 設定から削除することをお勧めします。

互換性のないリントルールまたは設定が有効になっている場合、ruff formatは警告を発します。ruff formatに警告がない場合は、準備完了です!

Exit codes#

ruff formatは、次のステータスコードで終了します。:

  • ファイルがフォーマットされたかどうかに関係なく、Ruff が正常に終了した場合は0
  • 無効な設定、無効な CLI オプション、または内部エラーが原因で Ruff が異常終了した場合は2

一方、ruff format--checkは以下の状態コードで終了します。:

  • 0 Ruff が正常に終了した場合。--checkが指定されていない場合はファイルがフォーマットされません。
  • 1 Ruff が正常に終了した場合。--checkが指定されていない場合は 1 つ以上のファイルがフォーマットされます。
  • 2 無効な設定、無効な CLI オプション、または内部エラーが原因で Ruff が異常終了した場合。

Black compatibility#

このフォーマッタは、Blackを代用に置き換えるように設計されています。

具体的には、フォーマッタは、black でフォーマットされたコード上で実行されたときに、ほぼ同じ出力を出力することを意図しています。Django や Zulip のような広範な black でフォーマットされたプロジェクト上で実行されると、99.9%以上の行が同じようにフォーマットされます。既存のプロジェクトを black からラフに移行する場合、マージンにいくつかの違いが見られると予想されますが、コードの大部分は変更されないはずです。

non-Black でフォーマットされたコードを実行すると、フォーマッタは Black とは異なる決定を行うため、特に行末コメントの処理に関しては、より多くの際が予想されます。

プロジェクト内で差異を特定した場合は、known deviationsと、問題トラッカーに登録されているunintentional deviationsに対してスポットチェックを行います。新しい差異を特定した場合は、file an issueしてください。

Intentional deviations#

Ruff フォーマッタは Black のドロップイン代替を目的としていますが、いくつかの既知の点で Blackin とは異なります。これらの違いのいくつかは、Black のコードスタイルを改善しようとする意識的な試みから生じていますが、他の違いは、基礎となる実装の違いから生じています。

これらの意図的な差異の完全な列挙については、Known deviationsを参照してください。

black からの意図しない差異は、issue trackerで追跡されます。

Preview style#

black ゲートは、previewフラグの背後でフォーマットを変更します。フォーマッタはまだ black のプレビュースタイルをサポートしてませんが、今後数ヶ月以内に Ruff 自身のpreviewフラグの背後でサポートする予定です。

Black は、毎年末にプレビュースタイルの一部を安定版に昇格させます。Ruff も同様に、previewフラグの下でフォーマット変更を実装し、versioning policyに従って、マイナーリリースを通じて安定版に昇格させます。

Sorting imports#

現在、Ruff フォーマッタはインポートをソートしません。インポートのソートとフォーマットの両方を行うには、Ruff リンタを呼び出してからフォーマッタを呼び出します。:

ruff check --select I --fix
ruff format

リンティングとフォーマットの両方のための統一されたコマンドはplannedです。