d6e9fd358013

vim: add pyflakes
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Fri, 21 May 2010 14:59:02 -0400
parents feaa7c9c1eff
children da49bac8587e
branches/tags (none)
files vim/.vimrc vim/ftplugin/python/README.rst vim/ftplugin/python/pyflakes.vim vim/ftplugin/python/pyflakes/LICENSE vim/ftplugin/python/pyflakes/README.rst vim/ftplugin/python/pyflakes/TODO vim/ftplugin/python/pyflakes/bin/pyflakes vim/ftplugin/python/pyflakes/pyflakes/__init__.py vim/ftplugin/python/pyflakes/pyflakes/ast.py vim/ftplugin/python/pyflakes/pyflakes/checker.py vim/ftplugin/python/pyflakes/pyflakes/messages.py vim/ftplugin/python/pyflakes/pyflakes/scripts/__init__.py vim/ftplugin/python/pyflakes/pyflakes/scripts/pyflakes.py vim/ftplugin/python/pyflakes/pyflakes/test/__init__.py vim/ftplugin/python/pyflakes/pyflakes/test/harness.py vim/ftplugin/python/pyflakes/pyflakes/test/test_imports.py vim/ftplugin/python/pyflakes/pyflakes/test/test_other.py vim/ftplugin/python/pyflakes/pyflakes/test/test_script.py vim/ftplugin/python/pyflakes/pyflakes/test/test_undefined_names.py vim/ftplugin/python/pyflakes/setup.py

Changes

--- a/vim/.vimrc	Thu May 20 17:58:29 2010 -0400
+++ b/vim/.vimrc	Fri May 21 14:59:02 2010 -0400
@@ -118,3 +118,9 @@
 
 " Ack
 map <leader>a :Ack 
