pysen を使って python の lint 環境をまとめる
pysen とは
このツールは主にPython向けのlinter/formatterの設定を一元管理し、Preferred Networks社内でよく使われているツール環境を誰でも簡単に設定できるように支援するツールです。チームごとに分散しうるようなツールに関するノウハウをコードとして集約し、PFN社内での共有を促進させることを目的として開発しています。pysenは実際にPFN社内で使われており、2020年4月に開発がスタートしてから、2021年3月現在でおよそ100を超える社内リポジトリに導入されています。
Pythonのlinter/formatterを誰でも手軽に設定できるようにするためのPFN社内ツール “pysen” の紹介 より引用
できること
- black, mypy, flake8, isort の lint の同時実行
- black, isort を使った format の実行
pysen を用いることで、上記のような、複数ツールを使った lint, format が、pysen の支配下で簡単に行えるようになります。
かゆいところに手が届くポイント
各 pysen でインストールされたコンポーネントは、 pysen を経由せずに直接実行することもできるので、pysen に一気に乗り換えるのは怖いけど…みたいな場合にもお手軽に導入できます。
ここでやること
pysen の簡単な使い方と、vscode との連携方法について、自分で作業していて少し詰まったポイントとともに、順に書いていきます。
環境
- OS
- Ubuntu
- Docker
- python:3.9-slim
- パッケージ管理ツール
- poetry
- フレームワーク
- django
使ってみる
インストール
poetry add -D pysen -E lint
これで pysen 用の依存関係諸々がインストールされる。
poetry add -D pysen
だけだと、初期状態では依存が足りないので注意。
git のインストール
コマンド実行時に git を使うので、docker を使っているとかで環境にない場合はインストールして呼び出せるようにしておく。
設定
pysen 用の設定を pyproject.toml
に追記する。
[tool.pysen]
version = "0.9"
[tool.pysen.lint]
enable_black = true
enable_flake8 = true
enable_isort = true
enable_mypy = true
mypy_preset = "strict"
line_length = 88
py_version = "py37"
[[tool.pysen.lint.mypy_targets]]
paths = ["."]
もっと細かい設定
pysen generate .
を実行することで、細かい設定用のファイルが生成されるので、それを通じて行う。(あまり確認できてない)
改めて確認すると、設定をexportするだけで、ここの設定が適用されるとは書いていない気がする。builder
で細かく設定するようなことも書いてあったので、細かい調整はそっちでするのかも。確認できたらまた更新する。
ref: https://github.com/pfnet/pysen#how-it-works-settings-file-directory
実行
lint
- black
- flake8
- isort
- mypy
上記のツールを組み合わせて実行され、それぞれの項目で lint の実行結果を見ることができる。
pysen run lint
# 例
Running commands concurrently...
... concurrent execution done
Running: black
Checking 6 files
error: cannot format /workspace/django_pysen/settings.py: Cannot parse: 16:8: BASE_DIR = Path(__file__).resolve().parent.parent
Oh no! 💥 💔 💥
5 files would be left unchanged, 1 file would fail to reformat.
Running: flake8
Checking 6 files
/workspace/django_pysen/settings.py:16:9: E221 multiple spaces before operator
/workspace/django_pysen/settings.py:16:10: E999 SyntaxError: invalid non-printable character U+3000
Running: isort
Checking 6 files
Running: mypy
[1/1] Checking 1 entries
/workspace/django_pysen/settings.py:16: error: invalid non-printable character
U+3000 [syntax]
BASE_DIR = Path(__file__).resolve().parent.parent
^
Found 1 error in 1 file (checked 6 source files)
** execution summary **
isort .......... OK (0.48 sec)
black .......... Failed (0.41 sec)
flake8 .......... Failed (0.46 sec)
mypy .......... Failed (0.31 sec)
lint finished with error(s)
Errored:
- black
- flake8
- mypy
format
lint でチェックした項目のうち、自動修正が可能な項目に対して変更がかかる。
pysen run format
# 例
Running commands
Running: isort
Checking 6 files
Running: black
Checking 6 files
reformatted /workspace/django_pysen/wsgi.py
reformatted /workspace/django_pysen/settings.py
All done! ✨ 🍰 ✨
2 files reformatted, 4 files left unchanged.
** execution summary **
isort .......... OK (0.40 sec)
black .......... OK (0.35 sec)
ファイル、ディレクトリごとに実行
run_files
を使うことで、path 指定で、それ以下に対して lint or format のコマンドを実行できる。
pysen run_files lint {path}
VSCode で使ってみる
拡張機能のアンインストール
ms-python.python
をインストールしているとこの後入れる pysen 側の拡張機能と衝突するので、先に外しておく。
pysen-ls
VSCode と連携するために、pysen に対応した language server を入れる。
(pyproject に pysen-ls の記述が入ってしまうため、 poetry で入れないほうが良いのかもしれない?)
poetry add -D pysen-ls
拡張機能のインストール
bonprosoft.pysen-vscode
をインストールする。
動きを確認する
formatOnSave
に指定するもよし、Format Current Document
で実行するもよし。
PROBLEMS のタブでもちゃんと確認できる。
参考
- https://github.com/pfnet/pysen
- https://tech.preferred.jp/ja/blog/pysen-is-the-new-sempai/
- https://twitter.com/bonprosoft/status/1375819767915769858
Discussion