PNG  IHDRxsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<,tEXtComment File Manager

File Manager

Path: /opt/cloudlinux/venv/lib64/python3.11/site-packages/pyflakes/test/

Viewing File: test_other.py

"""
Tests for various Pyflakes behavior.
"""

from sys import version_info

from pyflakes import messages as m
from pyflakes.test.harness import TestCase, skip, skipIf


class Test(TestCase):

    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.UndefinedLocal, m.UnusedVariable)

    def test_redefinedInGenerator(self):
        """
        Test that reusing a variable in a generator does not raise
        a warning.
        """
        self.flakes('''
        a = 1
        (1 for a, b in [(1, 2)])
        ''')
        self.flakes('''
        class A:
            a = 1
            list(1 for a, b in [(1, 2)])
        ''')
        self.flakes('''
        def f():
            a = 1
            (1 for a, b in [(1, 2)])
        ''', m.UnusedVariable)
        self.flakes('''
        (1 for a, b in [(1, 2)])
        (1 for a, b in [(1, 2)])
        ''')
        self.flakes('''
        for a, b in [(1, 2)]:
            pass
        (1 for a, b in [(1, 2)])
        ''')

    def test_redefinedInSetComprehension(self):
        """
        Test that reusing a variable in a set comprehension does not raise
        a warning.
        """
        self.flakes('''
        a = 1
        {1 for a, b in [(1, 2)]}
        ''')
        self.flakes('''
        class A:
            a = 1
            {1 for a, b in [(1, 2)]}
        ''')
        self.flakes('''
        def f():
            a = 1
            {1 for a, b in [(1, 2)]}
        ''', m.UnusedVariable)
        self.flakes('''
        {1 for a, b in [(1, 2)]}
        {1 for a, b in [(1, 2)]}
        ''')
        self.flakes('''
        for a, b in [(1, 2)]:
            pass
        {1 for a, b in [(1, 2)]}
        ''')

    def test_redefinedInDictComprehension(self):
        """
        Test that reusing a variable in a dict comprehension does not raise
        a warning.
        """
        self.flakes('''
        a = 1
        {1: 42 for a, b in [(1, 2)]}
        ''')
        self.flakes('''
        class A:
            a = 1
            {1: 42 for a, b in [(1, 2)]}
        ''')
        self.flakes('''
        def f():
            a = 1
            {1: 42 for a, b in [(1, 2)]}
        ''', m.UnusedVariable)
        self.flakes('''
        {1: 42 for a, b in [(1, 2)]}
        {1: 42 for a, b in [(1, 2)]}
        ''')
        self.flakes('''
        for a, b in [(1, 2)]:
            pass
        {1: 42 for a, b in [(1, 2)]}
        ''')

    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.RedefinedWhileUnused)

    def test_redefinedUnderscoreFunction(self):
        """
        Test that shadowing a function definition named with underscore doesn't
        raise anything.
        """
        self.flakes('''
        def _(): pass
        def _(): pass
        ''')

    def test_redefinedUnderscoreImportation(self):
        """
        Test that shadowing an underscore importation raises a warning.
        """
        self.flakes('''
        from .i18n import _
        def _(): pass
        ''', m.RedefinedWhileUnused)

    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.RedefinedWhileUnused)

    def test_redefinedIfElseFunction(self):
        """
        Test that shadowing a function definition twice in an if
        and else block does not raise a warning.
        """
        self.flakes('''
        if True:
            def a(): pass
        else:
            def a(): pass
        ''')

    def test_redefinedIfFunction(self):
        """
        Test that shadowing a function definition within an if block
        raises a warning.
        """
        self.flakes('''
        if True:
            def a(): pass
            def a(): pass
        ''', m.RedefinedWhileUnused)

    def test_redefinedTryExceptFunction(self):
        """
        Test that shadowing a function definition twice in try
        and except block does not raise a warning.
        """
        self.flakes('''
        try:
            def a(): pass
        except:
            def a(): pass
        ''')

    def test_redefinedTryFunction(self):
        """
        Test that shadowing a function definition within a try block
        raises a warning.
        """
        self.flakes('''
        try:
            def a(): pass
            def a(): pass
        except:
            pass
        ''', m.RedefinedWhileUnused)

    def test_redefinedIfElseInListComp(self):
        """
        Test that shadowing a variable in a list comprehension in
        an if and else block does not raise a warning.
        """
        self.flakes('''
        if False:
            a = 1
        else:
            [a for a in '12']
        ''')

    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_modernProperty(self):
        self.flakes("""
        class A:
            @property
            def t(self):
                pass
            @t.setter
            def t(self, value):
                pass
            @t.deleter
            def t(self):
                pass
        """)

    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_classRedefinition(self):
        """
        If a class is defined twice in the same module, a warning is emitted.
        """
        self.flakes('''
        class Foo:
            pass
        class Foo:
            pass
        ''', m.RedefinedWhileUnused)

    def test_functionRedefinedAsClass(self):
        """
        If a function is redefined as a class, a warning is emitted.
        """
        self.flakes('''
        def Foo():
            pass
        class Foo:
            pass
        ''', m.RedefinedWhileUnused)

    def test_classRedefinedAsFunction(self):
        """
        If a class is redefined as a function, a warning is emitted.
        """
        self.flakes('''
        class Foo:
            pass
        def Foo():
            pass
        ''', m.RedefinedWhileUnused)

    def test_classWithReturn(self):
        """
        If a return is used inside a class, a warning is emitted.
        """
        self.flakes('''
        class Foo(object):
            return
        ''', m.ReturnOutsideFunction)

    def test_moduleWithReturn(self):
        """
        If a return is used at the module level, a warning is emitted.
        """
        self.flakes('''
        return
        ''', m.ReturnOutsideFunction)

    def test_classWithYield(self):
        """
        If a yield is used inside a class, a warning is emitted.
        """
        self.flakes('''
        class Foo(object):
            yield
        ''', m.YieldOutsideFunction)

    def test_moduleWithYield(self):
        """
        If a yield is used at the module level, a warning is emitted.
        """
        self.flakes('''
        yield
        ''', m.YieldOutsideFunction)

    def test_classWithYieldFrom(self):
        """
        If a yield from is used inside a class, a warning is emitted.
        """
        self.flakes('''
        class Foo(object):
            yield from range(10)
        ''', m.YieldOutsideFunction)

    def test_moduleWithYieldFrom(self):
        """
        If a yield from is used at the module level, a warning is emitted.
        """
        self.flakes('''
        yield from range(10)
        ''', m.YieldOutsideFunction)

    def test_continueOutsideLoop(self):
        self.flakes('''
        continue
        ''', m.ContinueOutsideLoop)

        self.flakes('''
        def f():
            continue
        ''', m.ContinueOutsideLoop)

        self.flakes('''
        while True:
            pass
        else:
            continue
        ''', m.ContinueOutsideLoop)

        self.flakes('''
        while True:
            pass
        else:
            if 1:
                if 2:
                    continue
        ''', m.ContinueOutsideLoop)

        self.flakes('''
        while True:
            def f():
                continue
        ''', m.ContinueOutsideLoop)

        self.flakes('''
        while True:
            class A:
                continue
        ''', m.ContinueOutsideLoop)

    def test_continueInsideLoop(self):
        self.flakes('''
        while True:
            continue
        ''')

        self.flakes('''
        for i in range(10):
            continue
        ''')

        self.flakes('''
        while True:
            if 1:
                continue
        ''')

        self.flakes('''
        for i in range(10):
            if 1:
                continue
        ''')

        self.flakes('''
        while True:
            while True:
                pass
            else:
                continue
        else:
            pass
        ''')

        self.flakes('''
        while True:
            try:
                pass
            finally:
                while True:
                    continue
        ''')

    @skipIf(version_info > (3, 8), "Python <= 3.8 only")
    def test_continueInFinally(self):
        # 'continue' inside 'finally' is a special syntax error
        # that is removed in 3.8
        self.flakes('''
        while True:
            try:
                pass
            finally:
                continue
        ''', m.ContinueInFinally)

        self.flakes('''
        while True:
            try:
                pass
            finally:
                if 1:
                    if 2:
                        continue
        ''', m.ContinueInFinally)

        # Even when not in a loop, this is the error Python gives
        self.flakes('''
        try:
            pass
        finally:
            continue
        ''', m.ContinueInFinally)

    def test_breakOutsideLoop(self):
        self.flakes('''
        break
        ''', m.BreakOutsideLoop)

        self.flakes('''
        def f():
            break
        ''', m.BreakOutsideLoop)

        self.flakes('''
        while True:
            pass
        else:
            break
        ''', m.BreakOutsideLoop)

        self.flakes('''
        while True:
            pass
        else:
            if 1:
                if 2:
                    break
        ''', m.BreakOutsideLoop)

        self.flakes('''
        while True:
            def f():
                break
        ''', m.BreakOutsideLoop)

        self.flakes('''
        while True:
            class A:
                break
        ''', m.BreakOutsideLoop)

        self.flakes('''
        try:
            pass
        finally:
            break
        ''', m.BreakOutsideLoop)

    def test_breakInsideLoop(self):
        self.flakes('''
        while True:
            break
        ''')

        self.flakes('''
        for i in range(10):
            break
        ''')

        self.flakes('''
        while True:
            if 1:
                break
        ''')

        self.flakes('''
        for i in range(10):
            if 1:
                break
        ''')

        self.flakes('''
        while True:
            while True:
                pass
            else:
                break
        else:
            pass
        ''')

        self.flakes('''
        while True:
            try:
                pass
            finally:
                while True:
                    break
        ''')

        self.flakes('''
        while True:
            try:
                pass
            finally:
                break
        ''')

        self.flakes('''
        while True:
            try:
                pass
            finally:
                if 1:
                    if 2:
                        break
        ''')

    def test_defaultExceptLast(self):
        """
        A default except block should be last.

        YES:

        try:
            ...
        except Exception:
            ...
        except:
            ...

        NO:

        try:
            ...
        except:
            ...
        except Exception:
            ...
        """
        self.flakes('''
        try:
            pass
        except ValueError:
            pass
        ''')

        self.flakes('''
        try:
            pass
        except ValueError:
            pass
        except:
            pass
        ''')

        self.flakes('''
        try:
            pass
        except:
            pass
        ''')

        self.flakes('''
        try:
            pass
        except ValueError:
            pass
        else:
            pass
        ''')

        self.flakes('''
        try:
            pass
        except:
            pass
        else:
            pass
        ''')

        self.flakes('''
        try:
            pass
        except ValueError:
            pass
        except:
            pass
        else:
            pass
        ''')

    def test_defaultExceptNotLast(self):
        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        except:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        except:
            pass
        except ValueError:
            pass
        ''', m.DefaultExceptNotLast, m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        else:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except:
            pass
        else:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        except:
            pass
        else:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        except:
            pass
        except ValueError:
            pass
        else:
            pass
        ''', m.DefaultExceptNotLast, m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        finally:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except:
            pass
        finally:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        except:
            pass
        finally:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        except:
            pass
        except ValueError:
            pass
        finally:
            pass
        ''', m.DefaultExceptNotLast, m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        else:
            pass
        finally:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except:
            pass
        else:
            pass
        finally:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        except:
            pass
        else:
            pass
        finally:
            pass
        ''', m.DefaultExceptNotLast)

        self.flakes('''
        try:
            pass
        except:
            pass
        except ValueError:
            pass
        except:
            pass
        except ValueError:
            pass
        else:
            pass
        finally:
            pass
        ''', m.DefaultExceptNotLast, m.DefaultExceptNotLast)

    def test_starredAssignmentNoError(self):
        """
        Python 3 extended iterable unpacking
        """
        self.flakes('''
        a, *b = range(10)
        ''')

        self.flakes('''
        *a, b = range(10)
        ''')

        self.flakes('''
        a, *b, c = range(10)
        ''')

        self.flakes('''
        (a, *b) = range(10)
        ''')

        self.flakes('''
        (*a, b) = range(10)
        ''')

        self.flakes('''
        (a, *b, c) = range(10)
        ''')

        self.flakes('''
        [a, *b] = range(10)
        ''')

        self.flakes('''
        [*a, b] = range(10)
        ''')

        self.flakes('''
        [a, *b, c] = range(10)
        ''')

        # Taken from test_unpack_ex.py in the cPython source
        s = ", ".join("a%d" % i for i in range(1 << 8 - 1)) + \
            ", *rest = range(1<<8)"
        self.flakes(s)

        s = "(" + ", ".join("a%d" % i for i in range(1 << 8 - 1)) + \
            ", *rest) = range(1<<8)"
        self.flakes(s)

        s = "[" + ", ".join("a%d" % i for i in range(1 << 8 - 1)) + \
            ", *rest] = range(1<<8)"
        self.flakes(s)

    def test_starredAssignmentErrors(self):
        """
        SyntaxErrors (not encoded in the ast) surrounding Python 3 extended
        iterable unpacking
        """
        # Taken from test_unpack_ex.py in the cPython source
        s = ", ".join("a%d" % i for i in range(1 << 8)) + \
            ", *rest = range(1<<8 + 1)"
        self.flakes(s, m.TooManyExpressionsInStarredAssignment)

        s = "(" + ", ".join("a%d" % i for i in range(1 << 8)) + \
            ", *rest) = range(1<<8 + 1)"
        self.flakes(s, m.TooManyExpressionsInStarredAssignment)

        s = "[" + ", ".join("a%d" % i for i in range(1 << 8)) + \
            ", *rest] = range(1<<8 + 1)"
        self.flakes(s, m.TooManyExpressionsInStarredAssignment)

        s = ", ".join("a%d" % i for i in range(1 << 8 + 1)) + \
            ", *rest = range(1<<8 + 2)"
        self.flakes(s, m.TooManyExpressionsInStarredAssignment)

        s = "(" + ", ".join("a%d" % i for i in range(1 << 8 + 1)) + \
            ", *rest) = range(1<<8 + 2)"
        self.flakes(s, m.TooManyExpressionsInStarredAssignment)

        s = "[" + ", ".join("a%d" % i for i in range(1 << 8 + 1)) + \
            ", *rest] = range(1<<8 + 2)"
        self.flakes(s, m.TooManyExpressionsInStarredAssignment)

        # No way we can actually test this!
        # s = "*rest, " + ", ".join("a%d" % i for i in range(1<<24)) + \
        #    ", *rest = range(1<<24 + 1)"
        # self.flakes(s, m.TooManyExpressionsInStarredAssignment)

        self.flakes('''
        a, *b, *c = range(10)
        ''', m.TwoStarredExpressions)

        self.flakes('''
        a, *b, c, *d = range(10)
        ''', m.TwoStarredExpressions)

        self.flakes('''
        *a, *b, *c = range(10)
        ''', m.TwoStarredExpressions)

        self.flakes('''
        (a, *b, *c) = range(10)
        ''', m.TwoStarredExpressions)

        self.flakes('''
        (a, *b, c, *d) = range(10)
        ''', m.TwoStarredExpressions)

        self.flakes('''
        (*a, *b, *c) = range(10)
        ''', m.TwoStarredExpressions)

        self.flakes('''
        [a, *b, *c] = range(10)
        ''', m.TwoStarredExpressions)

        self.flakes('''
        [a, *b, c, *d] = range(10)
        ''', m.TwoStarredExpressions)

        self.flakes('''
        [*a, *b, *c] = range(10)
        ''', m.TwoStarredExpressions)

    @skip("todo: Too hard to make this warn but other cases stay silent")
    def test_doubleAssignment(self):
        """
        If a variable is re-assigned to without being used, no warning is
        emitted.
        """
        self.flakes('''
        x = 10
        x = 20
        ''', m.RedefinedWhileUnused)

    def test_doubleAssignmentConditionally(self):
        """
        If a variable is re-assigned within a conditional, no warning is
        emitted.
        """
        self.flakes('''
        x = 10
        if True:
            x = 20
        ''')

    def test_doubleAssignmentWithUse(self):
        """
        If a variable is re-assigned to after being used, no warning is
        emitted.
        """
        self.flakes('''
        x = 10
        y = x * 2
        x = 20
        ''')

    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 defined 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,:]
        ''')

    def test_varAugmentedAssignment(self):
        """
        Augmented assignment of a variable is supported.
        We don't care about var refs.
        """
        self.flakes('''
        foo = 0
        foo += 1
        ''')

    def test_attrAugmentedAssignment(self):
        """
        Augmented assignment of attributes is supported.
        We don't care about attr refs.
        """
        self.flakes('''
        foo = None
        foo.bar += foo.baz
        ''')

    def test_globalDeclaredInDifferentScope(self):
        """
        A 'global' can be declared in one scope and reused in another.
        """
        self.flakes('''
        def f(): global foo
        def g(): foo = 'anything'; foo.is_used()
        ''')

    def test_function_arguments(self):
        """
        Test to traverse ARG and ARGUMENT handler
        """
        self.flakes('''
        def foo(a, b):
            pass
        ''')

        self.flakes('''
        def foo(a, b, c=0):
            pass
        ''')

        self.flakes('''
        def foo(a, b, c=0, *args):
            pass
        ''')

        self.flakes('''
        def foo(a, b, c=0, *args, **kwargs):
            pass
        ''')

    def test_function_arguments_python3(self):
        self.flakes('''
        def foo(a, b, c=0, *args, d=0, **kwargs):
            pass
        ''')


class TestUnusedAssignment(TestCase):
    """
    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_unusedUnderscoreVariable(self):
        """
        Don't warn when the magic "_" (underscore) variable is unused.
        See issue #202.
        """
        self.flakes('''
        def a(unused_param):
            _ = unused_param
        ''')

    def test_unusedVariableAsLocals(self):
        """
        Using locals() it is perfectly valid to have unused variables
        """
        self.flakes('''
        def a():
            b = 1
            return locals()
        ''')

    def test_unusedVariableNoLocals(self):
        """
        Using locals() in wrong scope should not matter
        """
        self.flakes('''
        def a():
            locals()
            def a():
                b = 1
                return
        ''', m.UnusedVariable)

    @skip("todo: Difficult because it doesn't apply in the context of a loop")
    def test_unusedReassignedVariable(self):
        """
        Shadowing a used variable can still raise an UnusedVariable warning.
        """
        self.flakes('''
        def a():
            b = 1
            b.foo()
            b = 2
        ''', m.UnusedVariable)

    def test_variableUsedInLoop(self):
        """
        Shadowing a used variable cannot raise an UnusedVariable warning in the
        context of a loop.
        """
        self.flakes('''
        def a():
            b = True
            while b:
                b = False
        ''')

    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_assignToNonlocal(self):
        """
        Assigning to a nonlocal and then not using that binding is perfectly
        acceptable. Do not mistake it for an unused local variable.
        """
        self.flakes('''
        b = b'0'
        def a():
            nonlocal b
            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(tup):
            (x, y) = tup
        ''')
        self.flakes('''
        def f():
            (x, y) = 1, 2
        ''', m.UnusedVariable, m.UnusedVariable)
        self.flakes('''
        def f():
            (x, y) = coords = 1, 2
            if x > 1:
                print(coords)
        ''')
        self.flakes('''
        def f():
            (x, y) = coords = 1, 2
        ''', m.UnusedVariable)
        self.flakes('''
        def f():
            coords = (x, y) = 1, 2
        ''', m.UnusedVariable)

    def test_listUnpacking(self):
        """
        Don't warn when a variable included in list unpacking is unused.
        """
        self.flakes('''
        def f(tup):
            [x, y] = tup
        ''')
        self.flakes('''
        def f():
            [x, y] = [1, 2]
        ''', m.UnusedVariable, m.UnusedVariable)

    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
        ''')

    def test_tracebackhideSpecialVariable(self):
        """
        Do not warn about unused local variable __tracebackhide__, which is
        a special variable for py.test.
        """
        self.flakes("""
            def helper():
                __tracebackhide__ = True
        """)

    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_if_tuple(self):
        """
        Test C{if (foo,)} conditions.
        """
        self.flakes("""if (): pass""")
        self.flakes("""
        if (
            True
        ):
            pass
        """)
        self.flakes("""
        if (
            True,
        ):
            pass
        """, m.IfTuple)
        self.flakes("""
        x = 1 if (
            True,
        ) else 2
        """, m.IfTuple)

    def test_withStatementNoNames(self):
        """
        No warnings are emitted for using inside or after a nameless C{with}
        statement a name defined beforehand.
        """
        self.flakes('''
        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('''
        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('''
        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('''
        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('''
        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('''
        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('''
        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('''
        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('''
        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 the
        tuple-unpacking form of the C{with} statement is used before the
        C{with} statement.
        """
        self.flakes('''
        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('''
        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('''
        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('''
        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('''
        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('''
        with bar as baz:
            pass
        ''', m.UndefinedName)

        self.flakes('''
        with bar as bar:
            pass
        ''', m.UndefinedName)

    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)}
        ''')

    def test_exceptionUsedInExcept(self):
        self.flakes('''
        try: pass
        except Exception as e: e
        ''')

        self.flakes('''
        def download_review():
            try: pass
            except Exception as e: e
        ''')

    def test_exceptionUnusedInExcept(self):
        self.flakes('''
        try: pass
        except Exception as e: pass
        ''', m.UnusedVariable)

    @skipIf(version_info < (3, 11), 'new in Python 3.11')
    def test_exception_unused_in_except_star(self):
        self.flakes('''
            try:
                pass
            except* OSError as e:
                pass
        ''', m.UnusedVariable)

    def test_exceptionUnusedInExceptInFunction(self):
        self.flakes('''
        def download_review():
            try: pass
            except Exception as e: pass
        ''', m.UnusedVariable)

    def test_exceptWithoutNameInFunction(self):
        """
        Don't issue false warning when an unnamed exception is used.
        Previously, there would be a false warning, but only when the
        try..except was in a function
        """
        self.flakes('''
        import tokenize
        def foo():
            try: pass
            except tokenize.TokenError: pass
        ''')

    def test_exceptWithoutNameInFunctionTuple(self):
        """
        Don't issue false warning when an unnamed exception is used.
        This example catches a tuple of exception types.
        """
        self.flakes('''
        import tokenize
        def foo():
            try: pass
            except (tokenize.TokenError, IndentationError): pass
        ''')

    def test_augmentedAssignmentImportedFunctionCall(self):
        """
        Consider a function that is called on the right part of an
        augassign operation to be used.
        """
        self.flakes('''
        from foo import bar
        baz = 0
        baz += bar()
        ''')

    def test_assert_without_message(self):
        """An assert without a message is not an error."""
        self.flakes('''
        a = 1
        assert a
        ''')

    def test_assert_with_message(self):
        """An assert with a message is not an error."""
        self.flakes('''
        a = 1
        assert a, 'x'
        ''')

    def test_assert_tuple(self):
        """An assert of a non-empty tuple is always True."""
        self.flakes('''
        assert (False, 'x')
        assert (False, )
        ''', m.AssertTuple, m.AssertTuple)

    def test_assert_tuple_empty(self):
        """An assert of an empty tuple is always False."""
        self.flakes('''
        assert ()
        ''')

    def test_assert_static(self):
        """An assert of a static value is not an error."""
        self.flakes('''
        assert True
        assert 1
        ''')

    def test_yieldFromUndefined(self):
        """
        Test C{yield from} statement
        """
        self.flakes('''
        def bar():
            yield from foo()
        ''', m.UndefinedName)

    def test_f_string(self):
        """Test PEP 498 f-strings are treated as a usage."""
        self.flakes('''
        baz = 0
        print(f'\x7b4*baz\N{RIGHT CURLY BRACKET}')
        ''')

    @skipIf(version_info < (3, 8), 'new in Python 3.8')
    def test_assign_expr(self):
        """Test PEP 572 assignment expressions are treated as usage / write."""
        self.flakes('''
        from foo import y
        print(x := y)
        print(x)
        ''')

    @skipIf(version_info < (3, 8), 'new in Python 3.8')
    def test_assign_expr_generator_scope(self):
        """Test assignment expressions in generator expressions."""
        self.flakes('''
        if (any((y := x[0]) for x in [[True]])):
            print(y)
        ''')

    @skipIf(version_info < (3, 8), 'new in Python 3.8')
    def test_assign_expr_nested(self):
        """Test assignment expressions in nested expressions."""
        self.flakes('''
        if ([(y:=x) for x in range(4) if [(z:=q) for q in range(4)]]):
            print(y)
            print(z)
        ''')


class TestStringFormatting(TestCase):

    def test_f_string_without_placeholders(self):
        self.flakes("f'foo'", m.FStringMissingPlaceholders)
        self.flakes('''
            f"""foo
            bar
            """
        ''', m.FStringMissingPlaceholders)
        self.flakes('''
            print(
                f'foo'
                f'bar'
            )
        ''', m.FStringMissingPlaceholders)
        # this is an "escaped placeholder" but not a placeholder
        self.flakes("f'{{}}'", m.FStringMissingPlaceholders)
        # ok: f-string with placeholders
        self.flakes('''
            x = 5
            print(f'{x}')
        ''')
        # ok: f-string with format specifiers
        self.flakes('''
            x = 'a' * 90
            print(f'{x:.8}')
        ''')
        # ok: f-string with multiple format specifiers
        self.flakes('''
            x = y = 5
            print(f'{x:>2} {y:>2}')
        ''')

    def test_invalid_dot_format_calls(self):
        self.flakes('''
            '{'.format(1)
        ''', m.StringDotFormatInvalidFormat)
        self.flakes('''
            '{} {1}'.format(1, 2)
        ''', m.StringDotFormatMixingAutomatic)
        self.flakes('''
            '{0} {}'.format(1, 2)
        ''', m.StringDotFormatMixingAutomatic)
        self.flakes('''
            '{}'.format(1, 2)
        ''', m.StringDotFormatExtraPositionalArguments)
        self.flakes('''
            '{}'.format(1, bar=2)
        ''', m.StringDotFormatExtraNamedArguments)
        self.flakes('''
            '{} {}'.format(1)
        ''', m.StringDotFormatMissingArgument)
        self.flakes('''
            '{2}'.format()
        ''', m.StringDotFormatMissingArgument)
        self.flakes('''
            '{bar}'.format()
        ''', m.StringDotFormatMissingArgument)
        # too much string recursion (placeholder-in-placeholder)
        self.flakes('''
            '{:{:{}}}'.format(1, 2, 3)
        ''', m.StringDotFormatInvalidFormat)
        # ok: dotted / bracketed names need to handle the param differently
        self.flakes("'{.__class__}'.format('')")
        self.flakes("'{foo[bar]}'.format(foo={'bar': 'barv'})")
        # ok: placeholder-placeholders
        self.flakes('''
            print('{:{}} {}'.format(1, 15, 2))
        ''')
        # ok: not a placeholder-placeholder
        self.flakes('''
            print('{:2}'.format(1))
        ''')
        # ok: not mixed automatic
        self.flakes('''
            '{foo}-{}'.format(1, foo=2)
        ''')
        # ok: we can't determine statically the format args
        self.flakes('''
            a = ()
            "{}".format(*a)
        ''')
        self.flakes('''
            k = {}
            "{foo}".format(**k)
        ''')

    def test_invalid_percent_format_calls(self):
        self.flakes('''
            '%(foo)' % {'foo': 'bar'}
        ''', m.PercentFormatInvalidFormat)
        self.flakes('''
            '%s %(foo)s' % {'foo': 'bar'}
        ''', m.PercentFormatMixedPositionalAndNamed)
        self.flakes('''
            '%(foo)s %s' % {'foo': 'bar'}
        ''', m.PercentFormatMixedPositionalAndNamed)
        self.flakes('''
            '%j' % (1,)
        ''', m.PercentFormatUnsupportedFormatCharacter)
        self.flakes('''
            '%s %s' % (1,)
        ''', m.PercentFormatPositionalCountMismatch)
        self.flakes('''
            '%s %s' % (1, 2, 3)
        ''', m.PercentFormatPositionalCountMismatch)
        self.flakes('''
            '%(bar)s' % {}
        ''', m.PercentFormatMissingArgument,)
        self.flakes('''
            '%(bar)s' % {'bar': 1, 'baz': 2}
        ''', m.PercentFormatExtraNamedArguments)
        self.flakes('''
            '%(bar)s' % (1, 2, 3)
        ''', m.PercentFormatExpectedMapping)
        self.flakes('''
            '%s %s' % {'k': 'v'}
        ''', m.PercentFormatExpectedSequence)
        self.flakes('''
            '%(bar)*s' % {'bar': 'baz'}
        ''', m.PercentFormatStarRequiresSequence)
        # ok: single %s with mapping
        self.flakes('''
            '%s' % {'foo': 'bar', 'baz': 'womp'}
        ''')
        # ok: does not cause a MemoryError (the strings aren't evaluated)
        self.flakes('''
            "%1000000000000f" % 1
        ''')
        # ok: %% should not count towards placeholder count
        self.flakes('''
            '%% %s %% %s' % (1, 2)
        ''')
        # ok: * consumes one positional argument
        self.flakes('''
            '%.*f' % (2, 1.1234)
            '%*.*f' % (5, 2, 3.1234)
        ''')

    def test_ok_percent_format_cannot_determine_element_count(self):
        self.flakes('''
            a = []
            '%s %s' % [*a]
            '%s %s' % (*a,)
        ''')
        self.flakes('''
            k = {}
            '%(k)s' % {**k}
        ''')


class TestAsyncStatements(TestCase):

    def test_asyncDef(self):
        self.flakes('''
        async def bar():
            return 42
        ''')

    def test_asyncDefAwait(self):
        self.flakes('''
        async def read_data(db):
            await db.fetch('SELECT ...')
        ''')

    def test_asyncDefUndefined(self):
        self.flakes('''
        async def bar():
            return foo()
        ''', m.UndefinedName)

    def test_asyncFor(self):
        self.flakes('''
        async def read_data(db):
            output = []
            async for row in db.cursor():
                output.append(row)
            return output
        ''')

    def test_asyncForUnderscoreLoopVar(self):
        self.flakes('''
        async def coro(it):
            async for _ in it:
                pass
        ''')

    def test_loopControlInAsyncFor(self):
        self.flakes('''
        async def read_data(db):
            output = []
            async for row in db.cursor():
                if row[0] == 'skip':
                    continue
                output.append(row)
            return output
        ''')

        self.flakes('''
        async def read_data(db):
            output = []
            async for row in db.cursor():
                if row[0] == 'stop':
                    break
                output.append(row)
            return output
        ''')

    def test_loopControlInAsyncForElse(self):
        self.flakes('''
        async def read_data(db):
            output = []
            async for row in db.cursor():
                output.append(row)
            else:
                continue
            return output
        ''', m.ContinueOutsideLoop)

        self.flakes('''
        async def read_data(db):
            output = []
            async for row in db.cursor():
                output.append(row)
            else:
                break
            return output
        ''', m.BreakOutsideLoop)

    @skipIf(version_info > (3, 8), "Python <= 3.8 only")
    def test_continueInAsyncForFinally(self):
        self.flakes('''
        async def read_data(db):
            output = []
            async for row in db.cursor():
                try:
                    output.append(row)
                finally:
                    continue
            return output
        ''', m.ContinueInFinally)

    def test_asyncWith(self):
        self.flakes('''
        async def commit(session, data):
            async with session.transaction():
                await session.update(data)
        ''')

    def test_asyncWithItem(self):
        self.flakes('''
        async def commit(session, data):
            async with session.transaction() as trans:
                await trans.begin()
                ...
                await trans.end()
        ''')

    def test_matmul(self):
        self.flakes('''
        def foo(a, b):
            return a @ b
        ''')

    def test_formatstring(self):
        self.flakes('''
        hi = 'hi'
        mom = 'mom'
        f'{hi} {mom}'
        ''')

    def test_raise_notimplemented(self):
        self.flakes('''
        raise NotImplementedError("This is fine")
        ''')

        self.flakes('''
        raise NotImplementedError
        ''')

        self.flakes('''
        raise NotImplemented("This isn't gonna work")
        ''', m.RaiseNotImplemented)

        self.flakes('''
        raise NotImplemented
        ''', m.RaiseNotImplemented)


class TestIncompatiblePrintOperator(TestCase):
    """
    Tests for warning about invalid use of print function.
    """

    def test_valid_print(self):
        self.flakes('''
        print("Hello")
        ''')

    def test_invalid_print_when_imported_from_future(self):
        exc = self.flakes('''
        from __future__ import print_function
        import sys
        print >>sys.stderr, "Hello"
        ''', m.InvalidPrintSyntax).messages[0]

        self.assertEqual(exc.lineno, 4)
        self.assertEqual(exc.col, 0)

    def test_print_function_assignment(self):
        """
        A valid assignment, tested for catching false positives.
        """
        self.flakes('''
        from __future__ import print_function
        log = print
        log("Hello")
        ''')

    def test_print_in_lambda(self):
        self.flakes('''
        from __future__ import print_function
        a = lambda: print
        ''')

    def test_print_returned_in_function(self):
        self.flakes('''
        from __future__ import print_function
        def a():
            return print
        ''')

    def test_print_as_condition_test(self):
        self.flakes('''
        from __future__ import print_function
        if print: pass
        ''')
b IDATxytVսϓ22 A@IR :hCiZ[v*E:WũZA ^dQeQ @ !jZ'>gsV仿$|?g)&x-EIENT ;@xT.i%-X}SvS5.r/UHz^_$-W"w)Ɗ/@Z &IoX P$K}JzX:;` &, ŋui,e6mX ԵrKb1ԗ)DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA݀!I*]R;I2$eZ#ORZSrr6mteffu*((Pu'v{DIߔ4^pIm'77WEEE;vƎ4-$]'RI{\I&G :IHJ DWBB=\WR޽m o$K(V9ABB.}jѢv`^?IOȅ} ڶmG}T#FJ`56$-ھ}FI&v;0(h;Б38CӧOWf!;A i:F_m9s&|q%=#wZprrrla A &P\\СC[A#! {olF} `E2}MK/vV)i{4BffV\|ۭX`b@kɶ@%i$K z5zhmX[IXZ` 'b%$r5M4º/l ԃߖxhʔ)[@=} K6IM}^5k㏷݆z ΗÿO:gdGBmyT/@+Vɶ纽z񕏵l.y޴it뭷zV0[Y^>Wsqs}\/@$(T7f.InݺiR$푔n.~?H))\ZRW'Mo~v Ov6oԃxz! S,&xm/yɞԟ?'uaSѽb,8GלKboi&3t7Y,)JJ c[nzӳdE&KsZLӄ I?@&%ӟ۶mSMMњ0iؐSZ,|J+N ~,0A0!5%Q-YQQa3}$_vVrf9f?S8`zDADADADADADADADADAdqP,تmMmg1V?rSI꒟]u|l RCyEf٢9 jURbztѰ!m5~tGj2DhG*{H9)꒟ר3:(+3\?/;TUݭʴ~S6lڧUJ*i$d(#=Yݺd{,p|3B))q:vN0Y.jkק6;SɶVzHJJЀ-utѹսk>QUU\޲~]fFnK?&ߡ5b=z9)^|u_k-[y%ZNU6 7Mi:]ۦtk[n X(e6Bb."8cۭ|~teuuw|ήI-5"~Uk;ZicEmN/:]M> cQ^uiƞ??Ңpc#TUU3UakNwA`:Y_V-8.KKfRitv޲* 9S6ֿj,ՃNOMߤ]z^fOh|<>@Å5 _/Iu?{SY4hK/2]4%it5q]GGe2%iR| W&f*^]??vq[LgE_3f}Fxu~}qd-ږFxu~I N>\;͗O֊:̗WJ@BhW=y|GgwܷH_NY?)Tdi'?խwhlmQi !SUUsw4kӺe4rfxu-[nHtMFj}H_u~w>)oV}(T'ebʒv3_[+vn@Ȭ\S}ot}w=kHFnxg S 0eޢm~l}uqZfFoZuuEg `zt~? b;t%>WTkķh[2eG8LIWx,^\thrl^Ϊ{=dž<}qV@ ⠨Wy^LF_>0UkDuʫuCs$)Iv:IK;6ֲ4{^6եm+l3>݆uM 9u?>Zc }g~qhKwڭeFMM~pМuqǿz6Tb@8@Y|jx](^]gf}M"tG -w.@vOqh~/HII`S[l.6nØXL9vUcOoB\xoǤ'T&IǍQw_wpv[kmO{w~>#=P1Pɞa-we:iǏlHo׈꒟f9SzH?+shk%Fs:qVhqY`jvO'ρ?PyX3lх]˾uV{ݞ]1,MzYNW~̈́ joYn}ȚF߾׮mS]F z+EDxm/d{F{-W-4wY듏:??_gPf ^3ecg ҵs8R2מz@TANGj)}CNi/R~}c:5{!ZHӋӾ6}T]G]7W6^n 9*,YqOZj:P?Q DFL|?-^.Ɵ7}fFh׶xe2Pscz1&5\cn[=Vn[ĶE鎀uˌd3GII k;lNmشOuuRVfBE]ۣeӶu :X-[(er4~LHi6:Ѻ@ԅrST0trk%$Č0ez" *z"T/X9|8.C5Feg}CQ%͞ˣJvL/?j^h&9xF`њZ(&yF&Iݻfg#W;3^{Wo^4'vV[[K';+mӍִ]AC@W?1^{එyh +^]fm~iԵ]AB@WTk̏t uR?l.OIHiYyԶ]Aˀ7c:q}ힽaf6Z~қm(+sK4{^6}T*UUu]n.:kx{:2 _m=sAߤU@?Z-Vކеz왍Nэ{|5 pڶn b p-@sPg]0G7fy-M{GCF'%{4`=$-Ge\ eU:m+Zt'WjO!OAF@ik&t݆ϥ_ e}=]"Wz_.͜E3leWFih|t-wZۍ-uw=6YN{6|} |*={Ѽn.S.z1zjۻTH]흾 DuDvmvK.`V]yY~sI@t?/ϓ. m&["+P?MzovVЫG3-GRR[(!!\_,^%?v@ҵő m`Y)tem8GMx.))A]Y i`ViW`?^~!S#^+ѽGZj?Vģ0.))A꨷lzL*]OXrY`DBBLOj{-MH'ii-ϰ ok7^ )쭡b]UXSְmռY|5*cֽk0B7镹%ڽP#8nȎq}mJr23_>lE5$iwui+ H~F`IjƵ@q \ @#qG0".0" l`„.0! ,AQHN6qzkKJ#o;`Xv2>,tێJJ7Z/*A .@fفjMzkg @TvZH3Zxu6Ra'%O?/dQ5xYkU]Rֽkق@DaS^RSּ5|BeHNN͘p HvcYcC5:y #`οb;z2.!kr}gUWkyZn=f Pvsn3p~;4p˚=ē~NmI] ¾ 0lH[_L hsh_ғߤc_њec)g7VIZ5yrgk̞W#IjӪv>՞y睝M8[|]\շ8M6%|@PZڨI-m>=k='aiRo-x?>Q.}`Ȏ:Wsmu u > .@,&;+!!˱tﭧDQwRW\vF\~Q7>spYw$%A~;~}6¾ g&if_=j,v+UL1(tWake:@Ș>j$Gq2t7S?vL|]u/ .(0E6Mk6hiۺzښOrifޱxm/Gx> Lal%%~{lBsR4*}{0Z/tNIɚpV^#Lf:u@k#RSu =S^ZyuR/.@n&΃z~B=0eg뺆#,Þ[B/?H uUf7y Wy}Bwegל`Wh(||`l`.;Ws?V@"c:iɍL֯PGv6zctM̠':wuW;d=;EveD}9J@B(0iհ bvP1{\P&G7D޴Iy_$-Qjm~Yrr&]CDv%bh|Yzni_ˆR;kg}nJOIIwyuL}{ЌNj}:+3Y?:WJ/N+Rzd=hb;dj͒suݔ@NKMԄ jqzC5@y°hL m;*5ezᕏ=ep XL n?מ:r`۵tŤZ|1v`V뽧_csج'ߤ%oTuumk%%%h)uy]Nk[n 'b2 l.=͜E%gf$[c;s:V-͞WߤWh-j7]4=F-X]>ZLSi[Y*We;Zan(ӇW|e(HNNP5[= r4tP &0<pc#`vTNV GFqvTi*Tyam$ߏWyE*VJKMTfFw>'$-ؽ.Ho.8c"@DADADADADADADADADA~j*֘,N;Pi3599h=goضLgiJ5փy~}&Zd9p֚ e:|hL``b/d9p? fgg+%%hMgXosج, ΩOl0Zh=xdjLmhݻoO[g_l,8a]٭+ӧ0$I]c]:粹:Teꢢ"5a^Kgh,&= =՟^߶“ߢE ܹS J}I%:8 IDAT~,9/ʃPW'Mo}zNƍ쨓zPbNZ~^z=4mswg;5 Y~SVMRXUյڱRf?s:w ;6H:ºi5-maM&O3;1IKeamZh͛7+##v+c ~u~ca]GnF'ټL~PPPbn voC4R,ӟgg %hq}@#M4IÇ Oy^xMZx ) yOw@HkN˖-Sǎmb]X@n+i͖!++K3gd\$mt$^YfJ\8PRF)77Wא!Cl$i:@@_oG I{$# 8磌ŋ91A (Im7֭>}ߴJq7ޗt^ -[ԩSj*}%]&' -ɓ'ꫯVzzvB#;a 7@GxI{j޼ƌ.LÇWBB7`O"I$/@R @eee@۷>}0,ɒ2$53Xs|cS~rpTYYY} kHc %&k.], @ADADADADADADADADA@lT<%''*Lo^={رc5h %$+CnܸQ3fҥK}vUVVs9G R,_{xˇ3o߾;TTTd}馛]uuuG~iԩ@4bnvmvfϞ /Peeeq}}za I~,誫{UWW뮻}_~YƍSMMMYχ֝waw\ďcxꩧtEƍկ_?۷5@u?1kNׯWzz/wy>}zj3 k(ٺuq_Zvf̘:~ ABQ&r|!%KҥKgԞ={<_X-z !CyFUUz~ ABQIIIjݺW$UXXDٳZ~ ABQƍecW$<(~<RSSvZujjjԧOZQu@4 8m&&&jԩg$ď1h ͟?_{768@g =@`)))5o6m3)ѣƌJ;wҿUTT /KZR{~a=@0o<*狔iFɶ[ˎ;T]]OX@?K.ۈxN pppppppppppppppppPfl߾] ,{ァk۶mڿo5BTӦMӴiӴ|r DB2e|An!Dy'tkΝ[A $***t5' "!駟oaDnΝ:t֭[gDШQ06qD;@ x M6v(PiizmZ4ew"@̴ixf [~-Fٱc&IZ2|n!?$@{[HTɏ#@hȎI# _m(F /6Z3z'\r,r!;w2Z3j=~GY7"I$iI.p_"?pN`y DD?: _  Gÿab7J !Bx@0 Bo cG@`1C[@0G @`0C_u V1 aCX>W ` | `!<S `"<. `#c`?cAC4 ?c p#~@0?:08&_MQ1J h#?/`7;I  q 7a wQ A 1 Hp !#<8/#@1Ul7=S=K.4Z?E_$i@!1!E4?`P_  @Bă10#: "aU,xbFY1 [n|n #'vEH:`xb #vD4Y hi.i&EΖv#O H4IŶ}:Ikh @tZRF#(tXҙzZ ?I3l7q@õ|ۍ1,GpuY Ꮿ@hJv#xxk$ v#9 5 }_$c S#=+"K{F*m7`#%H:NRSp6I?sIՖ{Ap$I$I:QRv2$Z @UJ*$]<FO4IENDB`