Commits

Tarek Ziadé committed ffdd712

fixed mccabe for global loops and nested functions

Comments (0)

Files changed (9)

         self.tail = None
 
     def visitFunction(self, node):
+
         if self.classname:
             entity = '%s%s' % (self.classname, node.name)
         else:
             entity = node.name
 
         name = '%d:1: %r' % (node.lineno, entity)
-        self.graph = PathGraph(name)
-        pathnode = PathNode(name)
-        self.tail = pathnode
-        self.default(node)
-        self.graphs["%s%s" % (self.classname, node.name)] = self.graph
-        self.reset()
+
+        if self.graph is not None:
+            # closure
+            pathnode = self.appendPathNode(name)
+            self.tail = pathnode
+            self.default(node)
+            bottom = PathNode("", look='point')
+            self.graph.connect(self.tail, bottom)
+            self.graph.connect(pathnode, bottom)
+            self.tail = bottom
+        else:
+            self.graph = PathGraph(name)
+            pathnode = PathNode(name)
+            self.tail = pathnode
+            self.default(node)
+            self.graphs["%s%s" % (self.classname, node.name)] = self.graph
+            self.reset()
 
     def visitClass(self, node):
         old_classname = self.classname
         return pathnode
 
     def visitSimpleStatement(self, node):
-        name = "Stmt %d" % node.lineno
+        if node.lineno is None:
+            lineno = 0
+        else:
+            lineno = node.lineno
+        name = "Stmt %d" % lineno
         self.appendPathNode(name)
 
     visitAssert = visitAssign = visitAssTuple = visitPrint = \
 
     def visitLoop(self, node):
         name = "Loop %d" % node.lineno
-        pathnode = self.appendPathNode(name)
-        self.tail = pathnode
-        self.default(node.body)
-        bottom = PathNode("", look='point')
-        self.graph.connect(self.tail, bottom)
-        self.graph.connect(pathnode, bottom)
-        self.tail = bottom
+
+        if self.graph is None:
+            # global loop
+            self.graph = PathGraph(name)
+            pathnode = PathNode(name)
+            self.tail = pathnode
+            self.default(node)
+            self.graphs["%s%s" % (self.classname, name)] = self.graph
+            self.reset()
+        else:
+            pathnode = self.appendPathNode(name)
+            self.tail = pathnode
+            self.default(node.body)
+            bottom = PathNode("", look='point')
+            self.graph.connect(self.tail, bottom)
+            self.graph.connect(pathnode, bottom)
+            self.tail = bottom
+
         # TODO: else clause in node.else_
 
     visitFor = visitWhile = visitLoop
     complex = []
     ast = compiler.parse(code)
     visitor = PathGraphingAstVisitor()
-    try:
-        visitor.preorder(ast, visitor)
-    except AttributeError:
-        print('McCabe: Could not parse code')
-        return -1
-
+    visitor.preorder(ast, visitor)
     for graph in visitor.graphs.values():
         if graph is None:
             # ?
 def get_module_complexity(module_path, min=7):
     """Returns the complexity of a module"""
     code = open(module_path, "rU").read() + '\n\n'
-    res = get_code_complexity(code, min, filename=module_path)
-    if res == -1:
-        print('McCabe: Problem with %s' % module_path)
-    return res
+    return get_code_complexity(code, min, filename=module_path)
 
 
 def main(argv):
Add a comment to this file

flake8/test/__init__.py

Empty file removed.

flake8/test/harness.py

-
-import textwrap
-import _ast
-
-from twisted.trial import unittest
-
-from pyflakes import checker
-
-
-class Test(unittest.TestCase):
-
-    def flakes(self, input, *expectedOutputs, **kw):
-        ast = compile(textwrap.dedent(input), "<test>", "exec",
-                      _ast.PyCF_ONLY_AST)
-        w = checker.Checker(ast, **kw)
-        outputs = [type(o) for o in w.messages]
-        expectedOutputs = list(expectedOutputs)
-        outputs.sort()
-        expectedOutputs.sort()
-        self.assert_(outputs == expectedOutputs, '''\
-for input:
-%s
-expected outputs:
-%s
-but got:
-%s''' % (input, repr(expectedOutputs), '\n'.join(map(str, w.messages))))
-        return w

flake8/test/test_imports.py

