Created
August 1, 2017 06:36
-
-
Save inesusvet/afa7643c8bad34832a42dfc7eb0ee781 to your computer and use it in GitHub Desktop.
Git pre-commit hook to check code style of changed files right at commit time
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import print_function | |
""" | |
Pre-commit hook for PEP8 styling | |
Works well with flake8==3.0.4 | |
""" | |
__author__ = 'Ivan Styazhkin <[email protected]>' | |
import subprocess | |
import sys | |
CHANGES_CMD = 'git diff --name-only --cached --diff-filter=ACM'.split() | |
GIT_HASH_CMD = 'git ls-files --stage'.split() | |
GIT_FILE_CONTENT_CMD = 'git cat-file blob'.split() | |
# Presonal preferences for ignoring | |
IGNORED_ERRORS = ( | |
'F403', # 'from models import *' used; unable to detect undefined names | |
'F405', # assert_that may be undefined, or defined from star imports: hamcrest | |
) | |
MAX_LINE_LENGTH = 100 | |
FLAKES_CMD = [ | |
'flake8', | |
'-', | |
'--ignore=%s' % ','.join(IGNORED_ERRORS), | |
'--max-line-length=%s' % MAX_LINE_LENGTH, | |
] | |
def get_lines(stdout_text): | |
"""Assumes your console uses utf-8""" | |
return stdout_text.strip().decode('utf-8').split('\n') | |
def get_python_changes(): | |
"""Returns python filenames which are staged""" | |
python_changes = get_lines(subprocess.check_output(CHANGES_CMD)) | |
return [s for s in python_changes if s.endswith('.py')] | |
def get_staged_file_content(filename): | |
"""Returns staged version of the file""" | |
hash_line = subprocess.check_output(GIT_HASH_CMD + [filename]) | |
_, file_hash, _, _ = hash_line.split() | |
return subprocess.check_output(GIT_FILE_CONTENT_CMD + [file_hash]) | |
def main(stream): | |
filename_list = get_python_changes() | |
if not filename_list: | |
return | |
error_list = list() | |
for filename in filename_list: | |
content = get_staged_file_content(filename) | |
pipe = subprocess.Popen( | |
FLAKES_CMD, | |
stdin=subprocess.PIPE, | |
stdout=subprocess.PIPE, | |
) | |
pipe.stdin.write(content) | |
out, _ = pipe.communicate() | |
if out: | |
error_list.extend([ | |
line.replace('stdin', filename) | |
for line in get_lines(out) | |
]) | |
if not error_list: | |
print('\033[92mCheck flake8: OK\033[0m') | |
return | |
print('\033[91mCheck %d files for flake8: %d errors\033[0m' % (len(filename_list), len(error_list))) | |
for error in error_list: | |
print(error) | |
return 1 | |
if __name__ == '__main__': | |
exit(main(sys.stdout)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment