pre-commitでPythonの開発環境を整備する
2020-01-26
- プログラミング
Pythonを使った開発をしているとき、コードレビューでコーディングスタイルなどに関する表面的な指摘をするのが面倒だ。効率化するために、コミットの時点でこれらについてのチェックを自動で行い、エラーになった場合はコミットできないようにする。
はじめGit標準のpre-commit hookでやろうと思っていたが、pre-commitの方が設定や管理が楽そうなので、これを選んだ。
やりたいこと
コミット時に以下のチェックを行い、NGならコミットできなくする。
pre-commitとは
Git標準のpre-commit hookを管理するためのツール。設定はyaml管理で書ける。
言語としてはPython以外にGolang、Rustなどもサポートしている。
方法
-
pre-commitのインストール
pip3 install pre-commit
-
対象のローカルリポジトリのルートにcd
当然だが、git管理されているリポジトリでないといけない。 -
.pre-commit-config.yaml
の作成・編集
.pre-commit-config.yaml
という名前でファイルを作り、以下のように書く。なおrev
はそのrepo
で使いたいリビジョンやタグを書く。- repo: https://github.com/pre-commit/mirrors-autopep8 rev: v1.5 hooks: - id: autopep8 - repo: https://gitlab.com/pycqa/flake8 rev: 3.7.9 hooks: - id: flake8 - repo: https://github.com/pre-commit/mirrors-mypy rev: v0.761 hooks: - id: mypy args: [--ignore-missing-imports]
-
Gitのpre-commit hookの設定
pre-commit install
(この時点では
.pre-commit-config.yaml
に書いた各種ツールはまだダウンロードしていない。単にそのリポジトリの.git
以下にhookスクリプトが入るだけ。ダウンロードするのは次回のコミット時。)
これで設定完了。あとはいつも通り、ファイル修正して git add
& git commit
すればいい。設定したチェックが走り、エラーがあればコミットができなくなる。
なお以下のコマンドならコミットのタイミング以外でもチェックできる。
pre-commit run --all-files
試す
以下のような問題のあるコード(app.py
)をコミットしようとした。
msg:int="Hello, world!"
print( msg )
チェックされて、次のようなエラー。コミットできない!(flake8によるチェックが通っているのはautopep8が修正したため。)
$ git commit
autopep8.................................................................Failed
- hook id: autopep8
- files were modified by this hook
flake8...................................................................Passed
mypy.....................................................................Failed
- hook id: mypy
- exit code: 1
- files were modified by this hook
app.py:1: error: Incompatible types in assignment (expression has type "str", variable has type "int")
Found 1 error in 1 file (checked 1 source file)
以下のように修正して再コミット。(フォーマットはautopep8がやってくれたので、型ヒントだけ修正すればいい。)
msg: str = "Hello, world!"
print(msg)
これで通る。
$ git commit
autopep8.................................................................Passed
flake8...................................................................Passed
mypy.....................................................................Passed
あとはいつもと同じ。
補足
.pre-commit-config.yaml
に書いたautopep8とかはどこに入ったのだろうと探したら ~/.cache/pre-commit
以下に入っていた。これはpre_commit/store.pyで設定しているよう。
参考
- pre-commit
pre-commit公式。全部これに書いてある。 - pre-commit/hooks
pre-commitで使えるhookのリンク集。Python以外もある。 - pre-commit/mirrors-autopep8
autopep8のpre-commit。 - Using Version Control Hooks — flake8 3.7.9 documentation
flake8公式。pre-commitの設定方法について。 - pre-commit/mirrors-mypy
mypyのpre-commit。