Skip to content

Instantly share code, notes, and snippets.

@snim2
Created September 5, 2013 00:50
Show Gist options
  • Select an option

  • Save snim2/6444684 to your computer and use it in GitHub Desktop.

Select an option

Save snim2/6444684 to your computer and use it in GitHub Desktop.

Revisions

  1. snim2 created this gist Sep 5, 2013.
    99 changes: 99 additions & 0 deletions pre-commit.py
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,99 @@
    #!/usr/bin/env python

    """
    Git pre-commit hook to enforce PEP8 rules and run unit tests.
    Copyright (C) Sarah Mount, 2013.
    This program is free software; you can redistribute it and/or
    modify it under the terms of the GNU General Public License
    as published by the Free Software Foundation; either version 2
    of the License, or (at your option) any later version.
    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    GNU General Public License for more details.
    You should have received a copy of the GNU General Public License
    along with this program. If not, see <http://www.gnu.org/licenses/>.
    """

    import os
    import re
    import subprocess
    import sys

    __author__ = 'Sarah Mount <[email protected]>'
    __date__ = 'September 2013'

    modified_re = re.compile(r'^[AM]+\s+(?P<name>.*\.py)', re.MULTILINE)


    def get_staged_files():
    """Get all files staged for the current commit.
    """
    proc = subprocess.Popen(('git', 'status', '--porcelain'),
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE)
    out, _ = proc.communicate()
    staged_files = modified_re.findall(out)
    return staged_files


    def main():
    abort = False
    # Stash un-staged changes.
    subprocess.call(('git', 'stash', '-u', '--keep-index'),
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE,)
    # Determine all files staged for commit.
    staged_files = get_staged_files()
    # Enforce PEP8 conformance.
    print
    print '============ Enforcing PEP8 rules ============='
    for filename in staged_files:
    subprocess.call(('pep8ify', '-w', filename))
    try:
    os.unlink(filename + '.bak')
    except OSError:
    pass
    subprocess.call(('git', 'add', '-u', 'filename'))
    print
    print '========== Checking PEP8 conformance =========='
    for filename in staged_files:
    proc = subprocess.Popen(('pep8', filename),
    stdout=subprocess.PIPE)
    output, _ = proc.communicate()
    # If pep8 still reports problems then abort this commit.
    if output:
    abort = True
    print
    print '========= Found PEP8 non-conformance =========='
    print output
    # Run unit tests.
    print
    print '============== Running unit tests ============='
    print
    proc = subprocess.Popen(['python', 'pytest.py', 'tests'],
    stdout=subprocess.PIPE,
    stderr=subprocess.PIPE)
    out, _ = proc.communicate()
    print out
    if 'FAILURES' in out:
    abort = True
    # Un-stash un-staged changes.
    subprocess.call(('git', 'stash', 'pop', '-q'),
    stdout=subprocess.PIPE)
    # Should we abort this commit?
    if abort:
    print
    print '=============== ABORTING commit ==============='
    sys.exit(1)
    else:
    sys.exit(0)
    return


    if __name__ == '__main__':
    main()