Skip to content

Tutorial#

このチュートリアルでは、Ruff のリンタとフォーマッタをプロジェクトに統合するプロセスについて説明します。より詳細な概要については、Configuring Ruffを参照してください。

Getting Started#

まず、PyPI 経由で Ruff をインストールします(または、referred package managerを使用します)。:

$ pip install ruff

次に、プロジェクト構造が次のようになっていると仮定します。:

numbers
  ├── __init__.py
  └── numbers.py

ここで、numberspyには次のコードが含まれます。:

from typing import Iterable

import os

def sum_even_numbers(numbers: Iterable[int]) -> int:
    """Given an iterable of integers, return the sum of all even numbers in the iterable."""
    return sum(
        num for num in numbers
        if num % 2 == 0
    )

プロジェクトに対して Ruff linter を実行するには、ruff checkを使用します。:

$ ruff check
numbers/numbers.py:3:8: F401 [*] `os` imported but unused
Found 1 error.
[*] 1 fixable with the `--fix` option.

Ruff は、Python コードの一般的なエラーである未使用のインポートを特定しました。Ruff はこれを"修正可能な"エラーと見なしているため、ruff check --fixを実行することで問題を自動的に解決できます。:

$ ruff check --fix
Found 1 error (1 fixed, 0 remaining).

git diffを実行すると、次のように表示されます。:

--- a/numbers/numbers.py
+++ b/numbers/numbers.py
@@ -1,7 +1,5 @@
 from typing import Iterable

-import os
-

def sum_even_numbers(numbers: Iterable[int]) -> int:
    """Given an iterable of integers, return the sum of all even numbers in the iterable."""
    return sum(
        num for num in numbers
        if num % 2 == 0
    )

注:Ruff はデフォルトで現在のディレクトリで実行されますが、特定のパスを渡してチェックすることができます。:

$ ruff check numbers/numbers.py

プロジェクトが"ruff check"に合格したので、"ruff format"を使用して Ruff フォーマッタを実行できます。:

$ ruff format
1 file reformatted

git diffを実行すると、sum呼び出しがデフォルトの 88 文字の行長制限内に収まるように再フォーマットされたことがわかります。:

--- a/numbers.py
+++ b/numbers.py
@@ -3,7 +3,4 @@ from typing import Iterable

 def sum_even_numbers(numbers: Iterable[int]) -> int:
     """Given an iterable of integers, return the sum of all even numbers in the iterable."""
-    return sum(
-        num for num in numbers
-        if num % 2 == 0
-    )
+    return sum(num for num in numbers if num % 2 == 0)

これまでのところ、Ruff のデフォルト設定を使用しています。Ruff の動作のカスタマイズ方法を見てみましょう。

Configuration#

各 Python ファイルに適切な設定を決定するために、Ruff はファイルのディレクトリまたは任意の親ディレクトリで最初のpyproject.tomlruff.toml、または.ruff.tomlファイルを検索します。

Ruff を設定するために、プロジェクトのルートディレクトリに設定ファイルを作成しましょう。:

[tool.ruff]
# Set the maximum line length to 79.
line-length = 79

[tool.ruff.lint]
# Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that
# overlap with the use of a formatter, like Black, but we can override this behavior by
# explicitly adding the rule.
extend-select = ["E501"]
# Set the maximum line length to 79.
line-length = 79

[lint]
# Add the `line-too-long` rule to the enforced rule set. By default, Ruff omits rules that
# overlap with the use of a formatter, like Black, but we can override this behavior by
# explicitly adding the rule.
extend-select = ["E501"]

再び Ruff を実行すると、最大線幅が強制され、制限が 79 であることがわかります。:

$ ruff check
numbers/numbers.py:5:80: E501 Line too long (90 > 79)
Found 1 error.

サポートされている設定の完全な一覧については、Settingsを参照してください。特にこのプロジェクトでは、サポートされている Python の最小バージョンをメモしておきます。:

[project]
# Support Python 3.10+.
requires-python = ">=3.10"

[tool.ruff]
# Set the maximum line length to 79.
line-length = 79

[tool.ruff.lint]
# Add the `line-too-long` rule to the enforced rule set.
extend-select = ["E501"]
# Support Python 3.10+.
target-version = "py310"
# Set the maximum line length to 79.
line-length = 79

[lint]
# Add the `line-too-long` rule to the enforced rule set.
extend-select = ["E501"]

Rule Selection#

Ruff は、50 以上の組み込みプラグインに分割されたover 800 lint rulesをサポートしていますが、適切なルールのセットを決定することは、プロジェクトのニーズに依存します。ルールには厳しすぎるものもあれば、フレームワーク固有のものもあります。

