Python project用にlinter / formatterを一通り整備する
Python で自作モジュールを実装する際に、linter / formatter を一通り整備したので理解した内容を備忘録的にまとめてみます。
flake8 (linter)
flake8 は pycodestyle, pyflakes, mccabe の 3 つの linter をまとめた wrrapper ツールです。
pycodestyle は、PEP8にまとめられているコーディング規約をベースにしており、コードスタイルについてのチェックを行います。
コードスタイルに違反している箇所がある場合は、行数と下記の Document に定義されたエラーコードが返されます。
設定自体は、pyproject.toml 側に定義しています。
後述する、tox の設定ファイル(tox.ini
)にも記述できますが、ツール群の設定をなるべく一箇所に寄せるという意味でも pyproject.toml に記述しています。
flake8 --extend-ignore=W234
のようにコマンド実行時に option 指定する設定も pyproject.toml に定義します
オプション自体は下記の Document を参考にします。
[flake8]
max-line-length = 120
extend-ignore = W234
コードを書きながら CI で lint を回して、必要に応じて特定のエラー自体を ignore したり、in-line で ignore する形で調整しています。
black (formatter)
ソースコードを自動で整形する code formatter です。
--include
, --exclude
のような対象・除外ファイルの指定はできますが、black 自体は設定の余地が少なく制限が強いのが特徴です。
pyproject.toml にも対応しているので、black の設定も寄せています。
[tool.black]
target-version = ['py38', 'py39']
isort
また、上記に加えて、import 文を自動で整理するツールとして isort も利用しています。
これにより PEP8 に準拠した import の順序に修正できます。
オプションは下記の Document にまとめられており、一部ですが pyproject.toml
のサンプルもあります。
注意点として、既に利用している formatter と設定が conflict するケースがあるので、それを避けるために isort 側で formatter(black)を profile として指定します。
[tool.isort]
profile = "black"
lines_after_imports = 2
mypy
今回の Python project は、python3.9,10 を前提にしているので、型アノテーションをもとに静的型チェックを行う mypy も利用します。
型アノテーション自体は Python3.5 から導入されたType Hintsを利用しており、mypy の公式 Document にチートシートもあるので、この辺りを参考にアノテーションを付けていきます。
設定自体は mypy.ini
にも定義可能ですが、mypy の設定も pyproject.toml
に寄せます。
グローバルな設定を定義する section と module ごとの設定を定義する section に分かれており、module ごとの設定は [[tool.mypy.overrides]]
配下に module 名を指定する形で定義します。
モジュール名自体はワイルドカード指定できるので、特定のモジュール群に対してまとめて設定を適用することも可能です。
[tool.mypy]
python_version = "3.9"
mypy_path = ["src"]
[[tool.mypy.overrides]]
module = 'google.cloud.*'
ignore_missing-imports = true
linter / formatter などの各種ツールを紹介してきましたが、最後にツールの自動フックや実行周りの設定についても触れます。
pre-commit
これまで取り上げたようなツール群をまとめて実行するためのツールが pre-commit です。
.pre-commit-config.yaml
に hook する対象ツールの定義を書き、pre-commit install
を実行することで Git 標準の pre-commit hook として利用できます。
repos:
- repo: https://github.com/pycqa/isort
rev: 5.10.1
hooks:
- id: isort
- repo: https://github.com/psf/black
rev: 21.11b1
hooks:
- id: black
...
一方で、pre-commit run --all-files
のような形で手動実行もできるので、都度実行の場合は Makefile にタスクとして定義しておくのが良さそうです。
.PHONY: lint
lint: ## Run linter and formatter
.venv/bin/pre-commit run --all-files
終わりに
ざっと、linter / formatter を整備した時の内容をまとめてみました。
一通り整備していると正直セットアップだけでコストがかかるので、今であれば pysen などの整備用のツールを利用するのが良さそうと思います。
Discussion