🔧

Ruff(Pythonのlinter)を導入してみた🦾

2024/01/16に公開

保育ICTを愛するみなさまこんにちは、H.G.M developers T.K です。

はじめに

Ruffにformatter機能(Blackの機能)が追加されたことを知ったことが作業に至るきっかけでした。
所属プロジェクトではlinterは既にFlake8, isort, Blackを導入しておりましたが、Ruffの導入で1つに統合できかつRust製で高速に処理できるため業務改善に繋がるのではないかと考え作業に当たりました。

この記事を読んで欲しい人

  • Pythonの開発でlinterを検討している方
  • 開発エディタでVS Codeを利用している方

開発環境

  • Mac M1
  • VS Code
  • Python 3.10

ライブラリ

  • husky: 7.0.4
  • lint-staged: 12.5.0

やったこと

  • VS CodeにRuffの拡張機能を追加
  • VS CodeのWorkspaceにRuffの設定記載
  • pre-commit時にRuffのcheckコマンドを実行する設定

VS Codeの拡張機能

VS Codeの拡張機能「Ruff」を有効化します。
Ruff | VS Code Marketplace
VS CodeのRuffの拡張機能

Workspaceの設定

Workspaceはチーム開発の際に、各メンバーでVS Codeの共通設定を行うための設定です。

各メンバーの開発環境でlinterが別々の設定になっていたりすると、レビューの際に余計な差分を確認することになるので、時間を浪費してしまいます。開発する上でコードの一貫性を保つことや開発スピード向上のためにも、チーム開発の際にはWorkspaceの設定を整えています。

Workspaceでは「TypeScript」「JSON」など言語ごとの様々な設定が可能ですが、ここでは「Ruff」の設定のみを記載します。

.VS Code/{プロジェクト名}.code.workspace
{
  "settings": {
    ・・・
    "[python]": {
        "editor.tabSize": 4,
        "editor.formatOnSave": true,
        "editor.defaultFormatter": "charliermarsh.ruff",
        "editor.codeActionsOnSave": {
            "source.fixAll.ruff": true,
            "source.organizeImports.ruff": true
        }
    }
  }
  "extensions": {
    "recommendations": [
      ・・・
      "charliermarsh.ruff",
    ]
  }
}

こちらの設定で行なっていることを簡単に説明します。

  • editor.formatOnSave: ファイル保存時にフォーマットチェックを行います
  • editor.defaultFormatter: formatterにRuffの拡張機能を指定します
  • editor.codeActionsOnSave:
    • source.fixAll.ruff: lint違反を修正してくれます
    • source.organizeImports.ruff: 保存時にimportを整理してくれます
  • recommendations: 開発環境で共通で利用するVS Codeの拡張機能の識別子を追記します。VS CodeをWorkspaceから起動することで、おすすめの拡張機能として右下にポップアップが表示されます

VS Codeのおすすめ拡張機能のポップアップ画像

ruffの定義ファイルの作成

プロジェクト直下にRuffの定義ファイルを作成します。

pyprojyect.toml
[tool.ruff]
select = [
    "F", # Flake8
    "B", # Black
    "I", # isort
    "E", # error
    "W"  # warning
]
ignore = []
fixable = ["ALL"]
exclude = [
    ".ruff_cache"
]
line-length = 119
indent-width = 4
target-version = "py310"

[tool.ruff.per-file-ignores]
"__init__.py" = ["F401", "F403"]

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

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

pre-commit時の設定

開発プロジェクトでは、huskyとlint-stagedを採用しております。
huskyはGitのフックを利用できるnpmライブラリで、Gitのpre-commitをフックし、Ruffのcheckを実行することでcommit前にコードフォーマットをチェックするようにしました。
※huskyとlint-stagedのインストール方法は省略させて頂きます。

hooksの作成

npx husky add .husky/pre-commit "npm lint-staged"

コマンド実行後に、「.husky/pre-commit」が作成されますので、下記のように編集します。

.husky/pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"

pnpm lint-staged

lint-stagedの設定

コミット時にRuffのcheckコマンドを実行するように記述しております。

package.json
{
  ・・・
  "lint-staged": {
    "*.py": "pipenv run ruff check --fix"
  }
}

補足

おわりに

開発前のFlake8, isort, Blackと同様の機能をRuffにまとめられて管理が楽になりました。

今回の導入に当たりメンバー間で「ruff checkのルールをできる限りデフォルトの状態で使いたい。」と意見があり、最低限の設定で実装できるように検討しました。しかし、デフォルトの設定では、Ruffの導入時にはやはりlinterのエラーや警告が100件ほど発生したため、「pyproject.tomlのignoreに"B008"を記述しエラーを無視する設定」や「コード修正により対応」をする必要がありました。Ruffをデフォルトの設定のまま利用することは理想ではありますが、既に開発途中のプロジェクトではコードの記述が統一されていたりコーディング規約があったりとの兼ね合いから、やはりプロジェクト毎に適したRuffのルール定義の見直しは必要だと感じました。

pre-commitの処理は、ruff-pre-commitのライブラリもありますが、現行プロジェクトでは、lint-stagedにまとめて記述してのTypeScriptのESLintなどの他の処理も一元管理しています。

プロジェクトの規模からそれほど速度面の向上は感じられませんでしたが、今後プロジェクト拡大した際には速度面の恩恵を受けられることに期待したいです。

以上、H.G.M developers T.K でした。

Discussion