Skip to content

The Ruff Linter#

Ruff Linter は、Flake8(および数十のプラグイン)、isortpydocstyle,pyupgradeautoflakeなどの代替品として設計された非常に高速な Python リンタです。

ruff check#

ruff check は Ruff linter への主要なエントリーポイントです。ファイルまたはディレクトリのリストを受け入れ、検出されたすべての Python ファイルを検索し、オプションで修正可能なエラーを修正します。:

$ ruff check                  # Lint all files in the current directory.
$ ruff check --fix            # Lint all files in the current directory, and fix any fixable errors.
$ ruff check --watch          # Lint all files in the current directory, and re-lint on change.
$ ruff check path/to/code/    # Lint all files in `path/to/code` (and any subdirectories).

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

Note

Ruff v0.1.7では、ruff checkコマンドは現在の作業ディレクトリ(.)をデフォルトのパスとしてチェックします。 古いバージョンでは、例えばruff check.のように、これを手動で提供しなければなりません。 詳細については、the file discovery documentationを参照してください。

Rule selection#

有効なルールのセットは、lint.selectlint.extend-select、およびlint.ignoreの設定によって制御されます。

ラフのリンター鏡 Flake8 のルールコードシステムでは、各ルールコードは 1 ~ 3 文字の接頭辞とそれに続く 3 桁の数字(例:F401)で構成されます。接頭辞はルールの"ソース"を示します(例:Pyflakes のF、pycodestyle のE、Flake8-annotations のANN)。

lint.selectlint.ignoreなどのルールセレクタは、完全なルールコード(例:F401)または任意の有効なプレフィックス(例:F)のいずれかを受け入れます。たとえば、次の設定ファイルがあるとします。:

[tool.ruff.lint]
select = ["E", "F"]
ignore = ["F401"]
[lint]
select = ["E", "F"]
ignore = ["F401"]

Ruff は、E(pycodestyle)またはF(Pyflakes)のプレフィックスを持つすべてのルールを有効にしますが、F401は例外です。pyproject.tomlによる Ruff の設定の詳細については、Configuring Ruffを参照してください。

特殊なケースとして、Ruff はすべてのルールを有効にするALLコードもサポートしています。一部の pydocstyle ルール(D203D211など)は、代替の docstringformat を表しているため、競合することに注意してください。ALLが有効になっている場合、Ruff は競合するルールを自動的に無効にします。

Ruff の設定方法を知りたい場合は、次の推奨ガイドラインを参照してください。:

  • ルールセットを明示的にするには、lint.extend-selectよりもlint.selectを優先します。
  • 慎重にALLを使用してください。ALLを有効にすると、アップグレードするたびに新しいルールが暗黙的に有効になります。
  • ルールの小さなセット(select = ["E", "F"])から始めて、一度にカテゴリを追加します。たとえば、lake8-bugbear 拡張 を有効にするには、select = ["E", "F", "B"]に拡張することを検討してください。

たとえば、最も一般的な規則の一部を有効にする設定は、次のようになります(過度に制限されません)。:

[tool.ruff.lint]
select = [
    # pycodestyle
    "E",
    # Pyflakes
    "F",
    # pyupgrade
    "UP",
    # flake8-bugbear
    "B",
    # flake8-simplify
    "SIM",
    # isort
    "I",
]
[lint]
select = [
    # pycodestyle
    "E",
    # Pyflakes
    "F",
    # pyupgrade
    "UP",
    # flake8-bugbear
    "B",
    # flake8-simplify
    "SIM",
    # isort
    "I",
]

有効なルールセットを解決するために、Ruff は、現在のpyproject.toml、継承されたpyproject.tomlファイル、および CLI(例えば、--select)を含む、さまざまなソースからのlint.selectおよびlint.ignoreを調整する必要がある場合がある。

これらのシナリオでは、Ruff は"最も優先度の高い"selectをルールセットの基礎として使用し、extend-selectignoreの調整を適用する。CLI オプションにはpyproject.tomlオプションよりも高い優先度が与えられ、現在のpyproject.tomlファイルには継承されたpyproject.tomlファイルよりも高い優先度が与えられる。

たとえば、次のコンフィギュレーションファイルがあるとします。:

[tool.ruff.lint]
select = ["E", "F"]
ignore = ["F401"]
[lint]
select = ["E", "F"]
ignore = ["F401"]

ruff check--select F401を実行すると、Ruff はF401を強制し、他のルールは強制しません。

ruff check--extend-select Bを実行すると、Ruff はF401を除いて、EF、およびBの規則を強制します。

Fixes#

Ruff は、さまざまな lint エラーの自動修正をサポートしています。たとえば、Ruff は、使用されていないインポートの削除、docstring の再フォーマット、新しい Python 構文を使用するための型注釈の書き換えなどを行うことができます。

修正を有効にするには、--fixフラグをruff checkに渡します。:

$ ruff check --fix

デフォルトでは、Ruff は安全な修正が利用可能なすべての違反を修正します。ルールが修正をサポートしているかどうかを判断するには、Rulesを参照してください。

Fix safety#

Ruff はフィックスに"安全"と"安全でない"のラベルを付けます。コードの意味と意図は、安全なフィックスを適用しても保持されますが、安全でないフィックスを適用すると意味が変更される可能性があります。

例えば、unnecessary-iterable-allocation-for-first-element(RUF015)は、list(.)[0]の潜在的に実行不可能な使用をチェックするルールです。修正により、このパターンがnext(iter(.))に置き換えられ、大幅な高速化が可能になります。:

$ python -m timeit "head = list(range(99999999))[0]"
1 loop, best of 5: 1.69 sec per loop
$ python -m timeit "head = next(iter(range(99999999)))"
5000000 loops, best of 5: 70.8 nsec per loop

ただし、コレクションが空の場合は、発生した例外がIndexErrorからStopIterationに変更されます。:

$ python -c 'list(range(0))[0]'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
IndexError: list index out of range
$ python -c 'next(iter(range(0)))[0]'
Traceback (most recent call last):
  File "<string>", line 1, in <module>
StopIteration

これによりエラー処理が中断される可能性があるため、この修正は安全でないと分類されます。

Ruff はデフォルトで安全な修正のみを有効にします。安全でない修正は、設定ファイルの設定unsafe-fixes、またはruff check--unsafe-fixesフラグを渡すことで有効にできます。:

# Show unsafe fixes
ruff check --unsafe-fixes

# Apply unsafe fixes
ruff check --fix --unsafe-fixes

デフォルトでは、安全でない修正が利用可能であるが有効になっていない場合、Ruff はヒントを表示する。unsafe-fixes設定をfalseに設定するか、--no-unsafe-fixesフラグを使用することで、提案を安全でないものにすることができます。

修正の安全性は、lint.extend-safe-fixesおよびlint.extend-unsafe-fixes設定を使用して、ルールごとに調整できます。

たとえば、次の構成では、F601の安全でない修正を安全な修正に昇格させ、UP034の安全な修正を安全でない修正に降格させます。:

[tool.ruff.lint]
extend-safe-fixes = ["F601"]
extend-unsafe-fixes = ["UP034"]
[lint]
extend-safe-fixes = ["F601"]
extend-unsafe-fixes = ["UP034"]

接頭辞を使用してルールを選択することもできます。たとえば、Fを使用して、Pyflakes のすべてのルールの修正を安全にプロモートできます。

Note

json出力形式を使用すると、すべての修正は常にRuffによって表示される。各修正の安全性は、applicabilityフィールドで確認できます。

Disabling fixes#

Ruff が修正すべきルールのセットを制限するには、lint.fixableまたはlint.extend-fixable、およびlint.unfixable設定を使用します。

たとえば、次の設定では、unused-imports(F401)を除くすべてのルールの修正が有効になります。:

[tool.ruff.lint]
fixable = ["ALL"]
unfixable = ["F401"]
[lint]
fixable = ["ALL"]
unfixable = ["F401"]

逆に、次の設定ではF401の修正のみが有効になります。:

[tool.ruff.lint]
fixable = ["F401"]
[lint]
fixable = ["F401"]

Error suppression#

Ruff は、リントエラーを抑制するためのいくつかのメカニズムをサポートしており、それらは偽陽性であっても、許容される違反であってもです。

リントルールを完全に省略するには、コマンドラインまたはpyproject.tomlまたはruff.tomlファイルのlint.ignore設定を使用して、それを"ignore"リストに追加します。

