diff --git a/README b/README index c2d597b..e30f326 100644 --- a/README +++ b/README @@ -6,7 +6,7 @@ Flake8 is a wrapper around these tools: - PyFlakes - pep8 -- Ned's MacCabe script +- Ned's McCabe script 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 diff --git a/flake8/mccabe.py b/flake8/mccabe.py index 9f731e2..c41334c 100644 --- a/flake8/mccabe.py +++ b/flake8/mccabe.py @@ -13,6 +13,8 @@ import optparse import sys from collections import defaultdict +WARNING_CODE = "W901" + class ASTVisitor: @@ -63,8 +65,10 @@ class PathNode: class PathGraph: - def __init__(self, name): + def __init__(self, name, entity, lineno): self.name = name + self.entity = entity + self.lineno = lineno self.nodes = defaultdict(list) def connect(self, n1, n2): @@ -122,7 +126,7 @@ class PathGraphingAstVisitor(ASTVisitor): self.graph.connect(pathnode, bottom) self.tail = bottom else: - self.graph = PathGraph(name) + self.graph = PathGraph(name, entity, node.lineno) pathnode = PathNode(name) self.tail = pathnode self.default(node) @@ -163,7 +167,7 @@ class PathGraphingAstVisitor(ASTVisitor): if self.graph is None: # global loop - self.graph = PathGraph(name) + self.graph = PathGraph(name, name, node.lineno) pathnode = PathNode(name) self.tail = pathnode self.default(node) @@ -239,8 +243,13 @@ def get_code_complexity(code, min=7, filename='stdin'): # ? continue if graph.complexity() >= min: - msg = '%s:%s is too complex (%d)' % (filename, - graph.name, graph.complexity()) + msg = '%s:%d:1 %s %r is too complex (%d)' % ( + filename, + graph.lineno, + WARNING_CODE, + graph.entity, + graph.complexity(), + ) complex.append(msg) if len(complex) == 0: diff --git a/flake8/messages.py b/flake8/messages.py index 399ba0f..be63949 100644 --- a/flake8/messages.py +++ b/flake8/messages.py @@ -20,7 +20,7 @@ class Message(object): class UnusedImport(Message): - message = '%r imported but unused' + message = 'W402 %r imported but unused' def __init__(self, filename, lineno, name): Message.__init__(self, filename, lineno) @@ -28,7 +28,7 @@ class UnusedImport(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): Message.__init__(self, filename, lineno) @@ -36,7 +36,7 @@ class RedefinedWhileUnused(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): Message.__init__(self, filename, lineno) @@ -44,7 +44,7 @@ class ImportShadowedByLoopVar(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): Message.__init__(self, filename, lineno) @@ -52,7 +52,7 @@ class ImportStarUsed(Message): class UndefinedName(Message): - message = 'undefined name %r' + message = 'W802 undefined name %r' def __init__(self, filename, lineno, name): Message.__init__(self, filename, lineno) @@ -60,7 +60,7 @@ class UndefinedName(Message): class UndefinedExport(Message): - message = 'undefined name %r in __all__' + message = 'W803 undefined name %r in __all__' def __init__(self, filename, lineno, name): Message.__init__(self, filename, lineno) @@ -68,8 +68,8 @@ class UndefinedExport(Message): class UndefinedLocal(Message): - message = "local variable %r (defined in enclosing scope on line %r) " \ - "referenced before assignment" + message = "W804 local variable %r (defined in enclosing scope on line " \ + "%r) referenced before assignment" def __init__(self, filename, lineno, name, orig_lineno): Message.__init__(self, filename, lineno) @@ -77,7 +77,7 @@ class UndefinedLocal(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): Message.__init__(self, filename, lineno) @@ -85,7 +85,7 @@ class DuplicateArgument(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): Message.__init__(self, filename, lineno) @@ -93,7 +93,7 @@ class RedefinedFunction(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): Message.__init__(self, filename, lineno) @@ -106,7 +106,7 @@ class UnusedVariable(Message): 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): Message.__init__(self, filename, lineno) diff --git a/flake8/pep8.py b/flake8/pep8.py index 766302b..80cbfe6 100644 --- a/flake8/pep8.py +++ b/flake8/pep8.py @@ -1287,6 +1287,9 @@ def process_options(arglist=None): help="exclude files or directories which match these " "comma separated patterns (default: %s)" % 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', help="when parsing directories, only check filenames " "matching these comma separated patterns (default: " diff --git a/flake8/run.py b/flake8/run.py index 8683e50..7900e56 100644 --- a/flake8/run.py +++ b/flake8/run.py @@ -59,6 +59,9 @@ def main(): else: stdin = sys.stdin.read() warnings += check_code(stdin, complexity) + + if options.exit_zero: + raise SystemExit(0) raise SystemExit(warnings > 0)