+
+" Spellbad Coloring
+if has("gui_running")
+    highlight SpellBad term=underline gui=undercurl guisp=Orange
+endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/README.rst	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,70 @@
+pyflakes-vim
+============
+
+A Vim plugin for checking Python code on the fly.
+
+PyFlakes catches common Python errors like mistyping a variable name or
+accessing a local before it is bound, and also gives warnings for things like
+unused imports.
+
+pyflakes-vim uses the output from PyFlakes to highlight errors in your code.
+
+Make sure to check vim.org_ for the latest updates.
+
+.. _pyflakes.vim: http://www.vim.org/scripts/script.php?script_id=2441
+.. _vim.org: http://www.vim.org/scripts/script.php?script_id=2441
+
+Quick Installation
+------------------
+
+1. Make sure your ``.vimrc`` has::
+ 
+    filetype on            " enables filetype detection
+    filetype plugin on     " enables filetype specific plugins
+
+2. Download the latest release_.
+
+3. Unzip ``pyflakes.vim`` and the ``pyflakes`` directory into
+   ``~/.vim/ftplugin/python`` (or somewhere similar on your
+   `runtime path`_ that will be sourced for Python files).
+
+.. _release: http://www.vim.org/scripts/script.php?script_id=2441
+.. _runtime path: http://vimdoc.sourceforge.net/htmldoc/options.html#'runtimepath' 
+
+Installation
+------------
+
+If you downloaded this from vim.org_, then just drop the contents of the zip
+file into ``~/.vim/ftplugin/python``.
+
+Otherwise, you'll need PyFlakes on your PYTHONPATH somewhere.  I recommend
+getting my PyFlakes_ fork, which uses the ``_ast`` module new to Python 2.5,
+and is faster and more current than PyFlakes' old usage of the deprecated
+``compiler`` module.
+
+.. _vim.org: http://www.vim.org/scripts/script.php?script_id=2441
+.. _PyFlakes: http://github.com/kevinw/pyflakes
+
+Hacking
+-------
+
+::
+
+  git clone git://github.com/kevinw/pyflakes-vim.git
+  cd pyflakes-vim
+  git clone git://github.com/kevinw/pyflakes.git
+
+TODO
+----
+ * signs_ support (show warning and error icons to left of the buffer area)
+ * configuration variables
+ * parse or intercept useful output from the warnings module
+
+.. _signs: http://www.vim.org/htmldoc/sign.html
+
+Changelog
+---------
+
+Please see http://www.vim.org/scripts/script.php?script_id=2441 for a history of
+all changes.
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes.vim	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,226 @@
+" pyflakes.vim - A script to highlight Python code on the fly with warnings
+" from Pyflakes, a Python lint tool.
+"
+" Place this script and the accompanying pyflakes directory in
+" .vim/ftplugin/python.
+"
+" See README for additional installation and information.
+"
+" Thanks to matlib.vim for ideas/code on interactive linting.
+"
+" Maintainer: Kevin Watters <kevin.watters@gmail.com>
+" Version: 0.1
+
+if exists("b:did_pyflakes_plugin")
+    finish " only load once
+else
+    let b:did_pyflakes_plugin = 1
+endif
+
+if !exists('g:pyflakes_builtins')
+    let g:pyflakes_builtins = []
+endif
+
+if !exists("b:did_python_init")
+    let b:did_python_init = 0
+
+    if !has('python')
+        echoerr "Error: the pyflakes.vim plugin requires Vim to be compiled with +python"
+        finish
+    endif
+
+    python << EOF
+import vim
+import os.path
+import sys
+
+if sys.version_info[:2] < (2, 5):
+    raise AssertionError('Vim must be compiled with Python 2.5 or higher; you have ' + sys.version)
+
+# get the directory this script is in: the pyflakes python module should be installed there.
+scriptdir = os.path.join(os.path.dirname(vim.eval('expand("<sfile>")')), 'pyflakes')
+sys.path.insert(0, scriptdir)
+
+from pyflakes import checker, ast, messages
+from operator import attrgetter
+
+class SyntaxError(messages.Message):
+    message = 'could not compile: %s'
+    def __init__(self, filename, lineno, col, message):
+        messages.Message.__init__(self, filename, lineno, col)
+        self.message_args = (message,)
+
+class blackhole(object):
+    write = flush = lambda *a, **k: None
+
+def check(buffer):
+    filename = buffer.name
+    contents = '\n'.join(buffer[:]) + '\n'
+
+    vimenc = vim.eval('&encoding')
+    if vimenc:
+        contents = contents.decode(vimenc)
+
+    builtins = []
+    try:
+        builtins = eval(vim.eval('string(g:pyflakes_builtins)'))
+    except Exception:
+        pass
+
+    try:
+        # TODO: use warnings filters instead of ignoring stderr
+        old_stderr, sys.stderr = sys.stderr, blackhole()
+        try:
+            tree = ast.parse(contents, filename)
+        finally:
+            sys.stderr = old_stderr
+    except:
+        try:
+            value = sys.exc_info()[1]
+            lineno, offset, line = value[1][1:]
+        except IndexError:
+            lineno, offset, line = 1, 0, ''
+        if line and line.endswith("\n"):
+            line = line[:-1]
+
+        return [SyntaxError(filename, lineno, offset, str(value))]
+    else:
+        w = checker.Checker(tree, filename, builtins = builtins)
+        w.messages.sort(key = attrgetter('lineno'))
+        return w.messages
+
+
+def vim_quote(s):
+    return s.replace("'", "''")
+EOF
+    let b:did_python_init = 1
+endif
+
+if !b:did_python_init
+    finish
+endif
+
+au BufLeave <buffer> call s:ClearPyflakes()
+
+au BufEnter <buffer> call s:RunPyflakes()
+au InsertLeave <buffer> call s:RunPyflakes()
+au InsertEnter <buffer> call s:RunPyflakes()
+au BufWritePost <buffer> call s:RunPyflakes()
+
+au CursorHold <buffer> call s:RunPyflakes()
+au CursorHoldI <buffer> call s:RunPyflakes()
+
+au CursorHold <buffer> call s:GetPyflakesMessage()
+au CursorMoved <buffer> call s:GetPyflakesMessage()
+
+if !exists("*s:PyflakesUpdate")
+    function s:PyflakesUpdate()
+        silent call s:RunPyflakes()
+        call s:GetPyflakesMessage()
+    endfunction
+endif
+
+" Call this function in your .vimrc to update PyFlakes
+if !exists(":PyflakesUpdate")
+  command PyflakesUpdate :call s:PyflakesUpdate()
+endif
+
+" Hook common text manipulation commands to update PyFlakes
+"   TODO: is there a more general "text op" autocommand we could register
+"   for here?
+noremap <buffer><silent> dd dd:PyflakesUpdate<CR>
+noremap <buffer><silent> dw dw:PyflakesUpdate<CR>
+noremap <buffer><silent> u u:PyflakesUpdate<CR>
+noremap <buffer><silent> <C-R> <C-R>:PyflakesUpdate<CR>
+
+" WideMsg() prints [long] message up to (&columns-1) length
+" guaranteed without "Press Enter" prompt.
+if !exists("*s:WideMsg")
+    function s:WideMsg(msg)
+        let x=&ruler | let y=&showcmd
+        set noruler noshowcmd
+        redraw
+        echo a:msg
+        let &ruler=x | let &showcmd=y
+    endfun
+endif
+
+if !exists("*s:RunPyflakes")
+    function s:RunPyflakes()
+        highlight link PyFlakes SpellBad
+
+        if exists("b:cleared")
+            if b:cleared == 0
+                silent call s:ClearPyflakes()
+                let b:cleared = 1
+            endif
+        else
+            let b:cleared = 1
+        endif
+        
+        let b:matched = []
+        let b:matchedlines = {}
+        python << EOF
+for w in check(vim.current.buffer):
+    vim.command('let s:matchDict = {}')
+    vim.command("let s:matchDict['lineNum'] = " + str(w.lineno))
+    vim.command("let s:matchDict['message'] = '%s'" % vim_quote(w.message % w.message_args))
+    vim.command("let b:matchedlines[" + str(w.lineno) + "] = s:matchDict")
+
+    if w.col is None or isinstance(w, SyntaxError):
+        # without column information, just highlight the whole line
+        # (minus the newline)
+        vim.command(r"let s:mID = matchadd('PyFlakes', '\%" + str(w.lineno) + r"l\n\@!')")
+    else:
+        # with a column number, highlight the first keyword there
+        vim.command(r"let s:mID = matchadd('PyFlakes', '^\%" + str(w.lineno) + r"l\_.\{-}\zs\k\+\k\@!\%>" + str(w.col) + r"c')")
+
+    vim.command("call add(b:matched, s:matchDict)")
+EOF
+        let b:cleared = 0
+    endfunction
+end
+
+" keep track of whether or not we are showing a message
+let b:showing_message = 0
+
+if !exists("*s:GetPyflakesMessage")
+    function s:GetPyflakesMessage()
+        let s:cursorPos = getpos(".")
+
+        " Bail if RunPyflakes hasn't been called yet.
+        if !exists('b:matchedlines')
+            return
+        endif
+
+        " if there's a message for the line the cursor is currently on, echo
+        " it to the console
+        if has_key(b:matchedlines, s:cursorPos[1])
+            let s:pyflakesMatch = get(b:matchedlines, s:cursorPos[1])
+            call s:WideMsg(s:pyflakesMatch['message'])
+            let b:showing_message = 1
+            return
+        endif
+
+        " otherwise, if we're showing a message, clear it
+        if b:showing_message == 1
+            echo
+            let b:showing_message = 0
+        endif
+    endfunction
+endif
+
+if !exists('*s:ClearPyflakes')
+    function s:ClearPyflakes()
+        let s:matches = getmatches()
+        for s:matchId in s:matches
+            if s:matchId['group'] == 'PyFlakes'
+                call matchdelete(s:matchId['id'])
+            endif
+        endfor
+        let b:matched = []
+        let b:matchedlines = {}
+        let b:cleared = 1
+    endfunction
+endif
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/LICENSE	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,21 @@
+
+Copyright (c) 2005 Divmod, Inc., http://www.divmod.com/
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be
+included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/README.rst	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,36 @@
+pyflakes
+========
+
+This version of PyFlakes_ has been improved to use Python's newer ``ast``
+module, instead of ``compiler``. So code checking happens faster, and will stay
+up to date with new language changes.
+
+.. _PyFlakes: http://http://www.divmod.org/trac/wiki/DivmodPyflakes
+
+TODO
+----
+
+Importing several modules from the same package results in unnecessary warnings:
+
+::
+
+    import a.b
+    import a.c # Redefinition of unused "a" from line 1
+
+The following construct for defining a function differently depending on some
+condition results in a redefinition warning:
+
+::
+
+    if some_condition:
+        def foo(): do_foo()
+    else:
+        def foo(): do_bar() # redefinition of function 'foo' from line 2
+
+IDE Integration
+---------------
+
+* vim: pyflakes-vim_
+
+.. _pyflakes-vim: http://github.com/kevinw/pyflakes-vim
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/TODO	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,11 @@
+ - Check for methods that override other methods except that they vary by case.
+ - assign/increment + unbound local error not caught
+        def foo():
+          bar = 5
+          def meep():
+            bar += 2
+          meep()
+          print bar
+
+        print foo()
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/bin/pyflakes	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,4 @@
+#!/usr/bin/python
+
+from pyflakes.scripts.pyflakes import main
+main()
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/ast.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,311 @@
+# -*- coding: utf-8 -*-
+"""
+    ast
+    ~~~
+
+    The `ast` module helps Python applications to process trees of the Python
+    abstract syntax grammar.  The abstract syntax itself might change with
+    each Python release; this module helps to find out programmatically what
+    the current grammar looks like and allows modifications of it.
+
+    An abstract syntax tree can be generated by passing `ast.PyCF_ONLY_AST` as
+    a flag to the `compile()` builtin function or by using the `parse()`
+    function from this module.  The result will be a tree of objects whose
+    classes all inherit from `ast.AST`.
+
+    A modified abstract syntax tree can be compiled into a Python code object
+    using the built-in `compile()` function.
+
+    Additionally various helper functions are provided that make working with
+    the trees simpler.  The main intention of the helper functions and this
+    module in general is to provide an easy to use interface for libraries
+    that work tightly with the python syntax (template engines for example).
+
+
+    :copyright: Copyright 2008 by Armin Ronacher.
+    :license: Python License.
+"""
+from _ast import *
+from _ast import __version__
+
+
+def parse(expr, filename='<unknown>', mode='exec'):
+    """
+    Parse an expression into an AST node.
+    Equivalent to compile(expr, filename, mode, PyCF_ONLY_AST).
+    """
+    return compile(expr, filename, mode, PyCF_ONLY_AST)
+
+
+def literal_eval(node_or_string):
+    """
+    Safely evaluate an expression node or a string containing a Python
+    expression.  The string or node provided may only consist of the following
+    Python literal structures: strings, numbers, tuples, lists, dicts, booleans,
+    and None.
+    """
+    _safe_names = {'None': None, 'True': True, 'False': False}
+    if isinstance(node_or_string, basestring):
+        node_or_string = parse(node_or_string, mode='eval')
+    if isinstance(node_or_string, Expression):
+        node_or_string = node_or_string.body
+    def _convert(node):
+        if isinstance(node, Str):
+            return node.s
+        elif isinstance(node, Num):
+            return node.n
+        elif isinstance(node, Tuple):
+            return tuple(map(_convert, node.elts))
+        elif isinstance(node, List):
+            return list(map(_convert, node.elts))
+        elif isinstance(node, Dict):
+            return dict((_convert(k), _convert(v)) for k, v
+                        in zip(node.keys, node.values))
+        elif isinstance(node, Name):
+            if node.id in _safe_names:
+                return _safe_names[node.id]
+        raise ValueError('malformed string')
+    return _convert(node_or_string)
+
+
+def dump(node, annotate_fields=True, include_attributes=False):
+    """
+    Return a formatted dump of the tree in *node*.  This is mainly useful for
+    debugging purposes.  The returned string will show the names and the values
+    for fields.  This makes the code impossible to evaluate, so if evaluation is
+    wanted *annotate_fields* must be set to False.  Attributes such as line
+    numbers and column offsets are not dumped by default.  If this is wanted,
+    *include_attributes* can be set to True.
+    """
+    def _format(node):
+        if isinstance(node, AST):
+            fields = [(a, _format(b)) for a, b in iter_fields(node)]
+            rv = '%s(%s' % (node.__class__.__name__, ', '.join(
+                ('%s=%s' % field for field in fields)
+                if annotate_fields else
+                (b for a, b in fields)
+            ))
+            if include_attributes and node._attributes:
+                rv += fields and ', ' or ' '
+                rv += ', '.join('%s=%s' % (a, _format(getattr(node, a)))
+                                for a in node._attributes)
+            return rv + ')'
+        elif isinstance(node, list):
+            return '[%s]' % ', '.join(_format(x) for x in node)
+        return repr(node)
+    if not isinstance(node, AST):
+        raise TypeError('expected AST, got %r' % node.__class__.__name__)
+    return _format(node)
+
+
+def copy_location(new_node, old_node):
+    """
+    Copy source location (`lineno` and `col_offset` attributes) from
+    *old_node* to *new_node* if possible, and return *new_node*.
+    """
+    for attr in 'lineno', 'col_offset':
+        if attr in old_node._attributes and attr in new_node._attributes \
+           and hasattr(old_node, attr):
+            setattr(new_node, attr, getattr(old_node, attr))
+    return new_node
+
+
+def fix_missing_locations(node):
+    """
+    When you compile a node tree with compile(), the compiler expects lineno and
+    col_offset attributes for every node that supports them.  This is rather
+    tedious to fill in for generated nodes, so this helper adds these attributes
+    recursively where not already set, by setting them to the values of the
+    parent node.  It works recursively starting at *node*.
+    """
+    def _fix(node, lineno, col_offset):
+        if 'lineno' in node._attributes:
+            if not hasattr(node, 'lineno'):
+                node.lineno = lineno
+            else:
+                lineno = node.lineno
+        if 'col_offset' in node._attributes:
+            if not hasattr(node, 'col_offset'):
+                node.col_offset = col_offset
+            else:
+                col_offset = node.col_offset
+        for child in iter_child_nodes(node):
+            _fix(child, lineno, col_offset)
+    _fix(node, 1, 0)
+    return node
+
+def add_col_end(node):
+    def _fix(node, next):
+        children = list(iter_child_nodes(node))
+        for i, child in enumerate(children):
+            next_offset = children[i+1].col_offset if i < len(children) else next.col_offset
+            child.col_end = next_offset
+
+
+def increment_lineno(node, n=1):
+    """
+    Increment the line number of each node in the tree starting at *node* by *n*.
+    This is useful to "move code" to a different location in a file.
+    """
+    if 'lineno' in node._attributes:
+        node.lineno = getattr(node, 'lineno', 0) + n
+    for child in walk(node):
+        if 'lineno' in child._attributes:
+            child.lineno = getattr(child, 'lineno', 0) + n
+    return node
+
+
+def iter_fields(node):
+    """
+    Yield a tuple of ``(fieldname, value)`` for each field in ``node._fields``
+    that is present on *node*.
+    """
+    if node._fields is None:
+        return
+
+    for field in node._fields:
+        try:
+            yield field, getattr(node, field)
+        except AttributeError:
+            pass
+
+
+def iter_child_nodes(node):
+    """
+    Yield all direct child nodes of *node*, that is, all fields that are nodes
+    and all items of fields that are lists of nodes.
+    """
+    for name, field in iter_fields(node):
+        if isinstance(field, AST):
+            yield field
+        elif isinstance(field, list):
+            for item in field:
+                if isinstance(item, AST):
+                    yield item
+
+
+def get_docstring(node, clean=True):
+    """
+    Return the docstring for the given node or None if no docstring can
+    be found.  If the node provided does not have docstrings a TypeError
+    will be raised.
+    """
+    if not isinstance(node, (FunctionDef, ClassDef, Module)):
+        raise TypeError("%r can't have docstrings" % node.__class__.__name__)
+    if node.body and isinstance(node.body[0], Expr) and \
+       isinstance(node.body[0].value, Str):
+        if clean:
+            import inspect
+            return inspect.cleandoc(node.body[0].value.s)
+        return node.body[0].value.s
+
+
+def walk(node):
+    """
+    Recursively yield all child nodes of *node*, in no specified order.  This is
+    useful if you only want to modify nodes in place and don't care about the
+    context.
+    """
+    from collections import deque
+    todo = deque([node])
+    while todo:
+        node = todo.popleft()
+        todo.extend(iter_child_nodes(node))
+        yield node
+
+
+class NodeVisitor(object):
+    """
+    A node visitor base class that walks the abstract syntax tree and calls a
+    visitor function for every node found.  This function may return a value
+    which is forwarded by the `visit` method.
+
+    This class is meant to be subclassed, with the subclass adding visitor
+    methods.
+
+    Per default the visitor functions for the nodes are ``'visit_'`` +
+    class name of the node.  So a `TryFinally` node visit function would
+    be `visit_TryFinally`.  This behavior can be changed by overriding
+    the `visit` method.  If no visitor function exists for a node
+    (return value `None`) the `generic_visit` visitor is used instead.
+
+    Don't use the `NodeVisitor` if you want to apply changes to nodes during
+    traversing.  For this a special visitor exists (`NodeTransformer`) that
+    allows modifications.
+    """
+
+    def visit(self, node):
+        """Visit a node."""
+        method = 'visit_' + node.__class__.__name__
+        visitor = getattr(self, method, self.generic_visit)
+        return visitor(node)
+
+    def generic_visit(self, node):
+        """Called if no explicit visitor function exists for a node."""
+        for field, value in iter_fields(node):
+            if isinstance(value, list):
+                for item in value:
+                    if isinstance(item, AST):
+                        self.visit(item)
+            elif isinstance(value, AST):
+                self.visit(value)
+
+
+class NodeTransformer(NodeVisitor):
+    """
+    A :class:`NodeVisitor` subclass that walks the abstract syntax tree and
+    allows modification of nodes.
+
+    The `NodeTransformer` will walk the AST and use the return value of the
+    visitor methods to replace or remove the old node.  If the return value of
+    the visitor method is ``None``, the node will be removed from its location,
+    otherwise it is replaced with the return value.  The return value may be the
+    original node in which case no replacement takes place.
+
+    Here is an example transformer that rewrites all occurrences of name lookups
+    (``foo``) to ``data['foo']``::
+
+       class RewriteName(NodeTransformer):
+
+           def visit_Name(self, node):
+               return copy_location(Subscript(
+                   value=Name(id='data', ctx=Load()),
+                   slice=Index(value=Str(s=node.id)),
+                   ctx=node.ctx
+               ), node)
+
+    Keep in mind that if the node you're operating on has child nodes you must
+    either transform the child nodes yourself or call the :meth:`generic_visit`
+    method for the node first.
+
+    For nodes that were part of a collection of statements (that applies to all
+    statement nodes), the visitor may also return a list of nodes rather than
+    just a single node.
+
+    Usually you use the transformer like this::
+
+       node = YourTransformer().visit(node)
+    """
+
+    def generic_visit(self, node):
+        for field, old_value in iter_fields(node):
+            old_value = getattr(node, field, None)
+            if isinstance(old_value, list):
+                new_values = []
+                for value in old_value:
+                    if isinstance(value, AST):
+                        value = self.visit(value)
+                        if value is None:
+                            continue
+                        elif not isinstance(value, AST):
+                            new_values.extend(value)
+                            continue
+                    new_values.append(value)
+                old_value[:] = new_values
+            elif isinstance(old_value, AST):
+                new_node = self.visit(old_value)
+                if new_node is None:
+                    delattr(node, field)
+                else:
+                    setattr(node, field, new_node)
+        return node
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/checker.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,389 @@
+import ast
+from pyflakes import messages
+import __builtin__
+
+
+allowed_before_future = (ast.Module, ast.ImportFrom, ast.Expr, ast.Str)
+defined_names = set(('__file__', '__builtins__'))
+
+class Binding(object):
+    """
+    @ivar used: pair of (L{Scope}, line-number) indicating the scope and
+                line number that this binding was last used
+    """
+    def __init__(self, name, source):
+        self.name = name
+        self.source = source
+        self.used = False
+
+    def __str__(self):
+        return self.name
+
+    def __repr__(self):
+        return '<%s object %r from line %r at 0x%x>' % (self.__class__.__name__,
+                                                        self.name,
+                                                        self.source.lineno,
+                                                        id(self))
+
+class UnBinding(Binding):
+    '''Created by the 'del' operator.'''
+
+class Importation(Binding):
+    def __init__(self, name, source):
+        name = name.split('.')[0]
+        super(Importation, self).__init__(name, source)
+
+class Assignment(Binding):
+    pass
+
+class FunctionDefinition(Binding):
+    pass
+
+
+class Scope(dict):
+    import_starred = False       # set to True when import * is found
+
+    def __repr__(self):
+        return '<%s at 0x%x %s>' % (self.__class__.__name__, id(self), dict.__repr__(self))
+
+    def __init__(self):
+        super(Scope, self).__init__()
+
+class ClassScope(Scope):
+    pass
+
+
+
+class FunctionScope(Scope):
+    """
+    I represent a name scope for a function.
+
+    @ivar globals: Names declared 'global' in this function.
+    """
+    def __init__(self):
+        super(FunctionScope, self).__init__()
+        self.globals = {}
+
+
+
+class ModuleScope(Scope):
+    pass
+
+class Checker(ast.NodeVisitor):
+    def __init__(self, tree, filename='(none)', builtins = None):
+        ast.NodeVisitor.__init__(self)
+
+        self.deferred = []
+        self.dead_scopes = []
+        self.messages = []
+        self.filename = filename
+        self.scope_stack = [ModuleScope()]
+        self.futures_allowed = True
+        self.builtins = frozenset(builtins or [])
+
+        self.visit(tree)
+        for handler, scope in self.deferred:
+            self.scope_stack = scope
+            handler()
+        del self.scope_stack[1:]
+        self.pop_scope()
+        self.check_dead_scopes()
+
+    def defer(self, callable):
+        '''Schedule something to be called after just before completion.
+
+        This is used for handling function bodies, which must be deferred
+        because code later in the file might modify the global scope. When
+        `callable` is called, the scope at the time this is called will be
+        restored, however it will contain any new bindings added to it.
+        '''
+        self.deferred.append( (callable, self.scope_stack[:]) )
+
+    def check_dead_scopes(self):
+        # Check for modules that were imported but unused
+        for scope in self.dead_scopes:
+            for importation in scope.itervalues():
+                if isinstance(importation, Importation) and not importation.used:
+                    self.report(messages.UnusedImport, importation.source.lineno, importation.name)
+
+    def push_function_scope(self):
+        self.scope_stack.append(FunctionScope())
+
+    def push_class_scope(self):
+        self.scope_stack.append(ClassScope())
+
+    def pop_scope(self):
+        scope = self.scope_stack.pop()
+        self.dead_scopes.append(scope)
+
+    @property
+    def scope(self):
+        return self.scope_stack[-1]
+
+    def report(self, message_class, *args, **kwargs):
+        self.messages.append(message_class(self.filename, *args, **kwargs))
+
+    def visit_Import(self, node):
+        for name_node in node.names:
+            # "import bar as foo" -> name=bar, asname=foo
+            name = name_node.asname or name_node.name
+            self.add_binding(node, Importation(name, node))
+
+    def visit_GeneratorExp(self, node):
+        for generator in node.generators:
+            self.visit(generator.iter)
+            self.assign_vars(generator.target)
+
+        for generator in node.generators:
+            if hasattr(node, 'elt'):
+                self.visit(node.elt)
+
+            self.visit_nodes(generator.ifs)
+
+    visit_ListComp = visit_GeneratorExp
+
+    def visit_For(self, node):
+        '''
+        Process bindings for loop variables.
+        '''
+        self.visit_nodes(node.iter)
+
+        for var in self.flatten(node.target):
+            upval = self.scope.get(var.id)
+            if isinstance(upval, Importation) and upval.used:
+                self.report(messages.ImportShadowedByLoopVar,
+                            node.lineno, node.col_offset, var.id, upval.source.lineno)
+
+            self.add_binding(var, Assignment(var.id, var))
+
+        self.visit_nodes(node.body + node.orelse)
+
+    def visit_FunctionDef(self, node):
+
+        try:
+            decorators = node.decorator_list
+        except AttributeError:
+            # Use .decorators for Python 2.5 compatibility
+            decorators = node.decorators
+
+        self.visit_nodes(decorators)
+        self.add_binding(node, FunctionDefinition(node.name, node))
+        self.visit_Lambda(node)
+
+    def visit_Lambda(self, node):
+        self.visit_nodes(node.args.defaults)
+
+        def run_function():
+            self.push_function_scope()
+
+            # Check for duplicate arguments
+            argnames = set()
+            for arg in self.flatten(node.args.args):
+                if arg.id in argnames:
+                    self.report(messages.DuplicateArgument, arg.lineno, arg.col_offset, arg.id)
+                argnames.add(arg.id)
+
+            self.assign_vars(node.args.args, report_redef=False)
+            if node.args.vararg is not None:
+                self.add_binding(node, Assignment(node.args.vararg, node), False)
+            if node.args.kwarg is not None:
+                self.add_binding(node, Assignment(node.args.kwarg, node), False)
+            self.visit_nodes(node.body)
+            self.pop_scope()
+
+        self.defer(run_function)
+
+    def visit_Name(self, node):
+        '''
+        Locate names in locals / function / globals scopes.
+        '''
+        scope, name = self.scope, node.id
+
+        # try local scope
+        import_starred = scope.import_starred
+        try:
+            scope[name].used = (scope, node.lineno, node.col_offset)
+        except KeyError:
+            pass
+        else:
+            return
+
+        # try enclosing function scopes
+        for func_scope in self.scope_stack[-2:0:-1]:
+            import_starred = import_starred or func_scope.import_starred
+            if not isinstance(func_scope, FunctionScope):
+                continue
+            try:
+                func_scope[name].used = (scope, node.lineno, node.col_offset)
+            except KeyError:
+                pass
+            else:
+                return
+
+        # try global scope
+        import_starred = import_starred or self.scope_stack[0].import_starred
+        try:
+            self.scope_stack[0][node.id].used = (scope, node.lineno, node.col_offset)
+        except KeyError:
+            if not import_starred and not self.is_builtin(name):
+                self.report(messages.UndefinedName, node.lineno, node.col_offset, name)
+
+    def assign_vars(self, targets, report_redef=True):
+        scope = self.scope
+
+        for target in self.flatten(targets):
+            name = target.id
+            # if the name hasn't already been defined in the current scope
+            if isinstance(scope, FunctionScope) and name not in scope:
+                # for each function or module scope above us
+                for upscope in self.scope_stack[:-1]:
+                    if not isinstance(upscope, (FunctionScope, ModuleScope)):
+                        continue
+
+                    upval = upscope.get(name)
+                    # if the name was defined in that scope, and the name has
+                    # been accessed already in the current scope, and hasn't
+                    # been declared global
+                    if upval is not None:
+                        if upval.used and upval.used[0] is scope and name not in scope.globals:
+                            # then it's probably a mistake
+                            self.report(messages.UndefinedLocal,
+                                        upval.used[1], upval.used[2], name, upval.source.lineno, upval.source.col_offset)
+
+            self.add_binding(target, Assignment(name, target), report_redef)
+
+    def visit_Assign(self, node):
+        for target in node.targets:
+            self.visit_nodes(node.value)
+            self.assign_vars(node.targets)
+
+    def visit_Delete(self, node):
+        for target in self.flatten(node.targets):
+            if isinstance(self.scope, FunctionScope) and target.id in self.scope.globals:
+                del self.scope.globals[target.id]
+            else:
+                self.add_binding(target, UnBinding(target.id, target))
+
+    def visit_With(self, node):
+        self.visit(node.context_expr)
+
+        # handle new bindings made by optional "as" part
+        if node.optional_vars is not None:
+            self.assign_vars(node.optional_vars)
+
+        self.visit_nodes(node.body)
+
+    def visit_ImportFrom(self, node):
+        if node.module == '__future__':
+            if not self.futures_allowed:
+                self.report(messages.LateFutureImport, node.lineno, node.col_offset, [alias.name for alias in node.names])
+        else:
+            self.futures_allowed = False
+
+        for alias in node.names:
+            if alias.name == '*':
+                self.scope.import_starred = True
+                self.report(messages.ImportStarUsed, node.lineno, node.col_offset, node.module)
+                continue
+            name = alias.asname or alias.name
+            importation = Importation(name, node)
+            if node.module == '__future__':
+                importation.used = (self.scope, node.lineno, node.col_offset)
+            self.add_binding(node, importation)
+
+    def visit_Global(self, node):
+        '''
+        Keep track of global declarations.
+        '''
+        scope = self.scope
+        if isinstance(scope, FunctionScope):
+            scope.globals.update(dict.fromkeys(node.names))
+
+    def visit_ClassDef(self, node):
+        self.add_binding(node, Assignment(node.name, node))
+        self.visit_nodes(node.bases)
+
+        self.push_class_scope()
+        self.visit_nodes(node.body)
+        self.pop_scope()
+
+    def visit_excepthandler(self, node):
+        if node.type is not None:
+            self.visit(node.type)
+        if node.name is not None:
+            self.assign_vars(node.name)
+        self.visit_nodes(node.body)
+
+    visit_ExceptHandler = visit_excepthandler # in 2.6, this was CamelCased
+
+    def flatten(self, nodes):
+        if isinstance(nodes, ast.Attribute):
+            self.visit(nodes)
+            return []
+        elif isinstance(nodes, ast.Subscript):
+            self.visit(nodes.value)
+            self.visit(nodes.slice)
+            return []
+        elif isinstance(nodes, ast.Name):
+            return [nodes]
+        elif isinstance(nodes, (ast.Tuple, ast.List)):
+            return self.flatten(nodes.elts)
+
+        flattened_nodes = []
+        for node in nodes:
+            if hasattr(node, 'elts'):
+                flattened_nodes += self.flatten(node.elts)
+            elif node is not None:
+                flattened_nodes += self.flatten(node)
+
+        return flattened_nodes
+
+    def add_binding(self, node, value, report_redef=True):
+        line, col, scope, name = node.lineno, node.col_offset, self.scope, value.name
+
+        # Check for a redefined function
+        func = scope.get(name)
+        if (isinstance(func, FunctionDefinition) and isinstance(value, FunctionDefinition)):
+            self.report(messages.RedefinedFunction, line, name, func.source.lineno)
+
+        # Check for redefining an unused import
+        if report_redef and not isinstance(scope, ClassScope):
+            for up_scope in self.scope_stack[::-1]:
+                upval = up_scope.get(name)
+                if isinstance(upval, Importation) and not upval.used:
+                    self.report(messages.RedefinedWhileUnused, line, col, name, upval.source.lineno)
+
+        # Check for "del undefined_name"
+        if isinstance(value, UnBinding):
+            try:
+                del scope[name]
+            except KeyError:
+                self.report(messages.UndefinedName, line, col, name)
+        else:
+            scope[name] = value
+
+    def visit(self, node):
+        if not isinstance(node, allowed_before_future):
+            self.futures_allowed = False
+
+        return super(Checker, self).visit(node)
+
+    def visit_nodes(self, nodes):
+        try:
+            nodes = list(getattr(nodes, 'elts', nodes))
+        except TypeError:
+            nodes = [nodes]
+
+        for node in nodes:
+            self.visit(node)
+
+    def is_builtin(self, name):
+        if hasattr(__builtin__, name):
+            return True
+        if name in defined_names:
+            return True
+        if name in self.builtins:
+            return True
+
+        return False
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/messages.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,77 @@
+# (c) 2005 Divmod, Inc.  See LICENSE file for details
+
+class Message(object):
+    message = ''
+    message_args = ()
+    def __init__(self, filename, lineno, col = None):
+        self.filename = filename
+        self.lineno = lineno
+        self.col = col
+    def __str__(self):
+        if self.col is not None:
+            return '%s:%s(%d): %s' % (self.filename, self.lineno, self.col, self.message % self.message_args)
+        else:
+            return '%s:%s: %s' % (self.filename, self.lineno, self.message % self.message_args)
+
+
+class UnusedImport(Message):
+    message = '%r imported but unused'
+    def __init__(self, filename, lineno, name):
+        Message.__init__(self, filename, lineno)
+        self.message_args = (name,)
+
+
+class RedefinedWhileUnused(Message):
+    message = 'redefinition of unused %r from line %r'
+    def __init__(self, filename, lineno, col, name, orig_lineno):
+        Message.__init__(self, filename, lineno)
+        self.message_args = (name, orig_lineno)
+
+
+class ImportShadowedByLoopVar(Message):
+    message = 'import %r from line %r shadowed by loop variable'
+    def __init__(self, filename, lineno, col, name, orig_lineno):
+        Message.__init__(self, filename, lineno, col)
+        self.message_args = (name, orig_lineno)
+
+
+class ImportStarUsed(Message):
+    message = "'from %s import *' used; unable to detect undefined names"
+    def __init__(self, filename, lineno, col, modname):
+        Message.__init__(self, filename, lineno, col)
+        self.message_args = (modname,)
+
+
+class UndefinedName(Message):
+    message = 'undefined name %r'
+    def __init__(self, filename, lineno, col, name):
+        Message.__init__(self, filename, lineno, col)
+        self.message_args = (name,)
+
+
+class UndefinedLocal(Message):
+    message = "local variable %r (defined in enclosing scope on line %r) referenced before assignment"
+    def __init__(self, filename, lineno, col, name, orig_lineno, orig_col):
+        Message.__init__(self, filename, lineno)
+        self.message_args = (name, orig_lineno)
+
+
+class DuplicateArgument(Message):
+    message = 'duplicate argument %r in function definition'
+    def __init__(self, filename, lineno, col, name):
+        Message.__init__(self, filename, lineno, col)
+        self.message_args = (name,)
+
+
+class RedefinedFunction(Message):
+    message = 'redefinition of function %r from line %r'
+    def __init__(self, filename, lineno, name, orig_lineno):
+        Message.__init__(self, filename, lineno)
+        self.message_args = (name, orig_lineno)
+
+
+class LateFutureImport(Message):
+    message = 'future import(s) %r after other statements'
+    def __init__(self, filename, lineno, col, names):
+        Message.__init__(self, filename, lineno)
+        self.message_args = (names,)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/scripts/pyflakes.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,63 @@
+
+"""
+Implementation of the command-line I{pyflakes} tool.
+"""
+
+import _ast
+import sys
+import os
+
+checker = __import__('pyflakes.checker').checker
+
+def check(codeString, filename):
+    try:
+        tree = compile(codeString, filename, 'exec', _ast.PyCF_ONLY_AST)
+    except (SyntaxError, IndentationError):
+        value = sys.exc_info()[1]
+        try:
+            (lineno, offset, line) = value[1][1:]
+        except IndexError:
+            print >> sys.stderr, 'could not compile %r' % (filename,)
+            return 1
+        if line.endswith("\n"):
+            line = line[:-1]
+        print >> sys.stderr, '%s:%d: could not compile' % (filename, lineno)
+        print >> sys.stderr, line
+        print >> sys.stderr, " " * (offset-2), "^"
+        return 1
+    else:
+        w = checker.Checker(tree, filename)
+        w.messages.sort(lambda a, b: cmp(a.lineno, b.lineno))
+        for warning in w.messages:
+            print warning
+        return len(w.messages)
+
+
+def checkPath(filename):
+    """
+    Check the given path, printing out any warnings detected.
+
+    @return: the number of warnings printed
+    """
+    if os.path.exists(filename):
+        return check(file(filename, 'U').read() + '\n', filename)
+    else:
+        print >> sys.stderr, '%s: no such file' % (filename,)
+        return 1
+
+def main():
+    warnings = 0
+    args = sys.argv[1:]
+    if args:
+        for arg in args:
+            if os.path.isdir(arg):
+                for dirpath, dirnames, filenames in os.walk(arg):
+                    for filename in filenames:
+                        if filename.endswith('.py'):
+                            warnings += checkPath(os.path.join(dirpath, filename))
+            else:
+                warnings += checkPath(arg)
+    else:
+        warnings += check(sys.stdin.read(), '<stdin>')
+
+    raise SystemExit(warnings > 0)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/test/harness.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,24 @@
+
+import textwrap
+
+from twisted.trial import unittest
+
+from pyflakes import checker, ast
+
+
+class Test(unittest.TestCase):
+
+    def flakes(self, input, *expectedOutputs):
+        w = checker.Checker(ast.parse(textwrap.dedent(input)))
+        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([str(o) for o in w.messages])))
+        return w
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/test/test_imports.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,512 @@
+
+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_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):
+        self.flakes('import fu.bar; fu.bar')
+    test_packageImport.todo = "this has been hacked to treat 'import fu.bar' as just 'import fu'"
+
+    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
+        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_explicitlyPublic(self):
+        '''imports mentioned in __all__ are not unused'''
+        self.flakes('import fu; __all__ = ["fu"]')
+    test_explicitlyPublic.todo = "this would require importing the module or doing smarter parsing"
+
+    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')
+
+    def test_futureImportFirst(self):
+        """
+        __future__ imports must come before anything else.
+        """
+        self.flakes('''
+        x = 5
+        from __future__ import division
+        ''', m.LateFutureImport)
+
+
+
+class Python24Tests(harness.Test):
+    """
+    Tests for checking of syntax which is valid in Python 2.4 and newer.
+    """
+    if version_info < (2, 4):
+        skip = "Python 2.4 required for generator expression and decorator tests."
+
+
+    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)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/test/test_other.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,234 @@
+# (c) 2005-2008 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')
+
+
+
+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_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_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)
+
+    def test_listNestedListComprehension(self):
+        self.flakes('''
+        root = [['213', '123'], ['4354']]
+        foo = [int(c) for group in root for c in group]
+        ''')
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/test/test_script.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,48 @@
+
+"""
+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\n')
+        self.assertEquals(count, 1)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/pyflakes/test/test_undefined_names.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,182 @@
+
+from sys import version_info
+
+from pyflakes import messages as m
+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_magic_globals(self):
+        self.flakes('__file__')
+
+    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_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
+        ''', 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
+        ''', 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
+        ''', 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
+        ''', 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
+
+        f()
+        ''', m.UndefinedName)
+
+
+
+class Python24Test(harness.Test):
+    """
+    Tests for checking of syntax which is valid in Python 2.4 and newer.
+    """
+    if version_info < (2, 4):
+        skip = "Python 2.4 required for generator expression tests."
+
+    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)')
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/vim/ftplugin/python/pyflakes/setup.py	Fri May 21 14:59:02 2010 -0400
@@ -0,0 +1,19 @@
+#!/usr/bin/python
+# (c) 2005 Divmod, Inc.  See LICENSE file for details
+
+from distutils.core import setup
+
+setup(
+    name="pyflakes",
+    license="MIT",
+    version="0.2.1",
+    description="passive checker of Python programs",
+    author="Phil Frost",
+    maintainer="Moe Aboulkheir",
+    maintainer_email="moe@divmod.com",
+    url="http://www.divmod.org/projects/pyflakes",
+    packages=["pyflakes", "pyflakes.scripts"],
+    scripts=["bin/pyflakes"],
+    long_description="""Pyflakes is program to analyze Python programs and detect various errors. It
+works by parsing the source file, not importing it, so it is safe to use on
+modules with side effects. It's also much faster.""")