Python
Git

コミットの直前にコード整形を走らせる!

More than 1 year has passed since last update.

自己紹介

じゅんじゅんというニックネームで、関西を拠点に活動しているフロントエンドエンジニアです。

HAL大阪の2回生です👍 (2017.3.27現在)

イベントに行くので、大阪らへんの方は会いましょう!

gitにはキレイなコードしかあげたくない...

最近Pythonで開発することが増えて、githubも良い感じにPythonでのコードがおおくなってきたんですが、なんせコードの整形をし忘れてたら汚いインデントのコードを上げることになってしまう...

pep8

pep8とは、Pythonのコードスタイルガイドです。

Style Guide for Python Code

PEP8日本語訳

autopep8

autopep8は、pythonのコードをpep8の基準でインデントを行ってくれたりするコマンドラインツールです。

pipでインストールしておきましょう。

Pythonソースコードを自動でpep8に準拠させるツール-autopep8

コミットの直前にautopep8でコードをキレイにしてコミットするようにする

コミットの直前にスクリプトを動かすにはgitのhooksを使います。

Gitフック

この中の説明の通り

フックはGitディレクトリのhooksサブディレクトリに格納されています。一般的なプロジェクトでは、.git/hooksがそれにあたります。Gitはデフォルトでこのディレクトリに例となるスクリプトを生成します。それらの多くはそのままでも十分有用ですし、引数も記載されています。全ての例は基本的にシェルスクリプトで書かれています。いくつかPerlを含むものもありますが、適切に命名されたそれらの実行可能スクリプトはうまく動きます。RubyやPython等で自作していただいてもかまいません。それらのフックファイルの末尾は.sampleとなっていますので適時リネームしてください。

最初の4つのフックはコミットプロセスに関するものです。pre-commitフックはコミットメッセージが入力される前に実行されます。これはいまからコミットされるであろうスナップショットを検査したり、何かし忘れた事を確認したり、事前にテストを実行したり、何かしらコードを検査する目的で使用されます。git commit --no-verifyで回避することもできますが、このフックから0でない値が返るとコミットが中断されます。コーディングスタイルの検査(lintを実行する等)や、行末の空白文字の検査(デフォルトのフックがまさにそうです)、新しく追加されたメソッドのドキュメントが正しいかどうかの検査といったことが可能です。

このpre-commitというのを使えばいけそう!!!

コードを書きましょう

まず自身の使ってるgitのリポジトリへいきます。.gitというフォルダがあると思うので、その中のhooks/pre-commit.sampleとかいてあるファイルを同じディレクトリの.git/hooks/pre-commitへコピーします。

中身は

#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments.  The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".

if git rev-parse --verify HEAD >/dev/null 2>&1
then
    against=HEAD
else
    # Initial commit: diff against an empty tree object
    against=4b825dc642cb6eb9a060e54bf8d69288fbee4904
fi

# If you want to allow non-ASCII filenames set this variable to true.
allownonascii=$(git config --bool hooks.allownonascii)

# Redirect output to stderr.
exec 1>&2

# Cross platform projects tend to avoid non-ASCII filenames; prevent
# them from being added to the repository. We exploit the fact that the
# printable range starts at the space character and ends with tilde.
if [ "$allownonascii" != "true" ] &&
    # Note that the use of brackets around a tr range is ok here, (it's
    # even required, for portability to Solaris 10's /usr/bin/tr), since
    # the square bracket bytes happen to fall in the designated range.
    test $(git diff --cached --name-only --diff-filter=A -z $against |
      LC_ALL=C tr -d '[ -~]\0' | wc -c) != 0
then
    cat <<\EOF
Error: Attempt to add a non-ASCII file name.

This can cause problems if you want to work with people on other platforms.

To be portable it is advisable to rename the file.

If you know what you are doing you can disable this check using:

  git config hooks.allownonascii true
EOF
    exit 1
fi

# If there are whitespace errors, print the offending file names and fail.
exec git diff-index --check --cached $against --

こんな風になってると思うので、

このファイルへ

autopep8 -i ./**/*.py
echo "python file is auto formatted\n"
git add ./**/*.py

と書き加えて、保存します!

これだけでコミットの直前に.pyのファイルに対してformatをすることができます。

あとがき

Twitterしています!

是非フォローください! @konojunya