Skip to content

Instantly share code, notes, and snippets.

@aniav
Forked from mpasternacki/flakes.py
Created September 12, 2011 13:45
Show Gist options
  • Save aniav/1211285 to your computer and use it in GitHub Desktop.
Save aniav/1211285 to your computer and use it in GitHub Desktop.
Django management command to run pyflakes against Django project
import ast
import os
from pyflakes import checker, messages
import sys
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):
warnings = []
for arg in filenames:
if os.path.isdir(arg):
for dirpath, dirnames, filenames in os.walk(arg):
for filename in filenames:
if 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):
help = "Run pyflakes syntax checks."
args = '[filename [filename [...]]]'
def handle(self, *filenames, **options):
if not filenames:
filenames = getattr(settings, 'PYFLAKES_DEFAULT_ARGS', ['.'])
warnings = checkPaths(filenames)
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