This commit is contained in:
Tarek Ziade 2012-02-23 22:52:26 +01:00
commit 82a72535ad
5 changed files with 33 additions and 18 deletions

2
README
View file

@ -6,7 +6,7 @@ Flake8 is a wrapper around these tools:
- PyFlakes - PyFlakes
- pep8 - pep8
- Ned's MacCabe script - Ned's McCabe script
Flake8 runs all tools by launching the single 'flake8' script, but ignores pep8 Flake8 runs all tools by launching the single 'flake8' script, but ignores pep8
and PyFlakes extended options and just uses defaults. It displays the warnings and PyFlakes extended options and just uses defaults. It displays the warnings

View file

@ -13,6 +13,8 @@ import optparse
import sys import sys
from collections import defaultdict from collections import defaultdict
WARNING_CODE = "W901"
class ASTVisitor: class ASTVisitor:
@ -63,8 +65,10 @@ class PathNode:
class PathGraph: class PathGraph:
def __init__(self, name): def __init__(self, name, entity, lineno):
self.name = name self.name = name
self.entity = entity
self.lineno = lineno
self.nodes = defaultdict(list) self.nodes = defaultdict(list)
def connect(self, n1, n2): def connect(self, n1, n2):
@ -122,7 +126,7 @@ class PathGraphingAstVisitor(ASTVisitor):
self.graph.connect(pathnode, bottom) self.graph.connect(pathnode, bottom)
self.tail = bottom self.tail = bottom
else: else:
self.graph = PathGraph(name) self.graph = PathGraph(name, entity, node.lineno)
pathnode = PathNode(name) pathnode = PathNode(name)
self.tail = pathnode self.tail = pathnode
self.default(node) self.default(node)
@ -163,7 +167,7 @@ class PathGraphingAstVisitor(ASTVisitor):
if self.graph is None: if self.graph is None:
# global loop # global loop
self.graph = PathGraph(name) self.graph = PathGraph(name, name, node.lineno)
pathnode = PathNode(name) pathnode = PathNode(name)
self.tail = pathnode self.tail = pathnode
self.default(node) self.default(node)
@ -239,8 +243,13 @@ def get_code_complexity(code, min=7, filename='stdin'):
# ? # ?
continue continue
if graph.complexity() >= min: if graph.complexity() >= min:
msg = '%s:%s is too complex (%d)' % (filename, msg = '%s:%d:1 %s %r is too complex (%d)' % (
graph.name, graph.complexity()) filename,
graph.lineno,
WARNING_CODE,
graph.entity,
graph.complexity(),
)
complex.append(msg) complex.append(msg)
if len(complex) == 0: if len(complex) == 0:

View file

@ -20,7 +20,7 @@ class Message(object):
class UnusedImport(Message): class UnusedImport(Message):
message = '%r imported but unused' message = 'W402 %r imported but unused'
def __init__(self, filename, lineno, name): def __init__(self, filename, lineno, name):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -28,7 +28,7 @@ class UnusedImport(Message):
class RedefinedWhileUnused(Message): class RedefinedWhileUnused(Message):
message = 'redefinition of unused %r from line %r' message = 'W801 redefinition of unused %r from line %r'
def __init__(self, filename, lineno, name, orig_lineno): def __init__(self, filename, lineno, name, orig_lineno):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -36,7 +36,7 @@ class RedefinedWhileUnused(Message):
class ImportShadowedByLoopVar(Message): class ImportShadowedByLoopVar(Message):
message = 'import %r from line %r shadowed by loop variable' message = 'W403 import %r from line %r shadowed by loop variable'
def __init__(self, filename, lineno, name, orig_lineno): def __init__(self, filename, lineno, name, orig_lineno):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -44,7 +44,7 @@ class ImportShadowedByLoopVar(Message):
class ImportStarUsed(Message): class ImportStarUsed(Message):
message = "'from %s import *' used; unable to detect undefined names" message = "W404 'from %s import *' used; unable to detect undefined names"
def __init__(self, filename, lineno, modname): def __init__(self, filename, lineno, modname):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -52,7 +52,7 @@ class ImportStarUsed(Message):
class UndefinedName(Message): class UndefinedName(Message):
message = 'undefined name %r' message = 'W802 undefined name %r'
def __init__(self, filename, lineno, name): def __init__(self, filename, lineno, name):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -60,7 +60,7 @@ class UndefinedName(Message):
class UndefinedExport(Message): class UndefinedExport(Message):
message = 'undefined name %r in __all__' message = 'W803 undefined name %r in __all__'
def __init__(self, filename, lineno, name): def __init__(self, filename, lineno, name):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -68,8 +68,8 @@ class UndefinedExport(Message):
class UndefinedLocal(Message): class UndefinedLocal(Message):
message = "local variable %r (defined in enclosing scope on line %r) " \ message = "W804 local variable %r (defined in enclosing scope on line " \
"referenced before assignment" "%r) referenced before assignment"
def __init__(self, filename, lineno, name, orig_lineno): def __init__(self, filename, lineno, name, orig_lineno):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -77,7 +77,7 @@ class UndefinedLocal(Message):
class DuplicateArgument(Message): class DuplicateArgument(Message):
message = 'duplicate argument %r in function definition' message = 'W805 duplicate argument %r in function definition'
def __init__(self, filename, lineno, name): def __init__(self, filename, lineno, name):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -85,7 +85,7 @@ class DuplicateArgument(Message):
class RedefinedFunction(Message): class RedefinedFunction(Message):
message = 'redefinition of function %r from line %r' message = 'W806 redefinition of function %r from line %r'
def __init__(self, filename, lineno, name, orig_lineno): def __init__(self, filename, lineno, name, orig_lineno):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -93,7 +93,7 @@ class RedefinedFunction(Message):
class LateFutureImport(Message): class LateFutureImport(Message):
message = 'future import(s) %r after other statements' message = 'W405 future import(s) %r after other statements'
def __init__(self, filename, lineno, names): def __init__(self, filename, lineno, names):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)
@ -106,7 +106,7 @@ class UnusedVariable(Message):
used. used.
""" """
message = 'local variable %r is assigned to but never used' message = 'W806 local variable %r is assigned to but never used'
def __init__(self, filename, lineno, names): def __init__(self, filename, lineno, names):
Message.__init__(self, filename, lineno) Message.__init__(self, filename, lineno)

View file

@ -1287,6 +1287,9 @@ def process_options(arglist=None):
help="exclude files or directories which match these " help="exclude files or directories which match these "
"comma separated patterns (default: %s)" % "comma separated patterns (default: %s)" %
DEFAULT_EXCLUDE) DEFAULT_EXCLUDE)
parser.add_option('--exit-zero', action='store_true',
help="use exit code 0 (success), even if there are "
"warnings")
parser.add_option('--filename', metavar='patterns', default='*.py', parser.add_option('--filename', metavar='patterns', default='*.py',
help="when parsing directories, only check filenames " help="when parsing directories, only check filenames "
"matching these comma separated patterns (default: " "matching these comma separated patterns (default: "

View file

@ -59,6 +59,9 @@ def main():
else: else:
stdin = sys.stdin.read() stdin = sys.stdin.read()
warnings += check_code(stdin, complexity) warnings += check_code(stdin, complexity)
if options.exit_zero:
raise SystemExit(0)
raise SystemExit(warnings > 0) raise SystemExit(warnings > 0)