언어/파이썬 & 장고

[Python] pre-commit, black, flake8 적용하기

불곰1 2022. 2. 6. 15:36

git hook을 사용하여 커밋하기 전에 code style chek, formmatter, test 등등과 같은 사용자가 원하는 동작을 처리할 수 있습니다. 사용자가 추가한 단계에서 실패가 되면 커밋은 이뤄지지 않기 때문에 프로젝트의 품질을 올릴 수 있는 좋은 도구입니다.

여기서는 pre-commit을 사용하여 flake8로 코드 스타일을 체크하고 black으로 자동으로 코드 포매팅을 하도록 설정하도록 합니다.

아래는 변경된 파일부터 pre-commit, commit 의 과정을 설명하는 예시입니다.

https://ljvmiranda921.github.io/notebook/2018/06/21/precommits-using-black-and-flake8/

pre-commit 설치

$ pip install pre-commit

# 또는 

$ brew install pre-commit

$ pre-commit --v
pre-commit 2.17.0

설정

pre-commit을 적용하기 위해선 .pre-commit-config.yaml 설정 파일이 필요합니다. 샘플 설정을 출력해주는 명령어를 사용해 설정파일을 생성합니다.

$ pre-commit sample-config > .pre-commit-config.yaml

해당 파일을 열면 아래와 같이 샘플이 저장되어 있습니다.

# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
repos:
  - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v3.2.0
    hooks:
      - id: trailing-whitespace
      - id: end-of-file-fixer
      - id: check-yaml
      - id: check-added-large-files

pre-commit은 공개되어 있는 Git 저장소로부터 hook을 설치하여 실행합니다. pre-commit 에서 다양한 hook 주소를 확인할 수 있습니다.

우리는 여기서 black과 flake8이 필요하므로 아래와 같이 위의 설정 파일을 수정합니다.

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v3.2.0
    hooks:
    -   id: trailing-whitespace
    -   id: check-yaml
    -   id: check-json
-   repo: https://github.com/psf/black
    rev: stable
    hooks:
    - id: black
      language_version: python3.8
-   repo: https://gitlab.com/pycqa/flake8
    rev: 4.0.1
    hooks:
    - id: flake8

실행은 위에서 설정한 순서대로 진행이 됩니다.

만약 flake8에 적용된 lint를 변경하고 싶다면 .flake8 파일을 생성하면 됩니다. 아래는 80자 제한을 120자로 늘린 예시입니다.

[flake8]
max-line-length = 120

다음 버전이 맞게 명시되었는지 아래와 같이 autoupdate를 진행해 줍니다.

$ pre-commit autoupdate
[WARNING] The 'rev' field of repo 'https://github.com/psf/black' appears to be a mutable reference (moving tag / branch).  Mutable references are never updated after first install and are not supported.  See https://pre-commit.com/#using-the-latest-version-for-a-repository for more details.  Hint: `pre-commit autoupdate` often fixes this.
Updating https://github.com/pre-commit/pre-commit-hooks ... [INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
updating v3.2.0 -> v4.1.0.
Updating https://github.com/psf/black ... [INFO] Initializing environment for https://github.com/psf/black.
updating stable -> 22.1.0.
Updating https://gitlab.com/pycqa/flake8 ... [INFO] Initializing environment for https://gitlab.com/pycqa/flake8.
updating 4.0.1 -> 3.9.2.

pre-commit 등록

커밋이 될 때마다 위에서 설정한 파일이 pre-commit 단계에서 실행되도록 명령어를 입력해 줘야 합니다.

$ pre-commit install
pre-commit installed at .git/hooks/pre-commit

테스트

등록이 정상적으로 진행됐는지 아무 아래와 같이 lint가 깨지는 코드를 추가하여 commit을 진행해 봅니다.

def test_answer():
    assert 3 == 2
def test_tc2():
    assert 1==1
$ git commit -m 'pre-commit test'
[WARNING] The 'rev' field of repo 'https://github.com/psf/black' appears to be a mutable reference (moving tag / branch).  Mutable references are never updated after first install and are not supported.  See https://pre-commit.com/#using-the-latest-version-for-a-repository for more details.  Hint: `pre-commit autoupdate` often fixes this.
[INFO] Initializing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Initializing environment for https://github.com/psf/black.
[INFO] Initializing environment for https://gitlab.com/pycqa/flake8.
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/psf/black.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://gitlab.com/pycqa/flake8.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
Trim Trailing Whitespace.................................................Passed
Check Yaml...............................................................Passed
Check JSON...........................................(no files to check)Skipped
black....................................................................Failed
- hook id: black
- files were modified by this hook

reformatted tests/test_pytest.py

All done! ✨ 🍰 ✨
1 file reformatted.

flake8...................................................................Passed

이후 해당 파일을 다시 확인하면 아래와 같이 수정이 되어 있는 것을 볼 수 있습니다.

def test_answer():
    assert 3 == 2

def test_tc2():
    assert 1 == 1

이렇게 자동으로 변경된 파일은 다시 stage로 올리고 커밋을 진행하면 성공적으로 호출되는 것을 확인할 수 있습니다.

[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/psf/black.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://gitlab.com/pycqa/flake8.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
trim trailing whitespace.................................................Passed
check yaml...............................................................Passed
check json...........................................(no files to check)Skipped
black....................................................................Passed
flake8...................................................................Passed
[develop 5a2bb38] lint 변경
 2 files changed, 20 insertions(+)
 create mode 100644 .pre-commit-config.yaml