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