diff --git a/flake8/mccabe.py b/flake8/mccabe.py index b693ca7..ec5118b 100644 --- a/flake8/mccabe.py +++ b/flake8/mccabe.py @@ -3,7 +3,13 @@ http://nedbatchelder.com/blog/200803/python_code_complexity_microtool.html MIT License. """ -import compiler +try: + from compiler.visitor import ASTVisitor as Visitor + from compiler import parse +except ImportError: + from ast import NodeVisitor as Visitor + from ast import parse + import optparse import sys @@ -14,8 +20,8 @@ class PathNode: self.look = look def to_dot(self): - print 'node [shape=%s,label="%s"] %d;' % \ - (self.look, self.name, self.dot_id()) + print('node [shape=%s,label="%s"] %d;' % \ + (self.look, self.name, self.dot_id())) def dot_id(self): return id(self) @@ -36,13 +42,13 @@ class PathGraph: self.nodes.setdefault(n1, []).append(n2) def to_dot(self): - print 'subgraph {' + print('subgraph {') for node in self.nodes: node.to_dot() for node, nexts in self.nodes.items(): for next in nexts: - print '%s -- %s;' % (node.dot_id(), next.dot_id()) - print '}' + print('%s -- %s;' % (node.dot_id(), next.dot_id())) + print('}') def complexity(self): """ Return the McCabe complexity for the graph. @@ -53,13 +59,13 @@ class PathGraph: return num_edges - num_nodes + 2 -class PathGraphingAstVisitor(compiler.visitor.ASTVisitor): +class PathGraphingAstVisitor(Visitor): """ A visitor for a parsed Abstract Syntax Tree which finds executable statements. """ def __init__(self): - compiler.visitor.ASTVisitor.__init__(self) + Visitor.__init__(self) self.classname = "" self.graphs = {} self.reset() @@ -175,9 +181,9 @@ class PathGraphingAstVisitor(compiler.visitor.ASTVisitor): def get_code_complexity(code, min=7, filename='stdin'): complex = [] try: - ast = compiler.parse(code) + ast = parse(code) except AttributeError as e: - print >> sys.stderr, "Unable to parse %s: %s" % (filename, e) + sys.stderr.write("Unable to parse %s: %s\n" % (filename, e)) return 0 visitor = PathGraphingAstVisitor() @@ -215,20 +221,20 @@ def main(argv): options, args = opar.parse_args(argv) text = open(args[0], "rU").read() + '\n\n' - ast = compiler.parse(text) + ast = parse(text) visitor = PathGraphingAstVisitor() visitor.preorder(ast, visitor) if options.dot: - print 'graph {' + print('graph {') for graph in visitor.graphs.values(): if graph.complexity() >= options.min: graph.to_dot() - print '}' + print('}') else: for graph in visitor.graphs.values(): if graph.complexity() >= options.min: - print graph.name, graph.complexity() + print(graph.name, graph.complexity()) if __name__ == '__main__': diff --git a/flake8/pyflakes.py b/flake8/pyflakes.py index 036b25c..00aa8fd 100644 --- a/flake8/pyflakes.py +++ b/flake8/pyflakes.py @@ -2,7 +2,11 @@ # (c) 2005-2010 Divmod, Inc. # See LICENSE file for details -import __builtin__ +try: + import __builtin__ +except ImportError: + import builtins as __builtin__ + import os.path import _ast import sys @@ -251,7 +255,7 @@ class Checker(object): all = [] # Look for imported names that aren't used. - for importation in scope.itervalues(): + for importation in scope.values(): if isinstance(importation, Importation): if not importation.used and importation.name not in all: self.report( @@ -284,7 +288,7 @@ class Checker(object): def handleNode(self, node, parent): node.parent = parent if self.traceTree: - print ' ' * self.nodeDepth + node.__class__.__name__ + print(' ' * self.nodeDepth + node.__class__.__name__) self.nodeDepth += 1 if self.futuresAllowed and not \ (isinstance(node, _ast.ImportFrom) or self.isDocstring(node)): @@ -296,7 +300,7 @@ class Checker(object): finally: self.nodeDepth -= 1 if self.traceTree: - print ' ' * self.nodeDepth + 'end ' + node.__class__.__name__ + print (' ' * self.nodeDepth + 'end ' + node.__class__.__name__) def ignore(self, node): pass @@ -527,10 +531,15 @@ class Checker(object): if isinstance(arg, _ast.Tuple): addArgs(arg.elts) else: - if arg.id in args: + try: + id_ = arg.id + except AttributeError: + id_ = arg.arg + + if id_ in args: self.report(messages.DuplicateArgument, - node.lineno, arg.id) - args.append(arg.id) + node.lineno, id_) + args.append(id_) self.pushFunctionScope() addArgs(node.args.args) @@ -554,7 +563,7 @@ class Checker(object): """ Check to see if any assignments have not been used. """ - for name, binding in self.scope.iteritems(): + for name, binding in self.scope.items(): if (not binding.used and not name in self.scope.globals and isinstance(binding, Assignment)): self.report(messages.UnusedVariable, @@ -629,8 +638,9 @@ def checkPath(filename): @return: the number of warnings printed """ try: - return check(file(filename, 'U').read() + '\n', filename) - except IOError, msg: + return check(open(filename, 'U').read() + '\n', filename) + except IOError: + msg = sys.exc_info()[1] print >> sys.stderr, "%s: %s" % (filename, msg.args[1]) return 1 @@ -652,7 +662,8 @@ def check(codeString, filename): # First, compile into an AST and handle syntax errors. try: tree = compile(codeString, filename, "exec", _ast.PyCF_ONLY_AST) - except SyntaxError, value: + except SyntaxError: + value = sys.exc_info()[1] msg = value.args[0] (lineno, offset, text) = value.lineno, value.offset, value.text @@ -679,13 +690,15 @@ def check(codeString, filename): else: # Okay, it's syntactically valid. Now check it. w = Checker(tree, filename) - w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno)) + sorting = [(msg.lineno, msg) for msg in w.messages] + sorting.sort() + w.messages = [msg for index, msg in sorting] valid_warnings = 0 for warning in w.messages: if skip_warning(warning): continue - print warning + print(warning) valid_warnings += 1 return valid_warnings