デフォルトでは、Ruff は Flake8 の"F"ルールを"E"ルールのサブセットとともに有効にし、"ruff format"やBlackのようなフォーマッタの使用と重複するスタイルのルールを省略します。

リンターを初めて導入する場合は、デフォルトのルール・セットから始めるのが最適です。つまり、構成なしでさまざまな一般的なエラー(未使用のインポートなど)をキャッチしながら、ルール・セットは狭く焦点を絞っています。

別のリンターから Ruff に移行する場合は、以前の構成で適用されていたルールと同等のルールを有効にすることができます。たとえば、pyupgraderules を適用したい場合は、構成ファイルを次のように設定できます。:

[project]
requires-python = ">=3.10"

[tool.ruff.lint]
extend-select = [
  "UP",  # pyupgrade
]
target-version = "py310"

[lint]
extend-select = [
  "UP",  # pyupgrade
]

Ruff を再度実行すると、pyupgrade ルールが適用されていることがわかります。特に、Ruff はcollections.abc.Iterableの代わりに非推奨のtyping.Iterableを使用していることにフラグを立てています。:

$ ruff check
numbers/numbers.py:1:1: UP035 [*] Import from `collections.abc` instead: `Iterable`
Found 1 error.
[*] 1 fixable with the `--fix` option.

時間の経過とともに、追加のルールを適用することを選択する場合があります。たとえば、すべての関数に docstring があることを適用する場合があります。:

[project]
requires-python = ">=3.10"

[tool.ruff.lint]
extend-select = [
  "UP",  # pyupgrade
  "D",   # pydocstyle
]

[tool.ruff.lint.pydocstyle]
convention = "google"
target-version = "py310"

[lint]
extend-select = [
  "UP",  # pyupgrade
  "D",   # pydocstyle
]

[lint.pydocstyle]
convention = "google"

Ruff を再度実行すると、pydocstyle のルールが適用されていることがわかります。:

$ ruff check
numbers/__init__.py:1:1: D104 Missing docstring in public package
numbers/numbers.py:1:1: UP035 [*] Import from `collections.abc` instead: `Iterable`
numbers/numbers.py:1:1: D100 Missing docstring in public module
Found 3 errors.
[*] 1 fixable with the `--fix` option.

Ignoring Errors#

リントルールは、問題の行に# noqaコメントを追加することで無視できます。たとえば、IterableインポートのUP035ルールを無視しましょう。:

from typing import Iterable  # noqa: UP035

def sum_even_numbers(numbers: Iterable[int]) -> int:
    """Given an iterable of integers, return the sum of all even numbers in the iterable."""
    return sum(num for num in numbers if num % 2 == 0)

もう一度ruff checkを実行すると、Iterableインポートにフラグが立っていないことがわかります。:

$ ruff check
numbers/__init__.py:1:1: D104 Missing docstring in public package
numbers/numbers.py:1:1: D100 Missing docstring in public module
Found 3 errors.

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

# ruff: noqa: UP035
from typing import Iterable

def sum_even_numbers(numbers: Iterable[int]) -> int:
    """Given an iterable of integers, return the sum of all even numbers in the iterable."""
    return sum(num for num in numbers if num % 2 == 0)

エラーを無視する方法の詳細については、Error suppressionを参照してください。

Adding Rules#

既存のコードベースで新しいルールを有効にする場合、そのルールのすべての既存の違反を無視し、今後はそれを強制することに重点を置くことができます。

Ruff は、--add-noqaフラグを介してこのワークフローを有効にします。これにより、既存の違反に基づいて各ラインに# noqaディレクティブが追加されます。--add-noqa--selectコマンドラインフラグを組み合わせると、既存のすべてのUP035違反に# noqaディレクティブを追加できます。:

$ ruff check --select UP035 --add-noqa .
Added 1 noqa directive.

git diffを実行すると、次のように表示されます。:

diff --git a/tutorial/src/main.py b/tutorial/src/main.py
index b9291c5ca..b9f15b8c1 100644
--- a/numbers/numbers.py
+++ b/numbers/numbers.py
@@ -1,4 +1,4 @@
-from typing import Iterable
+from typing import Iterable  # noqa: UP035

 def sum_even_numbers(numbers: Iterable[int]) -> int:

Integrations#

このチュートリアルでは Ruff のコマンドラインインターフェイスに焦点を当てていますが、Ruff はruff-pre-commitを介してpre-commitフックとしても使用できます。:

- repo: https://github.com/astral-sh/ruff-pre-commit
  # Ruff version.
  rev: v0.1.4
  hooks:
    # Run the linter.
    - id: ruff
    # Run the formatter.
    - id: ruff-format

Ruff は、任意のエディタに統合することもできます。詳細については、Editorsセクションを参照してください。

その他の統合については、Integrationsセクションを参照してください。