Added a management command to run pyflakes, with the added feature of being able to mark individual lines with # pyflakes:ignore, which is needed in some cases.
- Legacy-Id: 7367
This commit is contained in:
parent
14d629afe9
commit
0eefa5760c
105
ietf/utils/management/commands/flakes.py
Normal file
105
ietf/utils/management/commands/flakes.py
Normal file
|
@ -0,0 +1,105 @@
|
|||
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)
|
||||
|
Loading…
Reference in a new issue