インラインで違反を抑制するために、Ruff はFlake8に似た"noqa"システムを使用しています。個々の違反を無視するには、次のように行末に# noqa: {code}を追加する。:

# Ignore F841.
x = 1  # noqa: F841

# Ignore E741 and F841.
i = 1  # noqa: E741, F841

# Ignore _all_ violations.
x = 1  # noqa

複数行の文字列(docstring のような)の場合、noqaディレクティブは文字列の末尾(末尾のトリプルクォートの後)に置く必要があり、次のように文字列全体に適用されます。:

"""Lorem ipsum dolor sit amet.

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor.
"""  # noqa: E501

インポートのソートでは、noqaはインポートブロックの最初の行の終わりに置かれ、次のようにブロック内のすべてのインポートに適用されます。:

import os  # noqa: I001
import abc

ファイル全体のすべての違反を無視するには、次のように、ファイル内の任意の場所(できれば先頭方向)に# ruff: noqa行を追加します。:

# ruff: noqa

ファイル全体にわたって特定のルールを無視するには、次のように、# ruff: noqa: {code}行をファイルの任意の場所に、できれば先頭に向かって追加します。:

# ruff: noqa: F841

または、lint.per-file-ignores設定を参照してください。これにより、pyproject.tomlまたはruff.tomlファイル内から同じ機能が有効になります。

グローバルなnoqaコメントは、1 行で違反を無視するコメントと区別するために、独自の行に配置する必要があります。

Ruff は Flake8 の# Flake8: noqaディレクティブも尊重し、# ruff: noqaと同等のものとして扱うことに注意してください。

Detecting unused suppression comments#

Ruff は、RUF100コードの下にunused-noqaという特別なルールを実装して、noqaディレクティブが"有効"であることを強制します。つまり、彼らが無視する違反は、実際にはその行でトリガーされています(したがって抑制されています)。未使用のnoqaディレクティブにフラグを付けるには、ruff check /path/to/file.py --extend-select RUF100を実行します。

Ruff は、その修正機能を介して、使用されていないnoqaディレクティブを削除することもできます。使用されていないnoqaディレクティブを削除するには、ruff check /path/to/file.py --extend-select RUF100 --fixを実行します。

Inserting necessary suppression comments#

Ruff は、違反を含むすべての行に自動的にnoqaディレクティブを追加できます。これは、新しいコードベースを Ruff に移行するときに便利です。すべての関連する行に(適切なルールコードとともに)自動的にnoqaディレクティブを追加するには、ruff check /path/to/file.py --add-noqaを実行します。

Action comments#

Ruff は isort のaction comments(# isort: skip_file,# isort: on,# isort: off,# isort: skip,# isort: split)を尊重しており、コードブロックやその他のインライン設定のインポートソートを選択的に有効または無効にすることができます。

Ruff はまた、# ruff:プレフィックスを持つこれらのアクションコメントの変種(例えば、# ruff: isort: skip_file#ruff: isort: on、など)を尊重する。これらの変種は、アクションコメントが Ruff を意図していることをより明確に伝えるが、機能的には isort 変種と同等です。

isort とは異なり、Ruff は docstring 内のアクションコメントを尊重しません。

詳細については、isort documentationを参照してください。

Exit codes#

デフォルトでは、ruff checkは以下の状態コードで終了します。:

  • 違反が見つからなかった場合、または存在するすべての違反が自動的に修正された場合は"0"。
  • 違反が見つかった場合は"1"。
  • 無効な構成、無効な CLI オプション、または内部エラーが原因で Ruff が異常終了した場合は"2"。

この規約は、ESLint、Prettier、RuboCop などのツールの規約を反映しています。

ruff checkは、終了コードの動作を変更する 2 つのコマンドラインフラグをサポートしています。:

  • --exit-zeroは、違反が見つかった場合でも、Ruff をステータスコード0で終了させます。異常終了した場合でも、Ruff はステータスコード2で終了することに注意してください。
  • --exit-non-zero-on-fixは、違反が見つかった場合、たとえそのような違反がすべて自動的に修正されたとしても、Ruff を1のステータスコードで終了させます。--exit-non-zero-on-fixを使用すると、修正後に違反が残っていなくても、ゼロ以外の終了コードになる可能性があることに注意してください。