-
-
Save lsemel/5196932 to your computer and use it in GitHub Desktop.
Run pyflakes against a Django project, with option to exclude directories/files
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
not working with pyflakes 0.8.1