-
-from sys import version_info
-
-from pyflakes import messages as m
-from pyflakes.test import harness
-
-
-class Test(harness.Test):
-
-    def test_unusedImport(self):
-        self.flakes('import fu, bar', m.UnusedImport, m.UnusedImport)
-        self.flakes('from baz import fu, bar', m.UnusedImport, m.UnusedImport)
-
-    def test_aliasedImport(self):
-        self.flakes('import fu as FU, bar as FU',
-                    m.RedefinedWhileUnused, m.UnusedImport)
-        self.flakes('from moo import fu as FU, bar as FU',
-                    m.RedefinedWhileUnused, m.UnusedImport)
-
-    def test_usedImport(self):
-        self.flakes('import fu; print fu')
-        self.flakes('from baz import fu; print fu')
-
-    def test_redefinedWhileUnused(self):
-        self.flakes('import fu; fu = 3', m.RedefinedWhileUnused)
-        self.flakes('import fu; del fu', m.RedefinedWhileUnused)
-        self.flakes('import fu; fu, bar = 3', m.RedefinedWhileUnused)
-        self.flakes('import fu; [fu, bar] = 3', m.RedefinedWhileUnused)
-
-    def test_redefinedByFunction(self):
-        self.flakes('''
-        import fu
-        def fu():
-            pass
-        ''', m.RedefinedWhileUnused)
-
-    def test_redefinedInNestedFunction(self):
-        """
-        Test that shadowing a global name with a nested function definition
-        generates a warning.
-        """
-        self.flakes('''
-        import fu
-        def bar():
-            def baz():
-                def fu():
-                    pass
-        ''', m.RedefinedWhileUnused, m.UnusedImport)
-
-    def test_redefinedByClass(self):
-        self.flakes('''
-        import fu
-        class fu:
-            pass
-        ''', m.RedefinedWhileUnused)
-
-    def test_redefinedBySubclass(self):
-        """
-        If an imported name is redefined by a class statement which also uses
-        that name in the bases list, no warning is emitted.
-        """
-        self.flakes('''
-        from fu import bar
-        class bar(bar):
-            pass
-        ''')
-
-    def test_redefinedInClass(self):
-        """
-        Test that shadowing a global with a class attribute does not produce a
-        warning.
-        """
-        self.flakes('''
-        import fu
-        class bar:
-            fu = 1
-        print fu
-        ''')
-
-    def test_usedInFunction(self):
-        self.flakes('''
-        import fu
-        def fun():
-            print fu
-        ''')
-
-    def test_shadowedByParameter(self):
-        self.flakes('''
-        import fu
-        def fun(fu):
-            print fu
-        ''', m.UnusedImport)
-
-        self.flakes('''
-        import fu
-        def fun(fu):
-            print fu
-        print fu
-        ''')
-
-    def test_newAssignment(self):
-        self.flakes('fu = None')
-
-    def test_usedInGetattr(self):
-        self.flakes('import fu; fu.bar.baz')
-        self.flakes('import fu; "bar".fu.baz', m.UnusedImport)
-
-    def test_usedInSlice(self):
-        self.flakes('import fu; print fu.bar[1:]')
-
-    def test_usedInIfBody(self):
-        self.flakes('''
-        import fu
-        if True: print fu
-        ''')
-
-    def test_usedInIfConditional(self):
-        self.flakes('''
-        import fu
-        if fu: pass
-        ''')
-
-    def test_usedInElifConditional(self):
-        self.flakes('''
-        import fu
-        if False: pass
-        elif fu: pass
-        ''')
-
-    def test_usedInElse(self):
-        self.flakes('''
-        import fu
-        if False: pass
-        else: print fu
-        ''')
-
-    def test_usedInCall(self):
-        self.flakes('import fu; fu.bar()')
-
-    def test_usedInClass(self):
-        self.flakes('''
-        import fu
-        class bar:
-            bar = fu
-        ''')
-
-    def test_usedInClassBase(self):
-        self.flakes('''
-        import fu
-        class bar(object, fu.baz):
-            pass
-        ''')
-
-    def test_notUsedInNestedScope(self):
-        self.flakes('''
-        import fu
-        def bleh():
-            pass
-        print fu
-        ''')
-
-    def test_usedInFor(self):
-        self.flakes('''
-        import fu
-        for bar in range(9):
-            print fu
-        ''')
-
-    def test_usedInForElse(self):
-        self.flakes('''
-        import fu
-        for bar in range(10):
-            pass
-        else:
-            print fu
-        ''')
-
-    def test_redefinedByFor(self):
-        self.flakes('''
-        import fu
-        for fu in range(2):
-            pass
-        ''', m.RedefinedWhileUnused)
-
-    def test_shadowedByFor(self):
-        """
-        Test that shadowing a global name with a for loop variable generates a
-        warning.
-        """
-        self.flakes('''
-        import fu
-        fu.bar()
-        for fu in ():
-            pass
-        ''', m.ImportShadowedByLoopVar)
-
-    def test_shadowedByForDeep(self):
-        """
-        Test that shadowing a global name with a for loop variable nested in a
-        tuple unpack generates a warning.
-        """
-        self.flakes('''
-        import fu
-        fu.bar()
-        for (x, y, z, (a, b, c, (fu,))) in ():
-            pass
-        ''', m.ImportShadowedByLoopVar)
-
-    def test_usedInReturn(self):
-        self.flakes('''
-        import fu
-        def fun():
-            return fu
-        ''')
-
-    def test_usedInOperators(self):
-        self.flakes('import fu; 3 + fu.bar')
-        self.flakes('import fu; 3 % fu.bar')
-        self.flakes('import fu; 3 - fu.bar')
-        self.flakes('import fu; 3 * fu.bar')
-        self.flakes('import fu; 3 ** fu.bar')
-        self.flakes('import fu; 3 / fu.bar')
-        self.flakes('import fu; 3 // fu.bar')
-        self.flakes('import fu; -fu.bar')
-        self.flakes('import fu; ~fu.bar')
-        self.flakes('import fu; 1 == fu.bar')
-        self.flakes('import fu; 1 | fu.bar')
-        self.flakes('import fu; 1 & fu.bar')
-        self.flakes('import fu; 1 ^ fu.bar')
-        self.flakes('import fu; 1 >> fu.bar')
-        self.flakes('import fu; 1 << fu.bar')
-
-    def test_usedInAssert(self):
-        self.flakes('import fu; assert fu.bar')
-
-    def test_usedInSubscript(self):
-        self.flakes('import fu; fu.bar[1]')
-
-    def test_usedInLogic(self):
-        self.flakes('import fu; fu and False')
-        self.flakes('import fu; fu or False')
-        self.flakes('import fu; not fu.bar')
-
-    def test_usedInList(self):
-        self.flakes('import fu; [fu]')
-
-    def test_usedInTuple(self):
-        self.flakes('import fu; (fu,)')
-
-    def test_usedInTry(self):
-        self.flakes('''
-        import fu
-        try: fu
-        except: pass
-        ''')
-
-    def test_usedInExcept(self):
-        self.flakes('''
-        import fu
-        try: fu
-        except: pass
-        ''')
-
-    def test_redefinedByExcept(self):
-        self.flakes('''
-        import fu
-        try: pass
-        except Exception, fu: pass
-        ''', m.RedefinedWhileUnused)
-
-    def test_usedInRaise(self):
-        self.flakes('''
-        import fu
-        raise fu.bar
-        ''')
-
-    def test_usedInYield(self):
-        self.flakes('''
-        import fu
-        def gen():
-            yield fu
-        ''')
-
-    def test_usedInDict(self):
-        self.flakes('import fu; {fu:None}')
-        self.flakes('import fu; {1:fu}')
-
-    def test_usedInParameterDefault(self):
-        self.flakes('''
-        import fu
-        def f(bar=fu):
-            pass
-        ''')
-
-    def test_usedInAttributeAssign(self):
-        self.flakes('import fu; fu.bar = 1')
-
-    def test_usedInKeywordArg(self):
-        self.flakes('import fu; fu.bar(stuff=fu)')
-
-    def test_usedInAssignment(self):
-        self.flakes('import fu; bar=fu')
-        self.flakes('import fu; n=0; n+=fu')
-
-    def test_usedInListComp(self):
-        self.flakes('import fu; [fu for _ in range(1)]')
-        self.flakes('import fu; [1 for _ in range(1) if fu]')
-
-    def test_redefinedByListComp(self):
-        self.flakes('import fu; [1 for fu in range(1)]',
-                    m.RedefinedWhileUnused)
-
-    def test_usedInTryFinally(self):
-        self.flakes('''
-        import fu
-        try: pass
-        finally: fu
-        ''')
-
-        self.flakes('''
-        import fu
-        try: fu
-        finally: pass
-        ''')
-
-    def test_usedInWhile(self):
-        self.flakes('''
-        import fu
-        while 0:
-            fu
-        ''')
-
-        self.flakes('''
-        import fu
-        while fu: pass
-        ''')
-
-    def test_usedInGlobal(self):
-        self.flakes('''
-        import fu
-        def f(): global fu
-        ''', m.UnusedImport)
-
-    def test_usedInBackquote(self):
-        self.flakes('import fu; `fu`')
-
-    def test_usedInExec(self):
-        self.flakes('import fu; exec "print 1" in fu.bar')
-
-    def test_usedInLambda(self):
-        self.flakes('import fu; lambda: fu')
-
-    def test_shadowedByLambda(self):
-        self.flakes('import fu; lambda fu: fu', m.UnusedImport)
-
-    def test_usedInSliceObj(self):
-        self.flakes('import fu; "meow"[::fu]')
-
-    def test_unusedInNestedScope(self):
-        self.flakes('''
-        def bar():
-            import fu
-        fu
-        ''', m.UnusedImport, m.UndefinedName)
-
-    def test_methodsDontUseClassScope(self):
-        self.flakes('''
-        class bar:
-            import fu
-            def fun(self):
-                fu
-        ''', m.UnusedImport, m.UndefinedName)
-
-    def test_nestedFunctionsNestScope(self):
-        self.flakes('''
-        def a():
-            def b():
-                fu
-            import fu
-        ''')
-
-    def test_nestedClassAndFunctionScope(self):
-        self.flakes('''
-        def a():
-            import fu
-            class b:
-                def c(self):
-                    print fu
-        ''')
-
-    def test_importStar(self):
-        self.flakes('from fu import *', m.ImportStarUsed)
-
-    def test_packageImport(self):
-        """
-        If a dotted name is imported and used, no warning is reported.
-        """
-        self.flakes('''
-        import fu.bar
-        fu.bar
-        ''')
-
-    def test_unusedPackageImport(self):
-        """
-        If a dotted name is imported and not used, an unused import warning is
-        reported.
-        """
-        self.flakes('import fu.bar', m.UnusedImport)
-
-    def test_duplicateSubmoduleImport(self):
-        """
-        If a submodule of a package is imported twice, an unused import warning
-        and a redefined while unused warning are reported.
-        """
-        self.flakes('''
-        import fu.bar, fu.bar
-        fu.bar
-        ''', m.RedefinedWhileUnused)
-        self.flakes('''
-        import fu.bar
-        import fu.bar
-        fu.bar
-        ''', m.RedefinedWhileUnused)
-
-    def test_differentSubmoduleImport(self):
-        """
-        If two different submodules of a package are imported, no duplicate
-        import warning is reported for the package.
-        """
-        self.flakes('''
-        import fu.bar, fu.baz
-        fu.bar, fu.baz
-        ''')
-        self.flakes('''
-        import fu.bar
-        import fu.baz
-        fu.bar, fu.baz
-        ''')
-
-    def test_assignRHSFirst(self):
-        self.flakes('import fu; fu = fu')
-        self.flakes('import fu; fu, bar = fu')
-        self.flakes('import fu; [fu, bar] = fu')
-        self.flakes('import fu; fu += fu')
-
-    def test_tryingMultipleImports(self):
-        self.flakes('''
-        try:
-            import fu
-        except ImportError:
-            import bar as fu
-        ''')
-    test_tryingMultipleImports.todo = ''
-
-    def test_nonGlobalDoesNotRedefine(self):
-        self.flakes('''
-        import fu
-        def a():
-            fu = 3
-            return fu
-        fu
-        ''')
-
-    def test_functionsRunLater(self):
-        self.flakes('''
-        def a():
-            fu
-        import fu
-        ''')
-
-    def test_functionNamesAreBoundNow(self):
-        self.flakes('''
-        import fu
-        def fu():
-            fu
-        fu
-        ''', m.RedefinedWhileUnused)
-
-    def test_ignoreNonImportRedefinitions(self):
-        self.flakes('a = 1; a = 2')
-
-    def test_importingForImportError(self):
-        self.flakes('''
-        try:
-            import fu
-        except ImportError:
-            pass
-        ''')
-    test_importingForImportError.todo = ''
-
-    def test_importedInClass(self):
-        '''Imports in class scope can be used through self'''
-        self.flakes('''
-        class c:
-            import i
-            def __init__(self):
-                self.i
-        ''')
-    test_importedInClass.todo = 'requires evaluating attribute access'
-
-    def test_futureImport(self):
-        '''__future__ is special'''
-        self.flakes('from __future__ import division')
-        self.flakes('''
-        "docstring is allowed before future import"
-        from __future__ import division
-        ''')
-
-    def test_futureImportFirst(self):
-        """
-        __future__ imports must come before anything else.
-        """
-        self.flakes('''
-        x = 5
-        from __future__ import division
-        ''', m.LateFutureImport)
-        self.flakes('''
-        from foo import bar
-        from __future__ import division
-        bar
-        ''', m.LateFutureImport)
-
-
-class TestSpecialAll(harness.Test):
-    """
-    Tests for suppression of unused import warnings by C{__all__}.
-    """
-    def test_ignoredInFunction(self):
-        """
-        An C{__all__} definition does not suppress unused import warnings in a
-        function scope.
-        """
-        self.flakes('''
-        def foo():
-            import bar
-            __all__ = ["bar"]
-        ''', m.UnusedImport, m.UnusedVariable)
-
-    def test_ignoredInClass(self):
-        """
-        An C{__all__} definition does not suppress unused import warnings in a
-        class scope.
-        """
-        self.flakes('''
-        class foo:
-            import bar
-            __all__ = ["bar"]
-        ''', m.UnusedImport)
-
-    def test_warningSuppressed(self):
-        """
-        If a name is imported and unused but is named in C{__all__}, no warning
-        is reported.
-        """
-        self.flakes('''
-        import foo
-        __all__ = ["foo"]
-        ''')
-
-    def test_unrecognizable(self):
-        """
-        If C{__all__} is defined in a way that can't be recognized statically,
-        it is ignored.
-        """
-        self.flakes('''
-        import foo
-        __all__ = ["f" + "oo"]
-        ''', m.UnusedImport)
-        self.flakes('''
-        import foo
-        __all__ = [] + ["foo"]
-        ''', m.UnusedImport)
-
-    def test_unboundExported(self):
-        """
-        If C{__all__} includes a name which is not bound, a warning is emitted.
-        """
-        self.flakes('''
-        __all__ = ["foo"]
-        ''', m.UndefinedExport)
-
-        # Skip this in __init__.py though, since the rules there are a little
-        # different.
-        for filename in ["foo/__init__.py", "__init__.py"]:
-            self.flakes('''
-            __all__ = ["foo"]
-            ''', filename=filename)
-
-    def test_usedInGenExp(self):
-        """
-        Using a global in a generator expression results in no warnings.
-        """
-        self.flakes('import fu; (fu for _ in range(1))')
-        self.flakes('import fu; (1 for _ in range(1) if fu)')
-
-    def test_redefinedByGenExp(self):
-        """
-        Re-using a global name as the loop variable for a generator
-        expression results in a redefinition warning.
-        """
-        self.flakes('import fu; (1 for fu in range(1))',
-                    m.RedefinedWhileUnused)
-
-    def test_usedAsDecorator(self):
-        """
-        Using a global name in a decorator statement results in no warnings,
-        but using an undefined name in a decorator statement results in an
-        undefined name warning.
-        """
-        self.flakes('''
-        from interior import decorate
-        @decorate
-        def f():
-            return "hello"
-        ''')
-
-        self.flakes('''
-        from interior import decorate
-        @decorate('value')
-        def f():
-            return "hello"
-        ''')
-
-        self.flakes('''
-        @decorate
-        def f():
-            return "hello"
-        ''', m.UndefinedName)
-
-
-class Python26Tests(harness.Test):
-    """
-    Tests for checking of syntax which is valid in PYthon 2.6 and newer.
-    """
-    if version_info < (2, 6):
-        skip = "Python 2.6 required for class decorator tests."
-
-    def test_usedAsClassDecorator(self):
-        """
-        Using an imported name as a class decorator results in no warnings,
-        but using an undefined name as a class decorator results in an
-        undefined name warning.
-        """
-        self.flakes('''
-        from interior import decorate
-        @decorate
-        class foo:
-            pass
-        ''')
-
-        self.flakes('''
-        from interior import decorate
-        @decorate("foo")
-        class bar:
-            pass
-        ''')
-
-        self.flakes('''
-        @decorate
-        class foo:
-            pass
-        ''', m.UndefinedName)

