Skip to content

Instantly share code, notes, and snippets.

@lentil
Created February 3, 2011 22:55
Show Gist options
  • Save lentil/810399 to your computer and use it in GitHub Desktop.
Save lentil/810399 to your computer and use it in GitHub Desktop.
PEP8 pre-commit hook in Python
#!/usr/bin/env python
from __future__ import with_statement
import os
import re
import shutil
import subprocess
import sys
import tempfile
def system(*args, **kwargs):
kwargs.setdefault('stdout', subprocess.PIPE)
proc = subprocess.Popen(args, **kwargs)
out, err = proc.communicate()
return out
def main():
modified = re.compile('^[AM]+\s+(?P<name>.*\.py)', re.MULTILINE)
files = system('git', 'status', '--porcelain')
files = modified.findall(files)
tempdir = tempfile.mkdtemp()
for name in files:
filename = os.path.join(tempdir, name)
filepath = os.path.dirname(filename)
if not os.path.exists(filepath):
os.makedirs(filepath)
with file(filename, 'w') as f:
system('git', 'show', ':' + name, stdout=f)
output = system('pep8', '.', cwd=tempdir)
shutil.rmtree(tempdir)
if output:
print output,
sys.exit(1)
if __name__ == '__main__':
main()
@umbrae
Copy link

umbrae commented Apr 8, 2015

For anyone else that stumbles onto this, @cowlicks looks to have the better approach. pep8 --diff takes input from stdin, and would indeed catch new files because in order to be committed they would need to be git added to begin with, which means they would show up in git diff --cached. The pre-2014 comments were all before pep8 had diff support, I believe.

@noamhasingit
Copy link

Here is my adjustment to @cowlicks with the following changes:

  1. support windows gawk instead of awk
  2. replace pep8 with pycodestyle which is the new style replacing pep8
    Add this to your .git/hooks/pre-commit project:

FILES=($(git diff --cached --name-status | grep -v ^D | gawk '$1 $2 { print $2}' | grep -e .py$))
for FILE in ${FILES[*]}; do
pycodestyle ${FILE}
done

@peterjc
Copy link

peterjc commented Oct 24, 2018

A custom script still has its uses (e.g. if you need to run other linting checks outside of the Python style checks), but nowadays I typically use the command line tool flake8 (which incorporates the pep8 aka pycodestyle checks, and has a number of plugins available adding even more linting checks) with a configuration file as needed (e.g. setting the max-line-length), and its default git pre-commit hook, setup as follows:

$ flake8 --install-hook git
$ git config --bool flake8.strict true

See http://flake8.pycqa.org/en/latest/user/using-hooks.html

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment