Branch: master
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
174 lines (148 sloc) 5.18 KB
#!/usr/bin/env python
Forked From
import os
import re
import subprocess
import sys
modified = re.compile('^[MA]\s+(?P<name>.*)$')
'output': 'Checking for pdb and ipdbs...',
'command': 'grep -n "import [i]*pdb" %s',
'ignore_files': ['.*pre-commit'],
'print_filename': True,
'exists': False,
'package': ''
'output': 'Checking for print statements...',
'command': 'grep -n "^\s*\bprint" %s',
'match_files': ['.*\.py$'],
'ignore_files': ['.*migrations.*', '.*management/commands.*',
'.*', '.*/scripts/.*'],
'print_filename': True,
'exists': False,
'package': ''
'output': 'Checking for console.log()...',
'command': 'grep -n console.log %s',
'match_files': ['.*\.js$'],
'print_filename': True,
'exists': False,
'package': ''
'output': 'Checking for debugger...',
'command': 'grep -n debugger %s',
'match_files': ['.*\.js$'],
'print_filename': True,
'exists': False,
'package': ''
'output': 'Running Jshint...',
'command': 'jshint %s | grep -v "Lint Free!"',
'match_files': ['.*\.js$'],
'print_filename': False,
'exists': True,
'package': 'jshint'
'output': 'Running Pyflakes...',
'command': 'pyflakes %s',
'match_files': ['.*\.py$'],
'ignore_files': ['.*settings/.*', '.*',
'.*migrations.*', '.*/terrain/.*'],
'print_filename': False,
'exists': True,
'package': 'pyflakes'
'output': 'Running pep8...',
'command': 'pep8 -r --ignore=E501,W293 %s',
'match_files': ['.*\.py$'],
'ignore_files': ['.*migrations.*'],
'print_filename': False,
'exists': True,
'package': 'pep8'
def highlight(text, status):
attrs = []
colors = {
'green': '32', 'red': '31', 'yellow': '33'
if not sys.stdout.isatty():
return text
attrs.append(colors.get(status, 'red'))
return '\x1b[%sm%s\x1b[0m' % (';'.join(attrs), text)
def exists(cmd, error=True):
devnull = open(os.devnull, 'w')
params = {'stdout': devnull, 'stderr': devnull, }
query = 'which %s' % cmd
code =, **params)
if code != 0 and error:
print(highlight('not installed %(command)s' % {'command': cmd}, 'yellow'))
def matches_file(file_name, match_files):
return any(
re.compile(match_file).match(file_name) for match_file in match_files)
def system(*args, **kwargs):
kwargs.setdefault('stdout', subprocess.PIPE)
proc = subprocess.Popen(args, **kwargs)
out, err = proc.communicate()
return out, err
def check_files(files, check):
result = 0
print(highlight(check['output'], 'yellow'))
if check['exists'] and check['package']:
for file_name in files:
if not 'match_files' in check or matches_file(file_name,
if not 'ignore_files' in check or not matches_file(
file_name, check['ignore_files']):
out, err = system(check['command'] % file_name,
stderr=subprocess.PIPE, shell=True)
if out or err:
if check['print_filename']:
prefix = '\t%s:' % file_name
prefix = '\t'
output_lines = ['%s%s' % (prefix, line) for line in
print(highlight('\n'.join(output_lines), 'red'))
if err:
print(highlight(err, 'red'))
result = 1
return result
def main():
# Stash any changes to the working tree that are not going to be committed['git', 'stash', '-u', '--keep-index'],
files = []
out, err = system('git', 'status', '--porcelain')
for line in out.splitlines():
match = modified.match(str(line))
if match:
result = 0
print(highlight('Running Django Code Validator...', 'yellow'))
if exists('$VIRTUAL_ENV/bin/python', error=False):
return_code ='$VIRTUAL_ENV/bin/python '
'validate', shell=True)
result = return_code or result
for check in CHECKS:
result = check_files(files, check) or result
# Unstash changes to the working tree that we had stashed['git', 'reset', '--hard'], stdout=subprocess.PIPE,
stderr=subprocess.PIPE)['git', 'stash', 'pop', '--quiet', '--index'],
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
if __name__ == '__main__':