flake8/test/test_other.py

-# (c) 2005-2010 Divmod, Inc.
-# See LICENSE file for details
-
-"""
-Tests for various Pyflakes behavior.
-"""
-
-from sys import version_info
-
-from pyflakes import messages as m
-from pyflakes.test import harness
-
-
-class Test(harness.Test):
-
-    def test_duplicateArgs(self):
-        self.flakes('def fu(bar, bar): pass', m.DuplicateArgument)
-
-    def test_localReferencedBeforeAssignment(self):
-        self.flakes('''
-        a = 1
-        def f():
-            a; a=1
-        f()
-        ''', m.UndefinedName)
-    test_localReferencedBeforeAssignment.todo = 'this requires finding all ' \
-            'assignments in the function body first'
-
-    def test_redefinedFunction(self):
-        """
-        Test that shadowing a function definition with another one raises a
-        warning.
-        """
-        self.flakes('''
-        def a(): pass
-        def a(): pass
-        ''', m.RedefinedFunction)
-
-    def test_redefinedClassFunction(self):
-        """
-        Test that shadowing a function definition in a class suite with another
-        one raises a warning.
-        """
-        self.flakes('''
-        class A:
-            def a(): pass
-            def a(): pass
-        ''', m.RedefinedFunction)
-
-    def test_functionDecorator(self):
-        """
-        Test that shadowing a function definition with a decorated version of
-        that function does not raise a warning.
-        """
-        self.flakes('''
-        from somewhere import somedecorator
-
-        def a(): pass
-        a = somedecorator(a)
-        ''')
-
-    def test_classFunctionDecorator(self):
-        """
-        Test that shadowing a function definition in a class suite with a
-        decorated version of that function does not raise a warning.
-        """
-        self.flakes('''
-        class A:
-            def a(): pass
-            a = classmethod(a)
-        ''')
-
-    def test_unaryPlus(self):
-        '''Don't die on unary +'''
-        self.flakes('+1')
-
-    def test_undefinedBaseClass(self):
-        """
-        If a name in the base list of a class definition is undefined, a
-        warning is emitted.
-        """
-        self.flakes('''
-        class foo(foo):
-            pass
-        ''', m.UndefinedName)
-
-    def test_classNameUndefinedInClassBody(self):
-        """
-        If a class name is used in the body of that class's definition and
-        the name is not already defined, a warning is emitted.
-        """
-        self.flakes('''
-        class foo:
-            foo
-        ''', m.UndefinedName)
-
-    def test_classNameDefinedPreviously(self):
-        """
-        If a class name is used in the body of that class's definition and
-        the name was previously defined in some other way, no warning is
-        emitted.
-        """
-        self.flakes('''
-        foo = None
-        class foo:
-            foo
-        ''')
-
-    def test_comparison(self):
-        """
-        If a defined name is used on either side of any of the six comparison
-        operators, no warning is emitted.
-        """
-        self.flakes('''
-        x = 10
-        y = 20
-        x < y
-        x <= y
-        x == y
-        x != y
-        x >= y
-        x > y
-        ''')
-
-    def test_identity(self):
-        """
-        If a deefined name is used on either side of an identity test, no
-        warning is emitted.
-        """
-        self.flakes('''
-        x = 10
-        y = 20
-        x is y
-        x is not y
-        ''')
-
-    def test_containment(self):
-        """
-        If a defined name is used on either side of a containment test, no
-        warning is emitted.
-        """
-        self.flakes('''
-        x = 10
-        y = 20
-        x in y
-        x not in y
-        ''')
-
-    def test_loopControl(self):
-        """
-        break and continue statements are supported.
-        """
-        self.flakes('''
-        for x in [1, 2]:
-            break
-        ''')
-        self.flakes('''
-        for x in [1, 2]:
-            continue
-        ''')
-
-    def test_ellipsis(self):
-        """
-        Ellipsis in a slice is supported.
-        """
-        self.flakes('''
-        [1, 2][...]
-        ''')
-
-    def test_extendedSlice(self):
-        """
-        Extended slices are supported.
-        """
-        self.flakes('''
-        x = 3
-        [1, 2][x,:]
-        ''')
-
-
-class TestUnusedAssignment(harness.Test):
-    """
-    Tests for warning about unused assignments.
-    """
-
-    def test_unusedVariable(self):
-        """
-        Warn when a variable in a function is assigned a value that's never
-        used.
-        """
-        self.flakes('''
-        def a():
-            b = 1
-        ''', m.UnusedVariable)
-
-    def test_assignToGlobal(self):
-        """
-        Assigning to a global and then not using that global is perfectly
-        acceptable. Do not mistake it for an unused local variable.
-        """
-        self.flakes('''
-        b = 0
-        def a():
-            global b
-            b = 1
-        ''')
-
-    def test_assignToMember(self):
-        """
-        Assigning to a member of another object and then not using that member
-        variable is perfectly acceptable. Do not mistake it for an unused
-        local variable.
-        """
-        # XXX: Adding this test didn't generate a failure. Maybe not
-        # necessary?
-        self.flakes('''
-        class b:
-            pass
-        def a():
-            b.foo = 1
-        ''')
-
-    def test_assignInForLoop(self):
-        """
-        Don't warn when a variable in a for loop is assigned to but not used.
-        """
-        self.flakes('''
-        def f():
-            for i in range(10):
-                pass
-        ''')
-
-    def test_assignInListComprehension(self):
-        """
-        Don't warn when a variable in a list comprehension is assigned to but
-        not used.
-        """
-        self.flakes('''
-        def f():
-            [None for i in range(10)]
-        ''')
-
-    def test_generatorExpression(self):
-        """
-        Don't warn when a variable in a generator expression is assigned to
-        but not used.
-        """
-        self.flakes('''
-        def f():
-            (None for i in range(10))
-        ''')
-
-    def test_assignmentInsideLoop(self):
-        """
-        Don't warn when a variable assignment occurs lexically after its use.
-        """
-        self.flakes('''
-        def f():
-            x = None
-            for i in range(10):
-                if i > 2:
-                    return x
-                x = i * 2
-        ''')
-
-    def test_tupleUnpacking(self):
-        """
-        Don't warn when a variable included in tuple unpacking is unused. It's
-        very common for variables in a tuple unpacking assignment to be unused
-        in good Python code, so warning will only create false positives.
-        """
-        self.flakes('''
-        def f():
-            (x, y) = 1, 2
-        ''')
-
-    def test_listUnpacking(self):
-        """
-        Don't warn when a variable included in list unpacking is unused.
-        """
-        self.flakes('''
-        def f():
-            [x, y] = [1, 2]
-        ''')
-
-    def test_closedOver(self):
-        """
-        Don't warn when the assignment is used in an inner function.
-        """
-        self.flakes('''
-        def barMaker():
-            foo = 5
-            def bar():
-                return foo
-            return bar
-        ''')
-
-    def test_doubleClosedOver(self):
-        """
-        Don't warn when the assignment is used in an inner function, even if
-        that inner function itself is in an inner function.
-        """
-        self.flakes('''
-        def barMaker():
-            foo = 5
-            def bar():
-                def baz():
-                    return foo
-            return bar
-        ''')
-
-
-class Python25Test(harness.Test):
-    """
-    Tests for checking of syntax only available in Python 2.5 and newer.
-    """
-    if version_info < (2, 5):
-        skip = "Python 2.5 required for if-else and with tests"
-
-    def test_ifexp(self):
-        """
-        Test C{foo if bar else baz} statements.
-        """
-        self.flakes("a = 'moo' if True else 'oink'")
-        self.flakes("a = foo if True else 'oink'", m.UndefinedName)
-        self.flakes("a = 'moo' if True else bar", m.UndefinedName)
-
-    def test_withStatementNoNames(self):
-        """
-        No warnings are emitted for using inside or after a nameless C{with}
-        statement a name defined beforehand.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        bar = None
-        with open("foo"):
-            bar
-        bar
-        ''')
-
-    def test_withStatementSingleName(self):
-        """
-        No warnings are emitted for using a name defined by a C{with} statement
-        within the suite or afterwards.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        with open('foo') as bar:
-            bar
-        bar
-        ''')
-
-    def test_withStatementAttributeName(self):
-        """
-        No warnings are emitted for using an attribute as the target of a
-        C{with} statement.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        import foo
-        with open('foo') as foo.bar:
-            pass
-        ''')
-
-    def test_withStatementSubscript(self):
-        """
-        No warnings are emitted for using a subscript as the target of a
-        C{with} statement.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        import foo
-        with open('foo') as foo[0]:
-            pass
-        ''')
-
-    def test_withStatementSubscriptUndefined(self):
-        """
-        An undefined name warning is emitted if the subscript used as the
-        target of a C{with} statement is not defined.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        import foo
-        with open('foo') as foo[bar]:
-            pass
-        ''', m.UndefinedName)
-
-    def test_withStatementTupleNames(self):
-        """
-        No warnings are emitted for using any of the tuple of names defined by
-        a C{with} statement within the suite or afterwards.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        with open('foo') as (bar, baz):
-            bar, baz
-        bar, baz
-        ''')
-
-    def test_withStatementListNames(self):
-        """
-        No warnings are emitted for using any of the list of names defined by a
-        C{with} statement within the suite or afterwards.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        with open('foo') as [bar, baz]:
-            bar, baz
-        bar, baz
-        ''')
-
-    def test_withStatementComplicatedTarget(self):
-        """
-        If the target of a C{with} statement uses any or all of the valid forms
-        for that part of the grammar (See
-        U{http://docs.python.org/reference/
-            compound_stmts.html#the-with-statement}),
-        the names involved are checked both for definedness and any bindings
-        created are respected in the suite of the statement and afterwards.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        c = d = e = g = h = i = None
-        with open('foo') as [(a, b), c[d], e.f, g[h:i]]:
-            a, b, c, d, e, g, h, i
-        a, b, c, d, e, g, h, i
-        ''')
-
-    def test_withStatementSingleNameUndefined(self):
-        """
-        An undefined name warning is emitted if the name first defined by a
-        C{with} statement is used before the C{with} statement.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        bar
-        with open('foo') as bar:
-            pass
-        ''', m.UndefinedName)
-
-    def test_withStatementTupleNamesUndefined(self):
-        """
-        An undefined name warning is emitted if a name first defined by a the
-        tuple-unpacking form of the C{with} statement is used before the
-        C{with} statement.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        baz
-        with open('foo') as (bar, baz):
-            pass
-        ''', m.UndefinedName)
-
-    def test_withStatementSingleNameRedefined(self):
-        """
-        A redefined name warning is emitted if a name bound by an import is
-        rebound by the name defined by a C{with} statement.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        import bar
-        with open('foo') as bar:
-            pass
-        ''', m.RedefinedWhileUnused)
-
-    def test_withStatementTupleNamesRedefined(self):
-        """
-        A redefined name warning is emitted if a name bound by an import is
-        rebound by one of the names defined by the tuple-unpacking form of a
-        C{with} statement.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        import bar
-        with open('foo') as (bar, baz):
-            pass
-        ''', m.RedefinedWhileUnused)
-
-    def test_withStatementUndefinedInside(self):
-        """
-        An undefined name warning is emitted if a name is used inside the
-        body of a C{with} statement without first being bound.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        with open('foo') as bar:
-            baz
-        ''', m.UndefinedName)
-
-    def test_withStatementNameDefinedInBody(self):
-        """
-        A name defined in the body of a C{with} statement can be used after
-        the body ends without warning.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        with open('foo') as bar:
-            baz = 10
-        baz
-        ''')
-
-    def test_withStatementUndefinedInExpression(self):
-        """
-        An undefined name warning is emitted if a name in the I{test}
-        expression of a C{with} statement is undefined.
-        """
-        self.flakes('''
-        from __future__ import with_statement
-        with bar as baz:
-            pass
-        ''', m.UndefinedName)
-
-        self.flakes('''
-        from __future__ import with_statement
-        with bar as bar:
-            pass
-        ''', m.UndefinedName)
-
-
-class Python27Test(harness.Test):
-    """
-    Tests for checking of syntax only available in Python 2.7 and newer.
-    """
-    if version_info < (2, 7):
-        skip = "Python 2.7 required for dict/set comprehension tests"
-
-    def test_dictComprehension(self):
-        """
-        Dict comprehensions are properly handled.
-        """
-        self.flakes('''
-        a = {1: x for x in range(10)}
-        ''')
-
-    def test_setComprehensionAndLiteral(self):
-        """
-        Set comprehensions are properly handled.
-        """
-        self.flakes('''
-        a = {1, 2, 3}
-        b = {x for x in range(10)}
-        ''')

flake8/test/test_script.py

-
-"""
-Tests for L{pyflakes.scripts.pyflakes}.
-"""
-
-import sys
-from StringIO import StringIO
-
-from twisted.python.filepath import FilePath
-from twisted.trial.unittest import TestCase
-
-from pyflakes.scripts.pyflakes import checkPath
-
-
-def withStderrTo(stderr, f):
-    """
-    Call C{f} with C{sys.stderr} redirected to C{stderr}.
-    """
-    (outer, sys.stderr) = (sys.stderr, stderr)
-    try:
-        return f()
-    finally:
-        sys.stderr = outer
-
-
-class CheckTests(TestCase):
-    """
-    Tests for L{check} and L{checkPath} which check a file for flakes.
-    """
-    def test_missingTrailingNewline(self):
-        """
-        Source which doesn't end with a newline shouldn't cause any
-        exception to be raised nor an error indicator to be returned by
-        L{check}.
-        """
-        fName = self.mktemp()
-        FilePath(fName).setContent("def foo():\n\tpass\n\t")
-        self.assertFalse(checkPath(fName))
-
-    def test_checkPathNonExisting(self):
-        """
-        L{checkPath} handles non-existing files.
-        """
-        err = StringIO()
-        count = withStderrTo(err, lambda: checkPath('extremo'))
-        self.assertEquals(err.getvalue(),
-                          'extremo: No such file or directory\n')
-        self.assertEquals(count, 1)
-
-    def test_multilineSyntaxError(self):
-        """
-        Source which includes a syntax error which results in the raised
-        L{SyntaxError.text} containing multiple lines of source are reported
-        with only the last line of that source.
-        """
-        source = """\
-def foo():
-    '''
-
-def bar():
-    pass
-
-def baz():
-    '''quux'''
-"""
-
-        # Sanity check - SyntaxError.text should be multiple lines, if it
-        # isn't, something this test was unprepared for has happened.
-        def evaluate(source):
-            exec source
-        exc = self.assertRaises(SyntaxError, evaluate, source)
-        self.assertTrue(exc.text.count('\n') > 1)
-
-        sourcePath = FilePath(self.mktemp())
-        sourcePath.setContent(source)
-        err = StringIO()
-        count = withStderrTo(err, lambda: checkPath(sourcePath.path))
-        self.assertEqual(count, 1)
-
-        self.assertEqual(
-            err.getvalue(),
-            """\
-%s:8: invalid syntax
-    '''quux'''
-           ^
-""" % (sourcePath.path,))
-
-    def test_eofSyntaxError(self):
-        """
-        The error reported for source files which end prematurely causing a
-        syntax error reflects the cause for the syntax error.
-        """
-        source = "def foo("
-        sourcePath = FilePath(self.mktemp())
-        sourcePath.setContent(source)
-        err = StringIO()
-        count = withStderrTo(err, lambda: checkPath(sourcePath.path))
-        self.assertEqual(count, 1)
-        self.assertEqual(
-            err.getvalue(),
-            """\
-%s:1: unexpected EOF while parsing
-def foo(
-         ^
-""" % (sourcePath.path,))
-
-    def test_nonDefaultFollowsDefaultSyntaxError(self):
-        """
-        Source which has a non-default argument following a default argument
-        should include the line number of the syntax error.  However these
-        exceptions do not include an offset.
-        """
-        source = """\
-def foo(bar=baz, bax):
-    pass
-"""
-        sourcePath = FilePath(self.mktemp())
-        sourcePath.setContent(source)
-        err = StringIO()
-        count = withStderrTo(err, lambda: checkPath(sourcePath.path))
-        self.assertEqual(count, 1)
-        self.assertEqual(
-            err.getvalue(),
-            """\
-%s:1: non-default argument follows default argument
-def foo(bar=baz, bax):
-""" % (sourcePath.path,))
-
-    def test_nonKeywordAfterKeywordSyntaxError(self):
-        """
-        Source which has a non-keyword argument after a keyword argument should
-        include the line number of the syntax error.  However these exceptions
-        do not include an offset.
-        """
-        source = """\
-foo(bar=baz, bax)
-"""
-        sourcePath = FilePath(self.mktemp())
-        sourcePath.setContent(source)
-        err = StringIO()
-        count = withStderrTo(err, lambda: checkPath(sourcePath.path))
-        self.assertEqual(count, 1)
-        self.assertEqual(
-            err.getvalue(),
-            """\
-%s:1: non-keyword arg after keyword arg
-foo(bar=baz, bax)
-""" % (sourcePath.path,))
-
-    def test_permissionDenied(self):
-        """
-        If the a source file is not readable, this is reported on standard
-        error.
-        """
-        sourcePath = FilePath(self.mktemp())
-        sourcePath.setContent('')
-        sourcePath.chmod(0)
-        err = StringIO()
-        count = withStderrTo(err, lambda: checkPath(sourcePath.path))
-        self.assertEquals(count, 1)
-        self.assertEquals(
-            err.getvalue(), "%s: Permission denied\n" % (sourcePath.path,))
-
-    def test_misencodedFile(self):
-        """
-        If a source file contains bytes which cannot be decoded, this is
-        reported on stderr.
-        """
-        source = u"""\
-# coding: ascii
-x = "\N{SNOWMAN}"
-""".encode('utf-8')
-        sourcePath = FilePath(self.mktemp())
-        sourcePath.setContent(source)
-        err = StringIO()
-        count = withStderrTo(err, lambda: checkPath(sourcePath.path))
-        self.assertEquals(count, 1)
-        self.assertEquals(
-            err.getvalue(),
-            "%s: problem decoding source\n" % (sourcePath.path,))

flake8/test/test_undefined_names.py

-
-from _ast import PyCF_ONLY_AST
-
-from twisted.trial.unittest import TestCase
-
-from pyflakes import messages as m, checker
-from pyflakes.test import harness
-
-
-class Test(harness.Test):
-    def test_undefined(self):
-        self.flakes('bar', m.UndefinedName)
-
-    def test_definedInListComp(self):
-        self.flakes('[a for a in range(10) if a]')
-
-    def test_functionsNeedGlobalScope(self):
-        self.flakes('''
-        class a:
-            def b():
-                fu
-        fu = 1
-        ''')
-
-    def test_builtins(self):
-        self.flakes('range(10)')
-
-    def test_magicGlobalsFile(self):
-        """
-        Use of the C{__file__} magic global should not emit an undefined name
-        warning.
-        """
-        self.flakes('__file__')
-
-    def test_magicGlobalsBuiltins(self):
-        """
-        Use of the C{__builtins__} magic global should not emit an undefined
-        name warning.
-        """
-        self.flakes('__builtins__')
-
-    def test_magicGlobalsName(self):
-        """
-        Use of the C{__name__} magic global should not emit an undefined name
-        warning.
-        """
-        self.flakes('__name__')
-
-    def test_magicGlobalsPath(self):
-        """
-        Use of the C{__path__} magic global should not emit an undefined name
-        warning, if you refer to it from a file called __init__.py.
-        """
-        self.flakes('__path__', m.UndefinedName)
-        self.flakes('__path__', filename='package/__init__.py')
-
-    def test_globalImportStar(self):
-        '''Can't find undefined names with import *'''
-        self.flakes('from fu import *; bar', m.ImportStarUsed)
-
-    def test_localImportStar(self):
-        '''
-        A local import * still allows undefined names to be found
-        in upper scopes
-        '''
-        self.flakes('''
-        def a():
-            from fu import *
-        bar
-        ''', m.ImportStarUsed, m.UndefinedName)
-
-    def test_unpackedParameter(self):
-        '''Unpacked function parameters create bindings'''
-        self.flakes('''
-        def a((bar, baz)):
-            bar; baz
-        ''')
-
-    def test_definedByGlobal(self):
-        '''
-        "global" can make an otherwise undefined name
-        in another function defined
-        '''
-        self.flakes('''
-        def a(): global fu; fu = 1
-        def b(): fu
-        ''')
-    test_definedByGlobal.todo = ''
-
-    def test_globalInGlobalScope(self):
-        """
-        A global statement in the global scope is ignored.
-        """
-        self.flakes('''
-        global x
-        def foo():
-            print x
-        ''', m.UndefinedName)
-
-    def test_del(self):
-        '''del deletes bindings'''
-        self.flakes('a = 1; del a; a', m.UndefinedName)
-
-    def test_delGlobal(self):
-        '''del a global binding from a function'''
-        self.flakes('''
-        a = 1
-        def f():
-            global a
-            del a
-        a
-        ''')
-
-    def test_delUndefined(self):
-        '''del an undefined name'''
-        self.flakes('del a', m.UndefinedName)
-
-    def test_globalFromNestedScope(self):
-        '''global names are available from nested scopes'''
-        self.flakes('''
-        a = 1
-        def b():
-            def c():
-                a
-        ''')
-
-    def test_laterRedefinedGlobalFromNestedScope(self):
-        """
-        Test that referencing a local name that shadows a global, before it is
-        defined, generates a warning.
-        """
-        self.flakes('''
-        a = 1
-        def fun():
-            a
-            a = 2
-            return a
-        ''', m.UndefinedLocal)
-
-    def test_laterRedefinedGlobalFromNestedScope2(self):
-        """
-        Test that referencing a local name in a nested scope that shadows a
-        global declared in an enclosing scope, before it is defined, generates
-        a warning.
-        """
-        self.flakes('''
-            a = 1
-            def fun():
-                global a
-                def fun2():
-                    a
-                    a = 2
-                    return a
-        ''', m.UndefinedLocal)
-
-    def test_intermediateClassScopeIgnored(self):
-        """
-        If a name defined in an enclosing scope is shadowed by a local variable
-        and the name is used locally before it is bound, an unbound local
-        warning is emitted, even if there is a class scope between
-        the enclosing scope and the local scope.
-        """
-        self.flakes('''
-        def f():
-            x = 1
-            class g:
-                def h(self):
-                    a = x
-                    x = None
-                    print x, a
-            print x
-        ''', m.UndefinedLocal)
-
-    def test_doubleNestingReportsClosestName(self):
-        """
-        Test that referencing a local name in a nested scope that shadows a
-        variable declared in two different outer scopes before it is defined
-        in the innermost scope generates an UnboundLocal warning which
-        refers to the nearest shadowed name.
-        """
-        exc = self.flakes('''
-            def a():
-                x = 1
-                def b():
-                    x = 2 # line 5
-                    def c():
-                        x
-                        x = 3
-                        return x
-                    return x
-                return x
-        ''', m.UndefinedLocal).messages[0]
-        self.assertEqual(exc.message_args, ('x', 5))
-
-    def test_laterRedefinedGlobalFromNestedScope3(self):
-        """
-        Test that referencing a local name in a nested scope that shadows a
-        global, before it is defined, generates a warning.
-        """
-        self.flakes('''
-            def fun():
-                a = 1
-                def fun2():
-                    a
-                    a = 1
-                    return a
-                return a
-        ''', m.UndefinedLocal)
-
-    def test_nestedClass(self):
-        '''nested classes can access enclosing scope'''
-        self.flakes('''
-        def f(foo):
-            class C:
-                bar = foo
-                def f(self):
-                    return foo
-            return C()
-
-        f(123).f()
-        ''')
-
-    def test_badNestedClass(self):
-        '''free variables in nested classes must bind at class creation'''
-        self.flakes('''
-        def f():
-            class C:
-                bar = foo
-            foo = 456
-            return foo
-        f()
-        ''', m.UndefinedName)
-
-    def test_definedAsStarArgs(self):
-        '''star and double-star arg names are defined'''
-        self.flakes('''
-        def f(a, *b, **c):
-            print a, b, c
-        ''')
-
-    def test_definedInGenExp(self):
-        """
-        Using the loop variable of a generator expression results in no
-        warnings.
-        """
-        self.flakes('(a for a in xrange(10) if a)')
-
-
-class NameTests(TestCase):
-    """
-    Tests for some extra cases of name handling.
-    """
-    def test_impossibleContext(self):
-        """
-        A Name node with an unrecognized context results in a RuntimeError
-        being raised.
-        """
-        tree = compile("x = 10", "<test>", "exec", PyCF_ONLY_AST)
-        # Make it into something unrecognizable.
-        tree.body[0].targets[0].ctx = object()
-        self.assertRaises(RuntimeError, checker.Checker, tree)

flake8/tests/__init__.py

+#

flake8/tests/test_mccabe.py

+import unittest
+import sys
+from StringIO import StringIO
+
+from flake8.mccabe import get_code_complexity
+
+
+_GLOBAL = """\
+
+for i in range(10):
+    pass
+
+def a():
+    def b():
+        def c():
+            pass
+        c()
+    b()
+
+"""
+
+
+class McCabeTest(unittest.TestCase):
+
+    def setUp(self):
+        self.old = sys.stdout
+        self.out = sys.stdout = StringIO()
+
+    def tearDown(self):
+        sys.sdtout = self.old
+
+    def test_sample(self):
+        self.assertEqual(get_code_complexity(_GLOBAL, 1), 2)
+        self.out.seek(0)
+        res = self.out.read().strip().split('\n')
+        wanted = ["stdin:5:1: 'a' is too complex (3)",
+                  'stdin:Loop 2 is too complex (1)']
+        self.assertEqual(res, wanted)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.