Skip to content

Instantly share code, notes, and snippets.

@taschik
Created June 27, 2018 02:57
Show Gist options
  • Save taschik/365f4bd2ddd7498cdd40759a5e417fad to your computer and use it in GitHub Desktop.
Save taschik/365f4bd2ddd7498cdd40759a5e417fad to your computer and use it in GitHub Desktop.
pycodestyle and pyflakes git hook

Requirements

  • Python >= 3.x
  • pycodestyle
  • pyflakes

Installation

cd path/to/repository/
wget https://gist.githubusercontent.com/Kilte/a4a9973ccc239136404fb70564c9d72b/raw/9374954a78ec00365ea1c040e0f8a4c03e877b3b/pre-commit -O .git/hooks/pre-commit
chmod +x .git/hooks/pre-commit
#!/usr/bin/env python3
import re
import subprocess
import sys
import pycodestyle
import pyflakes.api
import pyflakes.reporter
MAX_LINE_LENGTH = 100
def subprocess_call(cmd, cwd=None):
p = subprocess.Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE, cwd=cwd)
out, err = p.communicate()
return out.decode('utf-8'), err.decode('utf-8'), p.returncode
def find_modified_files(ext):
modified = re.compile('^(?:M|A).(?P<name>.*\.%s)' % ext)
out, _, _ = subprocess_call('git status --porcelain')
result = []
for line in out.splitlines():
match = modified.match(line.strip())
if match:
result.append(match.group('name').strip())
return result
class PEP8Report(pycodestyle.BaseReport):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self._deferred_output = []
def error(self, line_number, offset, text, check):
self._deferred_output.append('{0}:{1}: {2}'.format(self.filename, line_number, text))
return super().error(line_number, offset, text, check)
def get_results(self):
return self._deferred_output
def run_pycodestype(paths):
style_guide = pycodestyle.StyleGuide(
parse_argv=False,
config_file=False,
max_line_length=MAX_LINE_LENGTH,
reporter=PEP8Report
)
return style_guide.check_files(paths).get_results()
def run_pyflakes(paths):
reporter = pyflakes.reporter._makeDefaultReporter()
return pyflakes.api.checkRecursive(paths, reporter)
def main():
paths = find_modified_files('py')
if not paths:
return
exitcode = 0
results = run_pycodestype(paths)
if results:
print('PEP8 style violations have been detected.')
for i in results:
print(i)
exitcode = 1
if run_pyflakes(paths):
print('^' * 20)
print('Pyflakes violations have been detected.')
exitcode = 1
if exitcode != 0:
print('Please fix them or force the commit with "git commit --no-verify".')
sys.exit(exitcode)
if __name__ == '__main__':
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment