Skip to content

Instantly share code, notes, and snippets.

@lsemel
Forked from aniav/flakes.py
Last active December 15, 2015 03:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save lsemel/5196932 to your computer and use it in GitHub Desktop.
Save lsemel/5196932 to your computer and use it in GitHub Desktop.
Run pyflakes against a Django project, with option to exclude directories/files
from __future__ import absolute_import
import ast
import os
from pyflakes import checker, messages
import sys
import fnmatch
from optparse import make_option
from django.conf import settings
from django.core.management.base import BaseCommand
# BlackHole, PySyntaxError and checking based on
# https://github.com/patrys/gedit-pyflakes-plugin.git
class BlackHole(object):
write = flush = lambda *args, **kwargs: None
def __enter__(self):
self.stderr, sys.stderr = sys.stderr, self
def __exit__(self, *args, **kwargs):
sys.stderr = self.stderr
class PySyntaxError(messages.Message):
message = 'syntax error in line %d: %s'
def __init__(self, filename, lineno, col, message):
super(PySyntaxError, self).__init__(filename, lineno)
self.message_args = (col, message)
def check(codeString, filename):
"""
Check the Python source given by C{codeString} for flakes.
@param codeString: The Python source to check.
@type codeString: C{str}
@param filename: The name of the file the source came from, used to report
errors.
@type filename: C{str}
@return: The number of warnings emitted.
@rtype: C{int}
"""
try:
with BlackHole():
tree = ast.parse(codeString, filename)
except SyntaxError, e:
return [PySyntaxError(filename, e.lineno, e.offset, e.text)]
else:
# Okay, it's syntactically valid. Now parse it into an ast and check
# it.
w = checker.Checker(tree, filename)
lines = codeString.split('\n')
# honour pyflakes:ignore comments
messages = [message for message in w.messages
if lines[message.lineno-1].find('pyflakes:ignore') < 0]
messages.sort(lambda a, b: cmp(a.lineno, b.lineno))
return messages
def checkPath(filename):
"""
Check the given path, printing out any warnings detected.
@return: the number of warnings printed
"""
try:
return check(file(filename, 'U').read() + '\n', filename)
except IOError, msg:
return ["%s: %s" % (filename, msg.args[1])]
except TypeError:
pass
def checkPaths(filenames, excludes):
warnings = []
for arg in filenames:
if os.path.isdir(arg):
for dirpath, dirnames, filenames in os.walk(arg):
for filename in filenames:
skip = False
for exclude in excludes:
if fnmatch.fnmatch(os.path.join(dirpath, filename),exclude):
skip = True
break
if not skip and filename.endswith('.py'):
warnings.extend(checkPath(os.path.join(dirpath,
filename)))
else:
warnings.extend(checkPath(arg))
return warnings
#### pyflakes.scripts.pyflakes ends.
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
make_option('--exclude', '-e', dest='exclude',
help='patterns to exclude', action='append', default=[]),
)
help = "Run pyflakes syntax checks."
args = '[filename [filename [...]]]'
def handle(self, *filenames, **options):
if not filenames:
filenames = getattr(settings, 'PYFLAKES_DEFAULT_ARGS', ['.'])
exclude = options.get('exclude')
exclude.extend(['*migrations*'])
warnings = checkPaths(filenames, exclude)
warnings = [warning for warning in warnings if 'unable to detect undefined names' not in str(warning)]
for warning in warnings:
print warning
if warnings:
print 'Total warnings: %d' % len(warnings)
raise SystemExit(1)
@crucialfelix
Copy link

not working with pyflakes 0.8.1

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