PythonプロジェクトでRuffをPre-commitに設定してコード品質を上げてみる

2023.11.29

はじめに

データアナリティクス事業本部のkobayashiです。

Pythonコードでコード品質を上げるためはソースコードを整形するformatterのBlack、import文をソートするisort、ソースコードを解析してくれるLinterのflake8が定番の静的解析ツールかと思います。新規にPythonプロジェクトを始めるに当たりblack+isort+falke8と同等の機能を持つRuffを導入してみたのでその内容をまとめます。

astral-sh/ruff: An extremely fast Python linter and code formatter, written in Rust.

Ruffとは

Ruffとは、2022年にリリースされた比較的新しい静的解析ツールで、Rustで書かれています。同等の機能を持つ他のツールよりも高速に動作することが特徴です。さらに、一つのツールでFlake8(及びその数十のプラグイン)、Black、isort、pydocstyle、pyupgrade、autoflakeなど、多くの機能を統合することを目指しているツールになります。

Linterとしての機能は以前からあったのでRuffとblackを組み合わせて静的解析ツールとして使うパターンが多く見られるのですが、2023年10月にformatterの機能をサポートしたため今後はRuff一つで静的解析ツールとしての要件を満たすようになりました。

The Ruff Formatter: An extremely fast, Black-compatible Python formatter

RuffをPythonプロジェクトに導入してみる

環境

  • Python: 3.11.6

ではRuffをPythonプロジェクトに導入してみます。まずは前提条件としてプロジェクトはgitで管理されていてリモートのリポジトリとしてはGithubを使っている状態です。この上で具体的な導入内容としては

  • Ruffのインストールと設定
  • pre-commitでRuffの設定

を行ってgitでPythonコードをcommitする際にruffのformatterとlintを強制するようにしてコードの品質を保ちたいと思います。

Ruffのインストールと設定

インストールはいつも通りpipでインストールします

$ pip install ruff
$  pip list | grep ruff
ruff                       0.1.6

次にRuffの設定ですがRuffはpyproject.tomlをサポートしているのでRuffの設定をpyproject.tomlにまとめることが可能です。

プロジェクトディレクトリ直下にpyproject.tomlを作成します。

pyproject.toml

[tool.ruff]
line-length = 120
indent-width = 4
target-version = "py311"

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

fixable = ["ALL"]

[tool.ruff.lint.mccabe]
max-complexity = 5

[tool.ruff.isort]
force-single-line = true

[tool.ruff.format]
quote-style = "double"
indent-style = "space"
skip-magic-trailing-comma = false
line-ending = "auto"

主な設定箇所としては[tool.ruff]のブロックで使用するPythonのバージョンは3.11にしています。デフォルトですと3.10なので3.11を使う場合は明示的に指定する必要があります。次に[tool.ruff.lint]でlinterの設定を行っています。selectで使うlintのルールを指定します。また[tool.ruff.format]でformatterの設定を行っています。これらの設定はRuffの公式ページに設定値と詳しい解説があるのでそちらをご確認ください。

pre-commitでRuffの設定

次にpre-commitにRuffを設定してcommit時にRuffでformtterとlintで静的解析を強制したいと思います。

pre-commitを使うので予めpre-commitをインストールしておく必要があります。

$ brew install pre-commit
$ pre-commit install

インストールが終わったらプロジェクトディレクトリ直下に.pre-commit-config.yamlを作成します。

.pre-commit-config.yaml

repos:
  - repo: https://github.com/charliermarsh/ruff-pre-commit
    rev: v0.1.6
    hooks:
      - id: ruff
      - id: ruff-format

pre-commitのruffの設定は非常に簡単で上記の設定をすればcommit時にRuffで静的解析を行い、失敗すればcommitを拒否することができるようになります。

実際にコーディングルールを満たさない状態でcommitしようとすると以下のようにcommitがエラーになります。

ruff.....................................................................Failed
- hook id: ruff
- exit code: 1
app/models.py:8:8: F401 [*] `os` imported but unused
Found 1 error.
[*] 1 fixable with the `--fix` option.
ruff-format..............................................................Failed
- hook id: ruff-format
- files were modified by this hook
1 file reformatted, 4 files left unchanged

まとめ

Pythonプロジェクトの静的解析ツールとしてRuffを使ってみました。Ruffは非常に高速に動作するのでこれまで他のツールで行っていて実行速度が問題になっていた場合は最適だと思います。またpre-commitでRuffを設定することでルールを満たさないコードをcommitすることができなくなりコードが一定の品質であることを担保できるようになるのでチームでの開発では必須ではないかと思います。

最後まで読んで頂いてありがとうございました。