global: update vendored pyflakes from 0.7.3 to 1.5.0
authorGregory Szorc <gps@mozilla.com>
Mon, 23 Jan 2017 17:22:54 -0800
changeset 691174 1550fe5c904f8c8960a32c74f59a438909f290b8
parent 691173 5dcce04426ced555f1647ef39e10ae188460b09b
child 691175 ca20718707a677bd247ea40d52cd05a6dcc7ceaa
push id87314
push usergszorc@mozilla.com
push dateThu, 02 Nov 2017 02:08:10 +0000
global: update vendored pyflakes from 0.7.3 to 1.5.0 MozReview-Commit-ID: HwxUUi0rL9W
pylib/pyflakes/AUTHORS
pylib/pyflakes/LICENSE
pylib/pyflakes/NEWS.txt
pylib/pyflakes/PKG-INFO
pylib/pyflakes/README.rst
pylib/pyflakes/pyflakes.egg-info/PKG-INFO
pylib/pyflakes/pyflakes.egg-info/SOURCES.txt
pylib/pyflakes/pyflakes/__init__.py
pylib/pyflakes/pyflakes/api.py
pylib/pyflakes/pyflakes/checker.py
pylib/pyflakes/pyflakes/messages.py
pylib/pyflakes/pyflakes/reporter.py
pylib/pyflakes/pyflakes/scripts/pyflakes.py
pylib/pyflakes/pyflakes/test/harness.py
pylib/pyflakes/pyflakes/test/test_api.py
pylib/pyflakes/pyflakes/test/test_dict.py
pylib/pyflakes/pyflakes/test/test_doctests.py
pylib/pyflakes/pyflakes/test/test_imports.py
pylib/pyflakes/pyflakes/test/test_other.py
pylib/pyflakes/pyflakes/test/test_return_with_arguments_inside_generator.py
pylib/pyflakes/pyflakes/test/test_undefined_names.py
pylib/pyflakes/setup.cfg
pylib/pyflakes/setup.py
test-requirements.txt
--- a/pylib/pyflakes/AUTHORS
+++ b/pylib/pyflakes/AUTHORS
@@ -1,19 +1,22 @@
-
 Contributors
 ------------
 
+* Phil Frost - Former Divmod Team
 * Moe Aboulkheir - Former Divmod Team
 * Jean-Paul Calderone - Former Divmod Team
 * Glyph Lefkowitz - Former Divmod Team
 * Tristan Seligmann
 * Jonathan Lange
 * Georg Brandl
 * Ronny Pfannschmidt
 * Virgil Dupras
 * Kevin Watters
 * Ian Cordasco
 * Florent Xicluna
 * Domen Kožar
 * Marcin Cieślak
 * Steven Myint
 * Ignas Mikalajūnas
+
+See also the contributors list on GitHub:
+https://github.com/PyCQA/pyflakes/graphs/contributors
--- a/pylib/pyflakes/LICENSE
+++ b/pylib/pyflakes/LICENSE
@@ -1,10 +1,10 @@
 Copyright 2005-2011 Divmod, Inc.
-Copyright 2013 Florent Xicluna
+Copyright 2013-2014 Florent Xicluna
 
 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:
--- a/pylib/pyflakes/NEWS.txt
+++ b/pylib/pyflakes/NEWS.txt
@@ -1,8 +1,94 @@
+1.5.0 (2017-01-09)
+  - Enable support for PEP 526 annotated assignments
+
+1.4.0 (2016-12-30):
+  - Change formatting of ImportStarMessage to be consistent with other errors
+  - Support PEP 498 "f-strings"
+
+1.3.0 (2016-09-01):
+  - Fix PyPy2 Windows IntegrationTests
+  - Check for duplicate dictionary keys
+  - Fix TestMain tests on Windows
+  - Fix "continue" and "break" checks ignoring py3.5's "async for" loop
+
+1.2.3 (2016-05-12):
+  - Fix TypeError when processing relative imports
+
+1.2.2 (2016-05-06):
+  - Avoid traceback when exception is del-ed in except
+
+1.2.1 (2015-05-05):
+  - Fix false RedefinedWhileUnused for submodule imports
+
+1.2.0 (2016-05-03):
+  - Warn against reusing exception names after the except: block on Python 3
+  - Improve the error messages for imports
+
+1.1.0 (2016-03-01):
+  - Allow main() to accept arguments.
+  - Support @ matrix-multiplication operator
+  - Validate __future__ imports
+  - Fix doctest scope testing
+  - Warn for tuple assertions which are always true
+  - Warn for "import *" not at module level on Python 3
+  - Catch many more kinds of SyntaxErrors
+  - Check PEP 498 f-strings
+  - (and a few more sundry bugfixes)
+
+1.0.0 (2015-09-20):
+  - Python 3.5 support. async/await statements in particular.
+  - Fix test_api.py on Windows.
+  - Eliminate a false UnusedImport warning when the name has been
+    declared "global"
+
+0.9.2 (2015-06-17):
+  - Fix a traceback when a global is defined in one scope, and used in another.
+
+0.9.1 (2015-06-09):
+  - Update NEWS.txt to include 0.9.0, which had been forgotten.
+
+0.9.0 (2015-05-31):
+  - Exit gracefully, not with a traceback, on SIGINT and SIGPIPE.
+  - Fix incorrect report of undefined name when using lambda expressions in
+    generator expressions.
+  - Don't crash on DOS line endings on Windows and Python 2.6.
+  - Don't report an undefined name if the 'del' which caused a name to become
+    undefined is only conditionally executed.
+  - Properly handle differences in list comprehension scope in Python 3.
+  - Improve handling of edge cases around 'global' defined variables.
+  - Report an error for 'return' outside a function.
+
+0.8.1 (2014-03-30):
+  - Detect the declared encoding in Python 3.
+  - Do not report redefinition of import in a local scope, if the
+    global name is used elsewhere in the module.
+  - Catch undefined variable in loop generator when it is also used as
+    loop variable.
+  - Report undefined name for `(a, b) = (1, 2)` but not for the general
+    unpacking `(a, b) = func()`.
+  - Correctly detect when an imported module is used in default arguments
+    of a method, when the method and the module use the same name.
+  - Distribute a universal wheel file.
+
+0.8.0 (2014-03-22):
+  - Adapt for the AST in Python 3.4.
+  - Fix caret position on SyntaxError.
+  - Fix crash on Python 2.x with some doctest SyntaxError.
+  - Add tox.ini.
+  - The `PYFLAKES_NODOCTEST` environment variable has been replaced with the
+    `PYFLAKES_DOCTEST` environment variable (with the opposite meaning).
+    Doctest checking is now disabled by default; set the environment variable
+    to enable it.
+  - Correctly parse incremental `__all__ += [...]`.
+  - Catch return with arguments inside a generator (Python <= 3.2).
+  - Do not complain about `_` in doctests.
+  - Drop deprecated methods `pushFunctionScope` and `pushClassScope`.
+
 0.7.3 (2013-07-02):
   - Do not report undefined name for generator expression and dict or
     set comprehension at class level.
   - Deprecate `Checker.pushFunctionScope` and `Checker.pushClassScope`:
     use `Checker.pushScope` instead.
   - Remove dependency on Unittest2 for the tests.
 
 0.7.2 (2013-04-24):
@@ -78,12 +164,12 @@ 0.4.0 (2009-11-25):
 
 0.3.0 (2009-01-30):
   - Display more informative SyntaxError messages.
   - Don't hang flymake with unmatched triple quotes (only report a single
     line of source for a multiline syntax error).
   - Recognize __builtins__ as a defined name.
   - Improve pyflakes support for python versions 2.3-2.5
   - Support for if-else expressions and with statements.
-  - Warn instead of error on non-existant file paths.
+  - Warn instead of error on non-existent file paths.
   - Check for __future__ imports after other statements.
   - Add reporting for some types of import shadowing.
   - Improve reporting of unbound locals
--- a/pylib/pyflakes/PKG-INFO
+++ b/pylib/pyflakes/PKG-INFO
@@ -1,49 +1,101 @@
 Metadata-Version: 1.1
 Name: pyflakes
-Version: 0.7.3
+Version: 1.5.0
 Summary: passive checker of Python programs
-Home-page: https://launchpad.net/pyflakes
-Author: Florent Xicluna
-Author-email: pyflakes-dev@lists.launchpad.net
+Home-page: https://github.com/PyCQA/pyflakes
+Author: A lot of people
+Author-email: code-quality@python.org
 License: MIT
 Description: ========
         Pyflakes
         ========
         
         A simple program which checks Python source files for errors.
         
         Pyflakes analyzes programs and detects 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.
         
-        It is `available on PyPI <http://pypi.python.org/pypi/pyflakes>`_
-        and it supports all active versions of Python from 2.5 to 3.3.
+        It is `available on PyPI <https://pypi.python.org/pypi/pyflakes>`_
+        and it supports all active versions of Python from 2.5 to 3.5.
+        
         
         
         Installation
         ------------
         
         It can be installed with::
         
           $ pip install --upgrade pyflakes
         
         
+        Useful tips:
+        
+        * Be sure to install it for a version of Python which is compatible
+          with your codebase: for Python 2, ``pip2 install pyflakes`` and for
+          Python3, ``pip3 install pyflakes``.
+        
+        * You can also invoke Pyflakes with ``python3 -m pyflakes .`` or
+          ``python2 -m pyflakes .`` if you have it installed for both versions.
+        
+        * If you require more options and more flexibility, you could give a
+          look to Flake8_ too.
+          
+        
+        Design Principles
+        -----------------
+        Pyflakes makes a simple promise: it will never complain about style,
+        and it will try very, very hard to never emit false positives.
+        
+        Pyflakes is also faster than Pylint_
+        or Pychecker_. This is
+        largely because Pyflakes only examines the syntax tree of each file
+        individually. As a consequence, Pyflakes is more limited in the
+        types of things it can check.
+        
+        If you like Pyflakes but also want stylistic checks, you want
+        flake8_, which combines
+        Pyflakes with style checks against
+        `PEP 8`_ and adds
+        per-project configuration ability.
+        
+        
         Mailing-list
         ------------
         
         Share your feedback and ideas: `subscribe to the mailing-list
-        <http://mail.python.org/mailman/listinfo/code-quality>`_
+        <https://mail.python.org/mailman/listinfo/code-quality>`_
         
+        Contributing
+        ------------
+        
+        Issues are tracked on `Launchpad <https://bugs.launchpad.net/pyflakes>`_.
         
-        .. image:: https://api.travis-ci.org/pyflakes/pyflakes.png
-           :target: https://travis-ci.org/pyflakes/pyflakes
+        Patches may be submitted via a `GitHub pull request`_ or via the mailing list
+        if you prefer. If you are comfortable doing so, please `rebase your changes`_
+        so they may be applied to master with a fast-forward merge, and each commit is
+        a coherent unit of work with a well-written log message.  If you are not
+        comfortable with this rebase workflow, the project maintainers will be happy to
+        rebase your commits for you.
+        
+        All changes should include tests and pass flake8_.
+        
+        .. image:: https://api.travis-ci.org/PyCQA/pyflakes.svg
+           :target: https://travis-ci.org/PyCQA/pyflakes
            :alt: Build status
         
+        .. _Pylint: http://www.pylint.org/
+        .. _flake8: https://pypi.python.org/pypi/flake8
+        .. _`PEP 8`: http://legacy.python.org/dev/peps/pep-0008/
+        .. _Pychecker: http://pychecker.sourceforge.net/
+        .. _`rebase your changes`: https://git-scm.com/book/en/v2/Git-Branching-Rebasing
+        .. _`GitHub pull request`: https://github.com/PyCQA/pyflakes/pulls
+        
 Platform: UNKNOWN
 Classifier: Development Status :: 6 - Mature
 Classifier: Environment :: Console
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
 Classifier: Programming Language :: Python :: 3
--- a/pylib/pyflakes/README.rst
+++ b/pylib/pyflakes/README.rst
@@ -3,30 +3,82 @@ Pyflakes
 ========
 
 A simple program which checks Python source files for errors.
 
 Pyflakes analyzes programs and detects 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.
 
-It is `available on PyPI <http://pypi.python.org/pypi/pyflakes>`_
-and it supports all active versions of Python from 2.5 to 3.3.
+It is `available on PyPI <https://pypi.python.org/pypi/pyflakes>`_
+and it supports all active versions of Python from 2.5 to 3.5.
+
 
 
 Installation
 ------------
 
 It can be installed with::
 
   $ pip install --upgrade pyflakes
 
 
+Useful tips:
+
+* Be sure to install it for a version of Python which is compatible
+  with your codebase: for Python 2, ``pip2 install pyflakes`` and for
+  Python3, ``pip3 install pyflakes``.
+
+* You can also invoke Pyflakes with ``python3 -m pyflakes .`` or
+  ``python2 -m pyflakes .`` if you have it installed for both versions.
+
+* If you require more options and more flexibility, you could give a
+  look to Flake8_ too.
+  
+
+Design Principles
+-----------------
+Pyflakes makes a simple promise: it will never complain about style,
+and it will try very, very hard to never emit false positives.
+
+Pyflakes is also faster than Pylint_
+or Pychecker_. This is
+largely because Pyflakes only examines the syntax tree of each file
+individually. As a consequence, Pyflakes is more limited in the
+types of things it can check.
+
+If you like Pyflakes but also want stylistic checks, you want
+flake8_, which combines
+Pyflakes with style checks against
+`PEP 8`_ and adds
+per-project configuration ability.
+
+
 Mailing-list
 ------------
 
 Share your feedback and ideas: `subscribe to the mailing-list
-<http://mail.python.org/mailman/listinfo/code-quality>`_
+<https://mail.python.org/mailman/listinfo/code-quality>`_
 
+Contributing
+------------
+
+Issues are tracked on `Launchpad <https://bugs.launchpad.net/pyflakes>`_.
 
-.. image:: https://api.travis-ci.org/pyflakes/pyflakes.png
-   :target: https://travis-ci.org/pyflakes/pyflakes
+Patches may be submitted via a `GitHub pull request`_ or via the mailing list
+if you prefer. If you are comfortable doing so, please `rebase your changes`_
+so they may be applied to master with a fast-forward merge, and each commit is
+a coherent unit of work with a well-written log message.  If you are not
+comfortable with this rebase workflow, the project maintainers will be happy to
+rebase your commits for you.
+
+All changes should include tests and pass flake8_.
+
+.. image:: https://api.travis-ci.org/PyCQA/pyflakes.svg
+   :target: https://travis-ci.org/PyCQA/pyflakes
    :alt: Build status
+
+.. _Pylint: http://www.pylint.org/
+.. _flake8: https://pypi.python.org/pypi/flake8
+.. _`PEP 8`: http://legacy.python.org/dev/peps/pep-0008/
+.. _Pychecker: http://pychecker.sourceforge.net/
+.. _`rebase your changes`: https://git-scm.com/book/en/v2/Git-Branching-Rebasing
+.. _`GitHub pull request`: https://github.com/PyCQA/pyflakes/pulls
--- a/pylib/pyflakes/pyflakes.egg-info/PKG-INFO
+++ b/pylib/pyflakes/pyflakes.egg-info/PKG-INFO
@@ -1,49 +1,101 @@
 Metadata-Version: 1.1
 Name: pyflakes
-Version: 0.7.3
+Version: 1.5.0
 Summary: passive checker of Python programs
-Home-page: https://launchpad.net/pyflakes
-Author: Florent Xicluna
-Author-email: pyflakes-dev@lists.launchpad.net
+Home-page: https://github.com/PyCQA/pyflakes
+Author: A lot of people
+Author-email: code-quality@python.org
 License: MIT
 Description: ========
         Pyflakes
         ========
         
         A simple program which checks Python source files for errors.
         
         Pyflakes analyzes programs and detects 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.
         
-        It is `available on PyPI <http://pypi.python.org/pypi/pyflakes>`_
-        and it supports all active versions of Python from 2.5 to 3.3.
+        It is `available on PyPI <https://pypi.python.org/pypi/pyflakes>`_
+        and it supports all active versions of Python from 2.5 to 3.5.
+        
         
         
         Installation
         ------------
         
         It can be installed with::
         
           $ pip install --upgrade pyflakes
         
         
+        Useful tips:
+        
+        * Be sure to install it for a version of Python which is compatible
+          with your codebase: for Python 2, ``pip2 install pyflakes`` and for
+          Python3, ``pip3 install pyflakes``.
+        
+        * You can also invoke Pyflakes with ``python3 -m pyflakes .`` or
+          ``python2 -m pyflakes .`` if you have it installed for both versions.
+        
+        * If you require more options and more flexibility, you could give a
+          look to Flake8_ too.
+          
+        
+        Design Principles
+        -----------------
+        Pyflakes makes a simple promise: it will never complain about style,
+        and it will try very, very hard to never emit false positives.
+        
+        Pyflakes is also faster than Pylint_
+        or Pychecker_. This is
+        largely because Pyflakes only examines the syntax tree of each file
+        individually. As a consequence, Pyflakes is more limited in the
+        types of things it can check.
+        
+        If you like Pyflakes but also want stylistic checks, you want
+        flake8_, which combines
+        Pyflakes with style checks against
+        `PEP 8`_ and adds
+        per-project configuration ability.
+        
+        
         Mailing-list
         ------------
         
         Share your feedback and ideas: `subscribe to the mailing-list
-        <http://mail.python.org/mailman/listinfo/code-quality>`_
+        <https://mail.python.org/mailman/listinfo/code-quality>`_
         
+        Contributing
+        ------------
+        
+        Issues are tracked on `Launchpad <https://bugs.launchpad.net/pyflakes>`_.
         
-        .. image:: https://api.travis-ci.org/pyflakes/pyflakes.png
-           :target: https://travis-ci.org/pyflakes/pyflakes
+        Patches may be submitted via a `GitHub pull request`_ or via the mailing list
+        if you prefer. If you are comfortable doing so, please `rebase your changes`_
+        so they may be applied to master with a fast-forward merge, and each commit is
+        a coherent unit of work with a well-written log message.  If you are not
+        comfortable with this rebase workflow, the project maintainers will be happy to
+        rebase your commits for you.
+        
+        All changes should include tests and pass flake8_.
+        
+        .. image:: https://api.travis-ci.org/PyCQA/pyflakes.svg
+           :target: https://travis-ci.org/PyCQA/pyflakes
            :alt: Build status
         
+        .. _Pylint: http://www.pylint.org/
+        .. _flake8: https://pypi.python.org/pypi/flake8
+        .. _`PEP 8`: http://legacy.python.org/dev/peps/pep-0008/
+        .. _Pychecker: http://pychecker.sourceforge.net/
+        .. _`rebase your changes`: https://git-scm.com/book/en/v2/Git-Branching-Rebasing
+        .. _`GitHub pull request`: https://github.com/PyCQA/pyflakes/pulls
+        
 Platform: UNKNOWN
 Classifier: Development Status :: 6 - Mature
 Classifier: Environment :: Console
 Classifier: Intended Audience :: Developers
 Classifier: License :: OSI Approved :: MIT License
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
 Classifier: Programming Language :: Python :: 3
--- a/pylib/pyflakes/pyflakes.egg-info/SOURCES.txt
+++ b/pylib/pyflakes/pyflakes.egg-info/SOURCES.txt
@@ -1,13 +1,14 @@
 AUTHORS
 LICENSE
 MANIFEST.in
 NEWS.txt
 README.rst
+setup.cfg
 setup.py
 bin/pyflakes
 pyflakes/__init__.py
 pyflakes/__main__.py
 pyflakes/api.py
 pyflakes/checker.py
 pyflakes/messages.py
 pyflakes/reporter.py
@@ -16,12 +17,14 @@ pyflakes.egg-info/SOURCES.txt
 pyflakes.egg-info/dependency_links.txt
 pyflakes.egg-info/entry_points.txt
 pyflakes.egg-info/top_level.txt
 pyflakes/scripts/__init__.py
 pyflakes/scripts/pyflakes.py
 pyflakes/test/__init__.py
 pyflakes/test/harness.py
 pyflakes/test/test_api.py
+pyflakes/test/test_dict.py
 pyflakes/test/test_doctests.py
 pyflakes/test/test_imports.py
 pyflakes/test/test_other.py
+pyflakes/test/test_return_with_arguments_inside_generator.py
 pyflakes/test/test_undefined_names.py
\ No newline at end of file
--- a/pylib/pyflakes/pyflakes/__init__.py
+++ b/pylib/pyflakes/pyflakes/__init__.py
@@ -1,2 +1,1 @@
-
-__version__ = '0.7.3'
+__version__ = '1.5.0'
--- a/pylib/pyflakes/pyflakes/api.py
+++ b/pylib/pyflakes/pyflakes/api.py
@@ -1,17 +1,16 @@
 """
 API for the command-line I{pyflakes} tool.
 """
 from __future__ import with_statement
 
 import sys
 import os
 import _ast
-from optparse import OptionParser
 
 from pyflakes import checker, __version__
 from pyflakes import reporter as modReporter
 
 __all__ = ['check', 'checkPath', 'checkRecursive', 'iterSourceCode', 'main']
 
 
 def check(codeString, filename, reporter=None):
@@ -37,16 +36,28 @@ def check(codeString, filename, reporter
     try:
         tree = compile(codeString, filename, "exec", _ast.PyCF_ONLY_AST)
     except SyntaxError:
         value = sys.exc_info()[1]
         msg = value.args[0]
 
         (lineno, offset, text) = value.lineno, value.offset, value.text
 
+        if checker.PYPY:
+            if text is None:
+                lines = codeString.splitlines()
+                if len(lines) >= lineno:
+                    text = lines[lineno - 1]
+                    if sys.version_info >= (3, ) and isinstance(text, bytes):
+                        try:
+                            text = text.decode('ascii')
+                        except UnicodeDecodeError:
+                            text = None
+            offset -= 1
+
         # If there's an encoding problem with the file, the text is None.
         if text is None:
             # Avoid using msg, since for the only known case, it contains a
             # bogus message that claims the encoding the file declared was
             # unknown.
             reporter.unexpectedError(filename, 'problem decoding source')
         else:
             reporter.syntaxError(filename, msg, lineno, offset, text)
@@ -69,18 +80,29 @@ def checkPath(filename, reporter=None):
     @param reporter: A L{Reporter} instance, where errors and warnings will be
         reported.
 
     @return: the number of warnings printed
     """
     if reporter is None:
         reporter = modReporter._makeDefaultReporter()
     try:
-        with open(filename, 'U') as f:
-            codestr = f.read() + '\n'
+        # in Python 2.6, compile() will choke on \r\n line endings. In later
+        # versions of python it's smarter, and we want binary mode to give
+        # compile() the best opportunity to do the right thing WRT text
+        # encodings.
+        if sys.version_info < (2, 7):
+            mode = 'rU'
+        else:
+            mode = 'rb'
+
+        with open(filename, mode) as f:
+            codestr = f.read()
+        if sys.version_info < (2, 7):
+            codestr += '\n'     # Work around for Python <= 2.6
     except UnicodeError:
         reporter.unexpectedError(filename, 'problem decoding source')
         return 1
     except IOError:
         msg = sys.exc_info()[1]
         reporter.unexpectedError(filename, msg.args[1])
         return 1
     return check(codestr, filename, reporter)
@@ -115,17 +137,51 @@ def checkRecursive(paths, reporter):
     @return: The number of warnings found.
     """
     warnings = 0
     for sourcePath in iterSourceCode(paths):
         warnings += checkPath(sourcePath, reporter)
     return warnings
 
 
-def main(prog=None):
-    parser = OptionParser(prog=prog, version=__version__)
-    __, args = parser.parse_args()
+def _exitOnSignal(sigName, message):
+    """Handles a signal with sys.exit.
+
+    Some of these signals (SIGPIPE, for example) don't exist or are invalid on
+    Windows. So, ignore errors that might arise.
+    """
+    import signal
+
+    try:
+        sigNumber = getattr(signal, sigName)
+    except AttributeError:
+        # the signal constants defined in the signal module are defined by
+        # whether the C library supports them or not. So, SIGPIPE might not
+        # even be defined.
+        return
+
+    def handler(sig, f):
+        sys.exit(message)
+
+    try:
+        signal.signal(sigNumber, handler)
+    except ValueError:
+        # It's also possible the signal is defined, but then it's invalid. In
+        # this case, signal.signal raises ValueError.
+        pass
+
+
+def main(prog=None, args=None):
+    """Entry point for the script "pyflakes"."""
+    import optparse
+
+    # Handle "Keyboard Interrupt" and "Broken pipe" gracefully
+    _exitOnSignal('SIGINT', '... stopped')
+    _exitOnSignal('SIGPIPE', 1)
+
+    parser = optparse.OptionParser(prog=prog, version=__version__)
+    (__, args) = parser.parse_args(args=args)
     reporter = modReporter._makeDefaultReporter()
     if args:
         warnings = checkRecursive(args, reporter)
     else:
         warnings = check(sys.stdin.read(), '<stdin>', reporter)
     raise SystemExit(warnings > 0)
--- a/pylib/pyflakes/pyflakes/checker.py
+++ b/pylib/pyflakes/pyflakes/checker.py
@@ -1,120 +1,353 @@
 """
 Main module.
 
 Implement the central Checker class.
 Also, it models the Bindings and Scopes.
 """
+import __future__
 import doctest
 import os
 import sys
+
+PY2 = sys.version_info < (3, 0)
+PY32 = sys.version_info < (3, 3)    # Python 2.5 to 3.2
+PY33 = sys.version_info < (3, 4)    # Python 2.5 to 3.3
+PY34 = sys.version_info < (3, 5)    # Python 2.5 to 3.4
 try:
-    builtin_vars = dir(__import__('builtins'))
-    PY2 = False
-except ImportError:
-    builtin_vars = dir(__import__('__builtin__'))
-    PY2 = True
+    sys.pypy_version_info
+    PYPY = True
+except AttributeError:
+    PYPY = False
+
+builtin_vars = dir(__import__('__builtin__' if PY2 else 'builtins'))
 
 try:
     import ast
-    iter_child_nodes = ast.iter_child_nodes
 except ImportError:     # Python 2.5
     import _ast as ast
 
     if 'decorator_list' not in ast.ClassDef._fields:
         # Patch the missing attribute 'decorator_list'
         ast.ClassDef.decorator_list = ()
         ast.FunctionDef.decorator_list = property(lambda s: s.decorators)
 
-    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 in node._fields:
-            field = getattr(node, name, None)
-            if isinstance(field, ast.AST):
-                yield field
-            elif isinstance(field, list):
-                for item in field:
-                    yield item
-# Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally)
-if hasattr(ast, 'Try'):
-    ast_TryExcept = ast.Try
-    ast_TryFinally = ()
-else:
-    ast_TryExcept = ast.TryExcept
-    ast_TryFinally = ast.TryFinally
-
 from pyflakes import messages
 
 
 if PY2:
     def getNodeType(node_class):
         # workaround str.upper() which is locale-dependent
         return str(unicode(node_class.__name__).upper())
 else:
     def getNodeType(node_class):
         return node_class.__name__.upper()
 
+# Python >= 3.3 uses ast.Try instead of (ast.TryExcept + ast.TryFinally)
+if PY32:
+    def getAlternatives(n):
+        if isinstance(n, (ast.If, ast.TryFinally)):
+            return [n.body]
+        if isinstance(n, ast.TryExcept):
+            return [n.body + n.orelse] + [[hdl] for hdl in n.handlers]
+else:
+    def getAlternatives(n):
+        if isinstance(n, ast.If):
+            return [n.body]
+        if isinstance(n, ast.Try):
+            return [n.body + n.orelse] + [[hdl] for hdl in n.handlers]
+
+if PY34:
+    LOOP_TYPES = (ast.While, ast.For)
+else:
+    LOOP_TYPES = (ast.While, ast.For, ast.AsyncFor)
+
+
+class _FieldsOrder(dict):
+    """Fix order of AST node fields."""
+
+    def _get_fields(self, node_class):
+        # handle iter before target, and generators before element
+        fields = node_class._fields
+        if 'iter' in fields:
+            key_first = 'iter'.find
+        elif 'generators' in fields:
+            key_first = 'generators'.find
+        else:
+            key_first = 'value'.find
+        return tuple(sorted(fields, key=key_first, reverse=True))
+
+    def __missing__(self, node_class):
+        self[node_class] = fields = self._get_fields(node_class)
+        return fields
+
+
+def counter(items):
+    """
+    Simplest required implementation of collections.Counter. Required as 2.6
+    does not have Counter in collections.
+    """
+    results = {}
+    for item in items:
+        results[item] = results.get(item, 0) + 1
+    return results
+
+
+def iter_child_nodes(node, omit=None, _fields_order=_FieldsOrder()):
+    """
+    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 in _fields_order[node.__class__]:
+        if name == omit:
+            continue
+        field = getattr(node, name, None)
+        if isinstance(field, ast.AST):
+            yield field
+        elif isinstance(field, list):
+            for item in field:
+                yield item
+
+
+def convert_to_value(item):
+    if isinstance(item, ast.Str):
+        return item.s
+    elif hasattr(ast, 'Bytes') and isinstance(item, ast.Bytes):
+        return item.s
+    elif isinstance(item, ast.Tuple):
+        return tuple(convert_to_value(i) for i in item.elts)
+    elif isinstance(item, ast.Num):
+        return item.n
+    elif isinstance(item, ast.Name):
+        result = VariableKey(item=item)
+        constants_lookup = {
+            'True': True,
+            'False': False,
+            'None': None,
+        }
+        return constants_lookup.get(
+            result.name,
+            result,
+        )
+    elif (not PY33) and isinstance(item, ast.NameConstant):
+        # None, True, False are nameconstants in python3, but names in 2
+        return item.value
+    else:
+        return UnhandledKeyType()
+
 
 class Binding(object):
     """
     Represents the binding of a value to a name.
 
     The checker uses this to keep track of which names have been bound and
     which names have not. See L{Assignment} for a special type of binding that
     is checked with stricter rules.
 
-    @ivar used: pair of (L{Scope}, line-number) indicating the scope and
-                line number that this binding was last used
+    @ivar used: pair of (L{Scope}, node) indicating the scope and
+                the node 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))
 
+    def redefines(self, other):
+        return isinstance(other, Definition) and self.name == other.name
 
-class Importation(Binding):
+
+class Definition(Binding):
+    """
+    A binding that defines a function or a class.
+    """
+
+
+class UnhandledKeyType(object):
+    """
+    A dictionary key of a type that we cannot or do not check for duplicates.
+    """
+
+
+class VariableKey(object):
+    """
+    A dictionary key which is a variable.
+
+    @ivar item: The variable AST object.
+    """
+    def __init__(self, item):
+        self.name = item.id
+
+    def __eq__(self, compare):
+        return (
+            compare.__class__ == self.__class__
+            and compare.name == self.name
+        )
+
+    def __hash__(self):
+        return hash(self.name)
+
+
+class Importation(Definition):
     """
     A binding created by an import statement.
 
     @ivar fullName: The complete name given to the import statement,
         possibly including multiple dotted components.
     @type fullName: C{str}
     """
+
+    def __init__(self, name, source, full_name=None):
+        self.fullName = full_name or name
+        self.redefined = []
+        super(Importation, self).__init__(name, source)
+
+    def redefines(self, other):
+        if isinstance(other, SubmoduleImportation):
+            # See note in SubmoduleImportation about RedefinedWhileUnused
+            return self.fullName == other.fullName
+        return isinstance(other, Definition) and self.name == other.name
+
+    def _has_alias(self):
+        """Return whether importation needs an as clause."""
+        return not self.fullName.split('.')[-1] == self.name
+
+    @property
+    def source_statement(self):
+        """Generate a source statement equivalent to the import."""
+        if self._has_alias():
+            return 'import %s as %s' % (self.fullName, self.name)
+        else:
+            return 'import %s' % self.fullName
+
+    def __str__(self):
+        """Return import full name with alias."""
+        if self._has_alias():
+            return self.fullName + ' as ' + self.name
+        else:
+            return self.fullName
+
+
+class SubmoduleImportation(Importation):
+    """
+    A binding created by a submodule import statement.
+
+    A submodule import is a special case where the root module is implicitly
+    imported, without an 'as' clause, and the submodule is also imported.
+    Python does not restrict which attributes of the root module may be used.
+
+    This class is only used when the submodule import is without an 'as' clause.
+
+    pyflakes handles this case by registering the root module name in the scope,
+    allowing any attribute of the root module to be accessed.
+
+    RedefinedWhileUnused is suppressed in `redefines` unless the submodule
+    name is also the same, to avoid false positives.
+    """
+
     def __init__(self, name, source):
+        # A dot should only appear in the name when it is a submodule import
+        assert '.' in name and (not source or isinstance(source, ast.Import))
+        package_name = name.split('.')[0]
+        super(SubmoduleImportation, self).__init__(package_name, source)
         self.fullName = name
-        name = name.split('.')[0]
-        super(Importation, self).__init__(name, source)
+
+    def redefines(self, other):
+        if isinstance(other, Importation):
+            return self.fullName == other.fullName
+        return super(SubmoduleImportation, self).redefines(other)
+
+    def __str__(self):
+        return self.fullName
+
+    @property
+    def source_statement(self):
+        return 'import ' + self.fullName
+
+
+class ImportationFrom(Importation):
+
+    def __init__(self, name, source, module, real_name=None):
+        self.module = module
+        self.real_name = real_name or name
+
+        if module.endswith('.'):
+            full_name = module + self.real_name
+        else:
+            full_name = module + '.' + self.real_name
+
+        super(ImportationFrom, self).__init__(name, source, full_name)
+
+    def __str__(self):
+        """Return import full name with alias."""
+        if self.real_name != self.name:
+            return self.fullName + ' as ' + self.name
+        else:
+            return self.fullName
+
+    @property
+    def source_statement(self):
+        if self.real_name != self.name:
+            return 'from %s import %s as %s' % (self.module,
+                                                self.real_name,
+                                                self.name)
+        else:
+            return 'from %s import %s' % (self.module, self.name)
+
+
+class StarImportation(Importation):
+    """A binding created by a 'from x import *' statement."""
+
+    def __init__(self, name, source):
+        super(StarImportation, self).__init__('*', source)
+        # Each star importation needs a unique name, and
+        # may not be the module name otherwise it will be deemed imported
+        self.name = name + '.*'
+        self.fullName = name
+
+    @property
+    def source_statement(self):
+        return 'from ' + self.fullName + ' import *'
+
+    def __str__(self):
+        # When the module ends with a ., avoid the ambiguous '..*'
+        if self.fullName.endswith('.'):
+            return self.source_statement
+        else:
+            return self.name
+
+
+class FutureImportation(ImportationFrom):
+    """
+    A binding created by a from `__future__` import statement.
+
+    `__future__` imports are implicitly used.
+    """
+
+    def __init__(self, name, source, scope):
+        super(FutureImportation, self).__init__(name, source, '__future__')
+        self.used = (scope, source)
 
 
 class Argument(Binding):
     """
     Represents binding a name as an argument.
     """
 
 
-class Definition(Binding):
-    """
-    A binding that defines a function or a class.
-    """
-
-
 class Assignment(Binding):
     """
     Represents binding a name with an explicit assignment.
 
     The checker will raise warnings for any Assignment that isn't used. Also,
     the checker does not consider assignments in tuple/list unpacking to be
     Assignments, rather it treats them as simple Bindings.
     """
@@ -137,26 +370,27 @@ class ExportBinding(Binding):
     The only C{__all__} assignment that can be recognized is one which takes
     the value of a literal list containing literal strings.  For example::
 
         __all__ = ["foo", "bar"]
 
     Names which are imported and not otherwise used but appear in the value of
     C{__all__} will not have an unused import warning reported for them.
     """
-    def names(self):
-        """
-        Return a list of the names referenced by this binding.
-        """
-        names = []
-        if isinstance(self.source, ast.List):
-            for node in self.source.elts:
+
+    def __init__(self, name, source, scope):
+        if '__all__' in scope and isinstance(source, ast.AugAssign):
+            self.names = list(scope['__all__'].names)
+        else:
+            self.names = []
+        if isinstance(source.value, (ast.List, ast.Tuple)):
+            for node in source.value.elts:
                 if isinstance(node, ast.Str):
-                    names.append(node.s)
-        return names
+                    self.names.append(node.s)
+        super(ExportBinding, self).__init__(name, source)
 
 
 class Scope(dict):
     importStarred = False       # set to True when import * is found
 
     def __repr__(self):
         scope_cls = self.__class__.__name__
         return '<%s at 0x%x %s>' % (scope_cls, id(self), dict.__repr__(self))
@@ -175,16 +409,18 @@ class FunctionScope(Scope):
     usesLocals = False
     alwaysUsed = set(['__tracebackhide__',
                       '__traceback_info__', '__traceback_supplement__'])
 
     def __init__(self):
         super(FunctionScope, self).__init__()
         # Simplify: manage the special locals as globals
         self.globals = self.alwaysUsed.copy()
+        self.returnValue = None     # First non-empty return
+        self.isGenerator = False    # Detect a generator
 
     def unusedAssignments(self):
         """
         Return a generator for the assignments which have not been used.
         """
         for name, binding in self.items():
             if (not binding.used and name not in self.globals
                     and not self.usesLocals
@@ -192,29 +428,34 @@ class FunctionScope(Scope):
                 yield name, binding
 
 
 class GeneratorScope(Scope):
     pass
 
 
 class ModuleScope(Scope):
-    pass
+    """Scope for a module."""
+    _futures_allowed = True
+
+
+class DoctestScope(ModuleScope):
+    """Scope for a doctest."""
 
 
 # Globally defined names which are not attributes of the builtins module, or
 # are only present on some platforms.
 _MAGIC_GLOBALS = ['__file__', '__builtins__', 'WindowsError']
 
 
 def getNodeName(node):
     # Returns node.id, or node.name, or None
     if hasattr(node, 'id'):     # One of the many nodes with an id
         return node.id
-    if hasattr(node, 'name'):   # a ExceptHandler node
+    if hasattr(node, 'name'):   # an ExceptHandler node
         return node.name
 
 
 class Checker(object):
     """
     I check the cleanliness and sanity of Python code.
 
     @ivar _deferredFunctions: Tracking list used by L{deferFunction}.  Elements
@@ -224,36 +465,36 @@ class Checker(object):
 
     @ivar _deferredAssignments: Similar to C{_deferredFunctions}, but for
         callables which are deferred assignment checks.
     """
 
     nodeDepth = 0
     offset = None
     traceTree = False
-    withDoctest = ('PYFLAKES_NODOCTEST' not in os.environ)
 
     builtIns = set(builtin_vars).union(_MAGIC_GLOBALS)
     _customBuiltIns = os.environ.get('PYFLAKES_BUILTINS')
     if _customBuiltIns:
         builtIns.update(_customBuiltIns.split(','))
     del _customBuiltIns
 
-    def __init__(self, tree, filename='(none)', builtins=None):
+    def __init__(self, tree, filename='(none)', builtins=None,
+                 withDoctest='PYFLAKES_DOCTEST' in os.environ):
         self._nodeHandlers = {}
         self._deferredFunctions = []
         self._deferredAssignments = []
         self.deadScopes = []
         self.messages = []
         self.filename = filename
         if builtins:
             self.builtIns = self.builtIns.union(builtins)
+        self.withDoctest = withDoctest
         self.scopeStack = [ModuleScope()]
         self.exceptHandlers = [()]
-        self.futuresAllowed = True
         self.root = tree
         self.handleChildren(tree)
         self.runDeferred(self._deferredFunctions)
         # Set _deferredFunctions to None so that deferFunction will fail
         # noisily if called after we've run through the deferred functions.
         self._deferredFunctions = None
         self.runDeferred(self._deferredAssignments)
         # Set _deferredAssignments to None so that deferAssignment will fail
@@ -285,189 +526,227 @@ class Checker(object):
         """
         Run the callables in C{deferred} using their associated scope stack.
         """
         for handler, scope, offset in deferred:
             self.scopeStack = scope
             self.offset = offset
             handler()
 
+    def _in_doctest(self):
+        return (len(self.scopeStack) >= 2 and
+                isinstance(self.scopeStack[1], DoctestScope))
+
+    @property
+    def futuresAllowed(self):
+        if not all(isinstance(scope, ModuleScope)
+                   for scope in self.scopeStack):
+            return False
+
+        return self.scope._futures_allowed
+
+    @futuresAllowed.setter
+    def futuresAllowed(self, value):
+        assert value is False
+        if isinstance(self.scope, ModuleScope):
+            self.scope._futures_allowed = False
+
     @property
     def scope(self):
         return self.scopeStack[-1]
 
     def popScope(self):
         self.deadScopes.append(self.scopeStack.pop())
 
     def checkDeadScopes(self):
         """
         Look at scopes which have been fully examined and report names in them
         which were imported but unused.
         """
         for scope in self.deadScopes:
-            export = isinstance(scope.get('__all__'), ExportBinding)
-            if export:
-                all = scope['__all__'].names()
+            # imports in classes are public members
+            if isinstance(scope, ClassScope):
+                continue
+
+            all_binding = scope.get('__all__')
+            if all_binding and not isinstance(all_binding, ExportBinding):
+                all_binding = None
+
+            if all_binding:
+                all_names = set(all_binding.names)
+                undefined = all_names.difference(scope)
+            else:
+                all_names = undefined = []
+
+            if undefined:
                 if not scope.importStarred and \
                    os.path.basename(self.filename) != '__init__.py':
                     # Look for possible mistakes in the export list
-                    undefined = set(all) - set(scope)
                     for name in undefined:
                         self.report(messages.UndefinedExport,
                                     scope['__all__'].source, name)
-            else:
-                all = []
+
+                # mark all import '*' as used by the undefined in __all__
+                if scope.importStarred:
+                    for binding in scope.values():
+                        if isinstance(binding, StarImportation):
+                            binding.used = all_binding
 
             # Look for imported names that aren't used.
-            for importation in scope.values():
-                if isinstance(importation, Importation):
-                    if not importation.used and importation.name not in all:
-                        self.report(messages.UnusedImport,
-                                    importation.source, importation.name)
+            for value in scope.values():
+                if isinstance(value, Importation):
+                    used = value.used or value.name in all_names
+                    if not used:
+                        messg = messages.UnusedImport
+                        self.report(messg, value.source, str(value))
+                    for node in value.redefined:
+                        if isinstance(self.getParent(node), ast.For):
+                            messg = messages.ImportShadowedByLoopVar
+                        elif used:
+                            continue
+                        else:
+                            messg = messages.RedefinedWhileUnused
+                        self.report(messg, node, value.name, value.source)
 
     def pushScope(self, scopeClass=FunctionScope):
         self.scopeStack.append(scopeClass())
 
-    def pushFunctionScope(self):    # XXX Deprecated
-        self.pushScope(FunctionScope)
-
-    def pushClassScope(self):       # XXX Deprecated
-        self.pushScope(ClassScope)
-
     def report(self, messageClass, *args, **kwargs):
         self.messages.append(messageClass(self.filename, *args, **kwargs))
 
-    def hasParent(self, node, kind):
-        while hasattr(node, 'parent'):
+    def getParent(self, node):
+        # Lookup the first parent which is not Tuple, List or Starred
+        while True:
             node = node.parent
-            if isinstance(node, kind):
-                return True
+            if not hasattr(node, 'elts') and not hasattr(node, 'ctx'):
+                return node
 
-    def getCommonAncestor(self, lnode, rnode, stop=None):
-        if not stop:
-            stop = self.root
+    def getCommonAncestor(self, lnode, rnode, stop):
+        if stop in (lnode, rnode) or not (hasattr(lnode, 'parent') and
+                                          hasattr(rnode, 'parent')):
+            return None
         if lnode is rnode:
             return lnode
-        if stop in (lnode, rnode):
-            return stop
 
-        if not hasattr(lnode, 'parent') or not hasattr(rnode, 'parent'):
-            return
-        if (lnode.level > rnode.level):
+        if (lnode.depth > rnode.depth):
             return self.getCommonAncestor(lnode.parent, rnode, stop)
-        if (rnode.level > lnode.level):
+        if (lnode.depth < rnode.depth):
             return self.getCommonAncestor(lnode, rnode.parent, stop)
         return self.getCommonAncestor(lnode.parent, rnode.parent, stop)
 
-    def descendantOf(self, node, ancestors, stop=None):
+    def descendantOf(self, node, ancestors, stop):
         for a in ancestors:
-            if self.getCommonAncestor(node, a, stop) not in (stop, None):
+            if self.getCommonAncestor(node, a, stop):
                 return True
         return False
 
-    def onFork(self, parent, lnode, rnode, items):
-        return (self.descendantOf(lnode, items, parent) ^
-                self.descendantOf(rnode, items, parent))
-
     def differentForks(self, lnode, rnode):
         """True, if lnode and rnode are located on different forks of IF/TRY"""
-        ancestor = self.getCommonAncestor(lnode, rnode)
-        if isinstance(ancestor, ast.If):
-            for fork in (ancestor.body, ancestor.orelse):
-                if self.onFork(ancestor, lnode, rnode, fork):
+        ancestor = self.getCommonAncestor(lnode, rnode, self.root)
+        parts = getAlternatives(ancestor)
+        if parts:
+            for items in parts:
+                if self.descendantOf(lnode, items, ancestor) ^ \
+                   self.descendantOf(rnode, items, ancestor):
                     return True
-        elif isinstance(ancestor, ast_TryExcept):
-            body = ancestor.body + ancestor.orelse
-            for fork in [body] + [[hdl] for hdl in ancestor.handlers]:
-                if self.onFork(ancestor, lnode, rnode, fork):
-                    return True
-        elif isinstance(ancestor, ast_TryFinally):
-            if self.onFork(ancestor, lnode, rnode, ancestor.body):
-                return True
         return False
 
-    def addBinding(self, node, value, reportRedef=True):
+    def addBinding(self, node, value):
         """
         Called when a binding is altered.
 
         - `node` is the statement responsible for the change
-        - `value` is the optional new value, a Binding instance, associated
-          with the binding; if None, the binding is deleted if it exists.
-        - if `reportRedef` is True (default), rebinding while unused will be
-          reported.
+        - `value` is the new value, a Binding instance
         """
-        redefinedWhileUnused = False
-        if not isinstance(self.scope, ClassScope):
-            for scope in self.scopeStack[::-1]:
-                existing = scope.get(value.name)
-                if (isinstance(existing, Importation)
-                        and not existing.used
-                        and (not isinstance(value, Importation) or
-                             value.fullName == existing.fullName)
-                        and reportRedef
-                        and not self.differentForks(node, existing.source)):
-                    redefinedWhileUnused = True
+        # assert value.source in (node, node.parent):
+        for scope in self.scopeStack[::-1]:
+            if value.name in scope:
+                break
+        existing = scope.get(value.name)
+
+        if existing and not self.differentForks(node, existing.source):
+
+            parent_stmt = self.getParent(value.source)
+            if isinstance(existing, Importation) and isinstance(parent_stmt, ast.For):
+                self.report(messages.ImportShadowedByLoopVar,
+                            node, value.name, existing.source)
+
+            elif scope is self.scope:
+                if (isinstance(parent_stmt, ast.comprehension) and
+                        not isinstance(self.getParent(existing.source),
+                                       (ast.For, ast.comprehension))):
+                    self.report(messages.RedefinedInListComp,
+                                node, value.name, existing.source)
+                elif not existing.used and value.redefines(existing):
                     self.report(messages.RedefinedWhileUnused,
                                 node, value.name, existing.source)
 
-        existing = self.scope.get(value.name)
-        if not redefinedWhileUnused and self.hasParent(value.source, ast.ListComp):
-            if (existing and reportRedef
-                    and not self.hasParent(existing.source, (ast.For, ast.ListComp))
-                    and not self.differentForks(node, existing.source)):
-                self.report(messages.RedefinedInListComp,
-                            node, value.name, existing.source)
+            elif isinstance(existing, Importation) and value.redefines(existing):
+                existing.redefined.append(node)
 
-        if (isinstance(existing, Definition)
-                and not existing.used
-                and not self.differentForks(node, existing.source)):
-            self.report(messages.RedefinedWhileUnused,
-                        node, value.name, existing.source)
-        else:
-            self.scope[value.name] = value
+        if value.name in self.scope:
+            # then assume the rebound name is used as a global or within a loop
+            value.used = self.scope[value.name].used
+
+        self.scope[value.name] = value
 
     def getNodeHandler(self, node_class):
         try:
             return self._nodeHandlers[node_class]
         except KeyError:
             nodeType = getNodeType(node_class)
         self._nodeHandlers[node_class] = handler = getattr(self, nodeType)
         return handler
 
     def handleNodeLoad(self, node):
         name = getNodeName(node)
         if not name:
             return
-        # try local scope
-        try:
-            self.scope[name].used = (self.scope, node)
-        except KeyError:
-            pass
-        else:
-            return
 
-        scopes = [scope for scope in self.scopeStack[:-1]
-                  if isinstance(scope, (FunctionScope, ModuleScope))]
-        if isinstance(self.scope, GeneratorScope) and scopes[-1] != self.scopeStack[-2]:
-            scopes.append(self.scopeStack[-2])
+        in_generators = None
+        importStarred = None
 
         # try enclosing function scopes and global scope
-        importStarred = self.scope.importStarred
-        for scope in reversed(scopes):
-            importStarred = importStarred or scope.importStarred
+        for scope in self.scopeStack[-1::-1]:
+            # only generators used in a class scope can access the names
+            # of the class. this is skipped during the first iteration
+            if in_generators is False and isinstance(scope, ClassScope):
+                continue
+
             try:
                 scope[name].used = (self.scope, node)
             except KeyError:
                 pass
             else:
                 return
 
+            importStarred = importStarred or scope.importStarred
+
+            if in_generators is not False:
+                in_generators = isinstance(scope, GeneratorScope)
+
         # look in the built-ins
-        if importStarred or name in self.builtIns:
+        if name in self.builtIns:
             return
+
+        if importStarred:
+            from_list = []
+
+            for scope in self.scopeStack[-1::-1]:
+                for binding in scope.values():
+                    if isinstance(binding, StarImportation):
+                        # mark '*' imports as used for each scope
+                        binding.used = (self.scope, node)
+                        from_list.append(binding.fullName)
+
+            # report * usage, with a list of possible sources
+            from_list = ', '.join(sorted(from_list))
+            self.report(messages.ImportStarUsage, node, name, from_list)
+            return
+
         if name == '__path__' and os.path.basename(self.filename) == '__init__.py':
             # the special name __path__ is valid only in packages
             return
 
         # protected with a NameError handler?
         if 'NameError' not in self.exceptHandlers[-1]:
             self.report(messages.UndefinedName, node, name)
 
@@ -486,199 +765,266 @@ class Checker(object):
                 # been declared global
                 used = name in scope and scope[name].used
                 if used and used[0] is self.scope and name not in self.scope.globals:
                     # then it's probably a mistake
                     self.report(messages.UndefinedLocal,
                                 scope[name].used[1], name, scope[name].source)
                     break
 
-        parent = getattr(node, 'parent', None)
-        if isinstance(parent, (ast.For, ast.comprehension, ast.Tuple, ast.List)):
+        parent_stmt = self.getParent(node)
+        if isinstance(parent_stmt, (ast.For, ast.comprehension)) or (
+                parent_stmt != node.parent and
+                not self.isLiteralTupleUnpacking(parent_stmt)):
             binding = Binding(name, node)
-        elif (parent is not None and name == '__all__' and
-              isinstance(self.scope, ModuleScope)):
-            binding = ExportBinding(name, parent.value)
+        elif name == '__all__' and isinstance(self.scope, ModuleScope):
+            binding = ExportBinding(name, node.parent, self.scope)
         else:
             binding = Assignment(name, node)
-        if name in self.scope:
-            binding.used = self.scope[name].used
         self.addBinding(node, binding)
 
     def handleNodeDelete(self, node):
+
+        def on_conditional_branch():
+            """
+            Return `True` if node is part of a conditional body.
+            """
+            current = getattr(node, 'parent', None)
+            while current:
+                if isinstance(current, (ast.If, ast.While, ast.IfExp)):
+                    return True
+                current = getattr(current, 'parent', None)
+            return False
+
         name = getNodeName(node)
         if not name:
             return
+
+        if on_conditional_branch():
+            # We cannot predict if this conditional branch is going to
+            # be executed.
+            return
+
         if isinstance(self.scope, FunctionScope) and name in self.scope.globals:
             self.scope.globals.remove(name)
         else:
             try:
                 del self.scope[name]
             except KeyError:
                 self.report(messages.UndefinedName, node, name)
 
-    def handleChildren(self, tree):
-        for node in iter_child_nodes(tree):
+    def handleChildren(self, tree, omit=None):
+        for node in iter_child_nodes(tree, omit=omit):
             self.handleNode(node, tree)
 
+    def isLiteralTupleUnpacking(self, node):
+        if isinstance(node, ast.Assign):
+            for child in node.targets + [node.value]:
+                if not hasattr(child, 'elts'):
+                    return False
+            return True
+
     def isDocstring(self, node):
         """
         Determine if the given node is a docstring, as long as it is at the
         correct place in the node tree.
         """
         return isinstance(node, ast.Str) or (isinstance(node, ast.Expr) and
                                              isinstance(node.value, ast.Str))
 
     def getDocstring(self, node):
         if isinstance(node, ast.Expr):
             node = node.value
         if not isinstance(node, ast.Str):
             return (None, None)
-        # Computed incorrectly if the docstring has backslash
-        doctest_lineno = node.lineno - node.s.count('\n') - 1
+
+        if PYPY:
+            doctest_lineno = node.lineno - 1
+        else:
+            # Computed incorrectly if the docstring has backslash
+            doctest_lineno = node.lineno - node.s.count('\n') - 1
+
         return (node.s, doctest_lineno)
 
     def handleNode(self, node, parent):
         if node is None:
             return
         if self.offset and getattr(node, 'lineno', None) is not None:
             node.lineno += self.offset[0]
             node.col_offset += self.offset[1]
         if self.traceTree:
             print('  ' * self.nodeDepth + node.__class__.__name__)
         if self.futuresAllowed and not (isinstance(node, ast.ImportFrom) or
                                         self.isDocstring(node)):
             self.futuresAllowed = False
         self.nodeDepth += 1
-        node.level = self.nodeDepth
+        node.depth = self.nodeDepth
         node.parent = parent
         try:
             handler = self.getNodeHandler(node.__class__)
             handler(node)
         finally:
             self.nodeDepth -= 1
         if self.traceTree:
             print('  ' * self.nodeDepth + 'end ' + node.__class__.__name__)
 
     _getDoctestExamples = doctest.DocTestParser().get_examples
 
     def handleDoctests(self, node):
         try:
-            docstring, node_lineno = self.getDocstring(node.body[0])
-            if not docstring:
-                return
-            examples = self._getDoctestExamples(docstring)
+            (docstring, node_lineno) = self.getDocstring(node.body[0])
+            examples = docstring and self._getDoctestExamples(docstring)
         except (ValueError, IndexError):
             # e.g. line 6 of the docstring for <string> has inconsistent
             # leading whitespace: ...
             return
+        if not examples:
+            return
+
+        # Place doctest in module scope
+        saved_stack = self.scopeStack
+        self.scopeStack = [self.scopeStack[0]]
         node_offset = self.offset or (0, 0)
-        self.pushScope()
+        self.pushScope(DoctestScope)
+        underscore_in_builtins = '_' in self.builtIns
+        if not underscore_in_builtins:
+            self.builtIns.add('_')
         for example in examples:
             try:
                 tree = compile(example.source, "<doctest>", "exec", ast.PyCF_ONLY_AST)
             except SyntaxError:
                 e = sys.exc_info()[1]
+                if PYPY:
+                    e.offset += 1
                 position = (node_lineno + example.lineno + e.lineno,
-                            example.indent + 4 + e.offset)
+                            example.indent + 4 + (e.offset or 0))
                 self.report(messages.DoctestSyntaxError, node, position)
             else:
                 self.offset = (node_offset[0] + node_lineno + example.lineno,
                                node_offset[1] + example.indent + 4)
                 self.handleChildren(tree)
                 self.offset = node_offset
+        if not underscore_in_builtins:
+            self.builtIns.remove('_')
         self.popScope()
+        self.scopeStack = saved_stack
 
     def ignore(self, node):
         pass
 
     # "stmt" type nodes
-    RETURN = DELETE = PRINT = WHILE = IF = WITH = WITHITEM = RAISE = \
-        TRYFINALLY = ASSERT = EXEC = EXPR = handleChildren
+    DELETE = PRINT = FOR = ASYNCFOR = WHILE = IF = WITH = WITHITEM = \
+        ASYNCWITH = ASYNCWITHITEM = RAISE = TRYFINALLY = EXEC = \
+        EXPR = ASSIGN = handleChildren
 
-    CONTINUE = BREAK = PASS = ignore
+    PASS = ignore
 
     # "expr" type nodes
-    BOOLOP = BINOP = UNARYOP = IFEXP = DICT = SET = YIELD = YIELDFROM = \
-        COMPARE = CALL = REPR = ATTRIBUTE = SUBSCRIPT = LIST = TUPLE = \
-        STARRED = handleChildren
+    BOOLOP = BINOP = UNARYOP = IFEXP = SET = \
+        COMPARE = CALL = REPR = ATTRIBUTE = SUBSCRIPT = \
+        STARRED = NAMECONSTANT = handleChildren
 
     NUM = STR = BYTES = ELLIPSIS = ignore
 
     # "slice" type nodes
     SLICE = EXTSLICE = INDEX = handleChildren
 
     # expression contexts are node instances too, though being constants
     LOAD = STORE = DEL = AUGLOAD = AUGSTORE = PARAM = ignore
 
     # same for operators
     AND = OR = ADD = SUB = MULT = DIV = MOD = POW = LSHIFT = RSHIFT = \
         BITOR = BITXOR = BITAND = FLOORDIV = INVERT = NOT = UADD = USUB = \
-        EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = ignore
+        EQ = NOTEQ = LT = LTE = GT = GTE = IS = ISNOT = IN = NOTIN = \
+        MATMULT = ignore
 
     # additional node types
-    COMPREHENSION = KEYWORD = handleChildren
+    COMPREHENSION = KEYWORD = FORMATTEDVALUE = JOINEDSTR = handleChildren
+
+    def DICT(self, node):
+        # Complain if there are duplicate keys with different values
+        # If they have the same value it's not going to cause potentially
+        # unexpected behaviour so we'll not complain.
+        keys = [
+            convert_to_value(key) for key in node.keys
+        ]
+
+        key_counts = counter(keys)
+        duplicate_keys = [
+            key for key, count in key_counts.items()
+            if count > 1
+        ]
+
+        for key in duplicate_keys:
+            key_indices = [i for i, i_key in enumerate(keys) if i_key == key]
+
+            values = counter(
+                convert_to_value(node.values[index])
+                for index in key_indices
+            )
+            if any(count == 1 for value, count in values.items()):
+                for key_index in key_indices:
+                    key_node = node.keys[key_index]
+                    if isinstance(key, VariableKey):
+                        self.report(messages.MultiValueRepeatedKeyVariable,
+                                    key_node,
+                                    key.name)
+                    else:
+                        self.report(
+                            messages.MultiValueRepeatedKeyLiteral,
+                            key_node,
+                            key,
+                        )
+        self.handleChildren(node)
+
+    def ASSERT(self, node):
+        if isinstance(node.test, ast.Tuple) and node.test.elts != []:
+            self.report(messages.AssertTuple, node)
+        self.handleChildren(node)
 
     def GLOBAL(self, node):
         """
         Keep track of globals declarations.
         """
-        if isinstance(self.scope, FunctionScope):
-            self.scope.globals.update(node.names)
+        global_scope_index = 1 if self._in_doctest() else 0
+        global_scope = self.scopeStack[global_scope_index]
+
+        # Ignore 'global' statement in global scope.
+        if self.scope is not global_scope:
+
+            # One 'global' statement can bind multiple (comma-delimited) names.
+            for node_name in node.names:
+                node_value = Assignment(node_name, node)
+
+                # Remove UndefinedName messages already reported for this name.
+                # TODO: if the global is not used in this scope, it does not
+                # become a globally defined name.  See test_unused_global.
+                self.messages = [
+                    m for m in self.messages if not
+                    isinstance(m, messages.UndefinedName) or
+                    m.message_args[0] != node_name]
+
+                # Bind name to global scope if it doesn't exist already.
+                global_scope.setdefault(node_name, node_value)
+
+                # Bind name to non-global scopes, but as already "used".
+                node_value.used = (global_scope, node)
+                for scope in self.scopeStack[global_scope_index + 1:]:
+                    scope[node_name] = node_value
 
     NONLOCAL = GLOBAL
 
-    def LISTCOMP(self, node):
-        # handle generators before element
-        for gen in node.generators:
-            self.handleNode(gen, node)
-        self.handleNode(node.elt, node)
-
     def GENERATOREXP(self, node):
         self.pushScope(GeneratorScope)
-        # handle generators before element
-        for gen in node.generators:
-            self.handleNode(gen, node)
-        self.handleNode(node.elt, node)
-        self.popScope()
-
-    SETCOMP = GENERATOREXP
-
-    def DICTCOMP(self, node):
-        self.pushScope(GeneratorScope)
-        for gen in node.generators:
-            self.handleNode(gen, node)
-        self.handleNode(node.key, node)
-        self.handleNode(node.value, node)
+        self.handleChildren(node)
         self.popScope()
 
-    def FOR(self, node):
-        """
-        Process bindings for loop variables.
-        """
-        vars = []
+    LISTCOMP = handleChildren if PY2 else GENERATOREXP
 
-        def collectLoopVars(n):
-            if isinstance(n, ast.Name):
-                vars.append(n.id)
-            elif isinstance(n, ast.expr_context):
-                return
-            else:
-                for c in iter_child_nodes(n):
-                    collectLoopVars(c)
-
-        collectLoopVars(node.target)
-        for varn in vars:
-            if (isinstance(self.scope.get(varn), Importation)
-                    # unused ones will get an unused import warning
-                    and self.scope[varn].used):
-                self.report(messages.ImportShadowedByLoopVar,
-                            node, varn, self.scope[varn].source)
-
-        self.handleChildren(node)
+    DICTCOMP = SETCOMP = GENERATOREXP
 
     def NAME(self, node):
         """
         Handle occurrence of Name (which can be a load/store/delete access.)
         """
         # Locate the name in locals / function / globals scopes.
         if isinstance(node.ctx, (ast.Load, ast.AugLoad)):
             self.handleNodeLoad(node)
@@ -690,82 +1036,155 @@ class Checker(object):
             self.handleNodeStore(node)
         elif isinstance(node.ctx, ast.Del):
             self.handleNodeDelete(node)
         else:
             # must be a Param context -- this only happens for names in function
             # arguments, but these aren't dispatched through here
             raise RuntimeError("Got impossible expression context: %r" % (node.ctx,))
 
+    def CONTINUE(self, node):
+        # Walk the tree up until we see a loop (OK), a function or class
+        # definition (not OK), for 'continue', a finally block (not OK), or
+        # the top module scope (not OK)
+        n = node
+        while hasattr(n, 'parent'):
+            n, n_child = n.parent, n
+            if isinstance(n, LOOP_TYPES):
+                # Doesn't apply unless it's in the loop itself
+                if n_child not in n.orelse:
+                    return
+            if isinstance(n, (ast.FunctionDef, ast.ClassDef)):
+                break
+            # Handle Try/TryFinally difference in Python < and >= 3.3
+            if hasattr(n, 'finalbody') and isinstance(node, ast.Continue):
+                if n_child in n.finalbody:
+                    self.report(messages.ContinueInFinally, node)
+                    return
+        if isinstance(node, ast.Continue):
+            self.report(messages.ContinueOutsideLoop, node)
+        else:  # ast.Break
+            self.report(messages.BreakOutsideLoop, node)
+
+    BREAK = CONTINUE
+
+    def RETURN(self, node):
+        if isinstance(self.scope, (ClassScope, ModuleScope)):
+            self.report(messages.ReturnOutsideFunction, node)
+            return
+
+        if (
+            node.value and
+            hasattr(self.scope, 'returnValue') and
+            not self.scope.returnValue
+        ):
+            self.scope.returnValue = node.value
+        self.handleNode(node.value, node)
+
+    def YIELD(self, node):
+        if isinstance(self.scope, (ClassScope, ModuleScope)):
+            self.report(messages.YieldOutsideFunction, node)
+            return
+
+        self.scope.isGenerator = True
+        self.handleNode(node.value, node)
+
+    AWAIT = YIELDFROM = YIELD
+
     def FUNCTIONDEF(self, node):
         for deco in node.decorator_list:
             self.handleNode(deco, node)
+        self.LAMBDA(node)
         self.addBinding(node, FunctionDefinition(node.name, node))
-        self.LAMBDA(node)
-        if self.withDoctest:
+        # doctest does not process doctest within a doctest,
+        # or in nested functions.
+        if (self.withDoctest and
+                not self._in_doctest() and
+                not isinstance(self.scope, FunctionScope)):
             self.deferFunction(lambda: self.handleDoctests(node))
 
+    ASYNCFUNCTIONDEF = FUNCTIONDEF
+
     def LAMBDA(self, node):
         args = []
+        annotations = []
 
         if PY2:
             def addArgs(arglist):
                 for arg in arglist:
                     if isinstance(arg, ast.Tuple):
                         addArgs(arg.elts)
                     else:
-                        if arg.id in args:
-                            self.report(messages.DuplicateArgument,
-                                        node, arg.id)
                         args.append(arg.id)
             addArgs(node.args.args)
             defaults = node.args.defaults
         else:
             for arg in node.args.args + node.args.kwonlyargs:
-                if arg.arg in args:
-                    self.report(messages.DuplicateArgument,
-                                node, arg.arg)
                 args.append(arg.arg)
-                self.handleNode(arg.annotation, node)
-            if hasattr(node, 'returns'):    # Only for FunctionDefs
-                for annotation in (node.args.varargannotation,
-                                   node.args.kwargannotation, node.returns):
-                    self.handleNode(annotation, node)
+                annotations.append(arg.annotation)
             defaults = node.args.defaults + node.args.kw_defaults
 
-        # vararg/kwarg identifiers are not Name nodes
-        for wildcard in (node.args.vararg, node.args.kwarg):
+        # Only for Python3 FunctionDefs
+        is_py3_func = hasattr(node, 'returns')
+
+        for arg_name in ('vararg', 'kwarg'):
+            wildcard = getattr(node.args, arg_name)
             if not wildcard:
                 continue
-            if wildcard in args:
-                self.report(messages.DuplicateArgument, node, wildcard)
-            args.append(wildcard)
-        for default in defaults:
-            self.handleNode(default, node)
+            args.append(wildcard if PY33 else wildcard.arg)
+            if is_py3_func:
+                if PY33:  # Python 2.5 to 3.3
+                    argannotation = arg_name + 'annotation'
+                    annotations.append(getattr(node.args, argannotation))
+                else:     # Python >= 3.4
+                    annotations.append(wildcard.annotation)
+
+        if is_py3_func:
+            annotations.append(node.returns)
+
+        if len(set(args)) < len(args):
+            for (idx, arg) in enumerate(args):
+                if arg in args[:idx]:
+                    self.report(messages.DuplicateArgument, node, arg)
+
+        for child in annotations + defaults:
+            if child:
+                self.handleNode(child, node)
 
         def runFunction():
 
             self.pushScope()
             for name in args:
-                self.addBinding(node, Argument(name, node), reportRedef=False)
+                self.addBinding(node, Argument(name, node))
             if isinstance(node.body, list):
                 # case for FunctionDefs
                 for stmt in node.body:
                     self.handleNode(stmt, node)
             else:
                 # case for Lambdas
                 self.handleNode(node.body, node)
 
             def checkUnusedAssignments():
                 """
                 Check to see if any assignments have not been used.
                 """
                 for name, binding in self.scope.unusedAssignments():
                     self.report(messages.UnusedVariable, binding.source, name)
             self.deferAssignment(checkUnusedAssignments)
+
+            if PY32:
+                def checkReturnWithArgumentInsideGenerator():
+                    """
+                    Check to see if there is any return statement with
+                    arguments but the function is a generator.
+                    """
+                    if self.scope.isGenerator and self.scope.returnValue:
+                        self.report(messages.ReturnWithArgsInsideGenerator,
+                                    self.scope.returnValue)
+                self.deferAssignment(checkReturnWithArgumentInsideGenerator)
             self.popScope()
 
         self.deferFunction(runFunction)
 
     def CLASSDEF(self, node):
         """
         Check names used in a class definition, including its decorators, base
         classes, and the body of its definition.  Additionally, add its name to
@@ -774,77 +1193,163 @@ class Checker(object):
         for deco in node.decorator_list:
             self.handleNode(deco, node)
         for baseNode in node.bases:
             self.handleNode(baseNode, node)
         if not PY2:
             for keywordNode in node.keywords:
                 self.handleNode(keywordNode, node)
         self.pushScope(ClassScope)
-        if self.withDoctest:
+        # doctest does not process doctest within a doctest
+        # classes within classes are processed.
+        if (self.withDoctest and
+                not self._in_doctest() and
+                not isinstance(self.scope, FunctionScope)):
             self.deferFunction(lambda: self.handleDoctests(node))
         for stmt in node.body:
             self.handleNode(stmt, node)
         self.popScope()
         self.addBinding(node, ClassDefinition(node.name, node))
 
-    def ASSIGN(self, node):
-        self.handleNode(node.value, node)
-        for target in node.targets:
-            self.handleNode(target, node)
-
     def AUGASSIGN(self, node):
         self.handleNodeLoad(node.target)
         self.handleNode(node.value, node)
         self.handleNode(node.target, node)
 
+    def TUPLE(self, node):
+        if not PY2 and isinstance(node.ctx, ast.Store):
+            # Python 3 advanced tuple unpacking: a, *b, c = d.
+            # Only one starred expression is allowed, and no more than 1<<8
+            # assignments are allowed before a stared expression. There is
+            # also a limit of 1<<24 expressions after the starred expression,
+            # which is impossible to test due to memory restrictions, but we
+            # add it here anyway
+            has_starred = False
+            star_loc = -1
+            for i, n in enumerate(node.elts):
+                if isinstance(n, ast.Starred):
+                    if has_starred:
+                        self.report(messages.TwoStarredExpressions, node)
+                        # The SyntaxError doesn't distinguish two from more
+                        # than two.
+                        break
+                    has_starred = True
+                    star_loc = i
+            if star_loc >= 1 << 8 or len(node.elts) - star_loc - 1 >= 1 << 24:
+                self.report(messages.TooManyExpressionsInStarredAssignment, node)
+        self.handleChildren(node)
+
+    LIST = TUPLE
+
     def IMPORT(self, node):
         for alias in node.names:
-            name = alias.asname or alias.name
-            importation = Importation(name, node)
+            if '.' in alias.name and not alias.asname:
+                importation = SubmoduleImportation(alias.name, node)
+            else:
+                name = alias.asname or alias.name
+                importation = Importation(name, node, alias.name)
             self.addBinding(node, importation)
 
     def IMPORTFROM(self, node):
         if node.module == '__future__':
             if not self.futuresAllowed:
                 self.report(messages.LateFutureImport,
                             node, [n.name for n in node.names])
         else:
             self.futuresAllowed = False
 
+        module = ('.' * node.level) + (node.module or '')
+
         for alias in node.names:
-            if alias.name == '*':
+            name = alias.asname or alias.name
+            if node.module == '__future__':
+                importation = FutureImportation(name, node, self.scope)
+                if alias.name not in __future__.all_feature_names:
+                    self.report(messages.FutureFeatureNotDefined,
+                                node, alias.name)
+            elif alias.name == '*':
+                # Only Python 2, local import * is a SyntaxWarning
+                if not PY2 and not isinstance(self.scope, ModuleScope):
+                    self.report(messages.ImportStarNotPermitted,
+                                node, module)
+                    continue
+
                 self.scope.importStarred = True
-                self.report(messages.ImportStarUsed, node, node.module)
-                continue
-            name = alias.asname or alias.name
-            importation = Importation(name, node)
-            if node.module == '__future__':
-                importation.used = (self.scope, node)
+                self.report(messages.ImportStarUsed, node, module)
+                importation = StarImportation(module, node)
+            else:
+                importation = ImportationFrom(name, node,
+                                              module, alias.name)
             self.addBinding(node, importation)
 
     def TRY(self, node):
         handler_names = []
         # List the exception handlers
-        for handler in node.handlers:
+        for i, handler in enumerate(node.handlers):
             if isinstance(handler.type, ast.Tuple):
                 for exc_type in handler.type.elts:
                     handler_names.append(getNodeName(exc_type))
             elif handler.type:
                 handler_names.append(getNodeName(handler.type))
+
+            if handler.type is None and i < len(node.handlers) - 1:
+                self.report(messages.DefaultExceptNotLast, handler)
         # Memorize the except handlers and process the body
         self.exceptHandlers.append(handler_names)
         for child in node.body:
             self.handleNode(child, node)
         self.exceptHandlers.pop()
         # Process the other nodes: "except:", "else:", "finally:"
-        for child in iter_child_nodes(node):
-            if child not in node.body:
-                self.handleNode(child, node)
+        self.handleChildren(node, omit='body')
 
     TRYEXCEPT = TRY
 
     def EXCEPTHANDLER(self, node):
-        # 3.x: in addition to handling children, we must handle the name of
-        # the exception, which is not a Name node, but a simple string.
-        if isinstance(node.name, str):
-            self.handleNodeStore(node)
+        if PY2 or node.name is None:
+            self.handleChildren(node)
+            return
+
+        # 3.x: the name of the exception, which is not a Name node, but
+        # a simple string, creates a local that is only bound within the scope
+        # of the except: block.
+
+        for scope in self.scopeStack[::-1]:
+            if node.name in scope:
+                is_name_previously_defined = True
+                break
+        else:
+            is_name_previously_defined = False
+
+        self.handleNodeStore(node)
         self.handleChildren(node)
+        if not is_name_previously_defined:
+            # See discussion on https://github.com/PyCQA/pyflakes/pull/59
+
+            # We're removing the local name since it's being unbound
+            # after leaving the except: block and it's always unbound
+            # if the except: block is never entered. This will cause an
+            # "undefined name" error raised if the checked code tries to
+            # use the name afterwards.
+            #
+            # Unless it's been removed already. Then do nothing.
+
+            try:
+                del self.scope[node.name]
+            except KeyError:
+                pass
+
+    def ANNASSIGN(self, node):
+        """
+        Annotated assignments don't have annotations evaluated on function
+        scope, hence the custom implementation.
+
+        See: PEP 526.
+        """
+        if node.value:
+            # Only bind the *targets* if the assignment has a value.
+            # Otherwise it's not really ast.Store and shouldn't silence
+            # UndefinedLocal warnings.
+            self.handleNode(node.target, node)
+        if not isinstance(self.scope, FunctionScope):
+            self.handleNode(node.annotation, node)
+        if node.value:
+            # If the assignment has value, handle the *value* now.
+            self.handleNode(node.value, node)
--- a/pylib/pyflakes/pyflakes/messages.py
+++ b/pylib/pyflakes/pyflakes/messages.py
@@ -44,24 +44,40 @@ class RedefinedInListComp(Message):
 class ImportShadowedByLoopVar(Message):
     message = 'import %r from line %r shadowed by loop variable'
 
     def __init__(self, filename, loc, name, orig_loc):
         Message.__init__(self, filename, loc)
         self.message_args = (name, orig_loc.lineno)
 
 
+class ImportStarNotPermitted(Message):
+    message = "'from %s import *' only allowed at module level"
+
+    def __init__(self, filename, loc, modname):
+        Message.__init__(self, filename, loc)
+        self.message_args = (modname,)
+
+
 class ImportStarUsed(Message):
     message = "'from %s import *' used; unable to detect undefined names"
 
     def __init__(self, filename, loc, modname):
         Message.__init__(self, filename, loc)
         self.message_args = (modname,)
 
 
+class ImportStarUsage(Message):
+    message = "%r may be undefined, or defined from star imports: %s"
+
+    def __init__(self, filename, loc, name, from_list):
+        Message.__init__(self, filename, loc)
+        self.message_args = (name, from_list)
+
+
 class UndefinedName(Message):
     message = 'undefined name %r'
 
     def __init__(self, filename, loc, name):
         Message.__init__(self, filename, loc)
         self.message_args = (name,)
 
 
@@ -95,34 +111,123 @@ class UndefinedLocal(Message):
 class DuplicateArgument(Message):
     message = 'duplicate argument %r in function definition'
 
     def __init__(self, filename, loc, name):
         Message.__init__(self, filename, loc)
         self.message_args = (name,)
 
 
-class Redefined(Message):
-    message = 'redefinition of %r from line %r'
+class MultiValueRepeatedKeyLiteral(Message):
+    message = 'dictionary key %r repeated with different values'
+
+    def __init__(self, filename, loc, key):
+        Message.__init__(self, filename, loc)
+        self.message_args = (key,)
 
-    def __init__(self, filename, loc, name, orig_loc):
+
+class MultiValueRepeatedKeyVariable(Message):
+    message = 'dictionary key variable %s repeated with different values'
+
+    def __init__(self, filename, loc, key):
         Message.__init__(self, filename, loc)
-        self.message_args = (name, orig_loc.lineno)
+        self.message_args = (key,)
 
 
 class LateFutureImport(Message):
-    message = 'future import(s) %r after other statements'
+    message = 'from __future__ imports must occur at the beginning of the file'
 
     def __init__(self, filename, loc, names):
         Message.__init__(self, filename, loc)
-        self.message_args = (names,)
+        self.message_args = ()
+
+
+class FutureFeatureNotDefined(Message):
+    """An undefined __future__ feature name was imported."""
+    message = 'future feature %s is not defined'
+
+    def __init__(self, filename, loc, name):
+        Message.__init__(self, filename, loc)
+        self.message_args = (name,)
 
 
 class UnusedVariable(Message):
     """
-    Indicates that a variable has been explicity assigned to but not actually
+    Indicates that a variable has been explicitly assigned to but not actually
     used.
     """
     message = 'local variable %r is assigned to but never used'
 
     def __init__(self, filename, loc, names):
         Message.__init__(self, filename, loc)
         self.message_args = (names,)
+
+
+class ReturnWithArgsInsideGenerator(Message):
+    """
+    Indicates a return statement with arguments inside a generator.
+    """
+    message = '\'return\' with argument inside generator'
+
+
+class ReturnOutsideFunction(Message):
+    """
+    Indicates a return statement outside of a function/method.
+    """
+    message = '\'return\' outside function'
+
+
+class YieldOutsideFunction(Message):
+    """
+    Indicates a yield or yield from statement outside of a function/method.
+    """
+    message = '\'yield\' outside function'
+
+
+# For whatever reason, Python gives different error messages for these two. We
+# match the Python error message exactly.
+class ContinueOutsideLoop(Message):
+    """
+    Indicates a continue statement outside of a while or for loop.
+    """
+    message = '\'continue\' not properly in loop'
+
+
+class BreakOutsideLoop(Message):
+    """
+    Indicates a break statement outside of a while or for loop.
+    """
+    message = '\'break\' outside loop'
+
+
+class ContinueInFinally(Message):
+    """
+    Indicates a continue statement in a finally block in a while or for loop.
+    """
+    message = '\'continue\' not supported inside \'finally\' clause'
+
+
+class DefaultExceptNotLast(Message):
+    """
+    Indicates an except: block as not the last exception handler.
+    """
+    message = 'default \'except:\' must be last'
+
+
+class TwoStarredExpressions(Message):
+    """
+    Two or more starred expressions in an assignment (a, *b, *c = d).
+    """
+    message = 'two starred expressions in assignment'
+
+
+class TooManyExpressionsInStarredAssignment(Message):
+    """
+    Too many expressions in an assignment with star-unpacking
+    """
+    message = 'too many expressions in star-unpacking assignment'
+
+
+class AssertTuple(Message):
+    """
+    Assertion test is a tuple, which are always True.
+    """
+    message = 'assertion is always true, perhaps remove parentheses?'
--- a/pylib/pyflakes/pyflakes/reporter.py
+++ b/pylib/pyflakes/pyflakes/reporter.py
@@ -1,12 +1,13 @@
 """
 Provide the Reporter class.
 """
 
+import re
 import sys
 
 
 class Reporter(object):
     """
     Formats the results of pyflakes checks to users.
     """
 
@@ -32,37 +33,41 @@ class Reporter(object):
         @ptype filename: C{unicode}
         @param msg: A message explaining the problem.
         @ptype msg: C{unicode}
         """
         self._stderr.write("%s: %s\n" % (filename, msg))
 
     def syntaxError(self, filename, msg, lineno, offset, text):
         """
-        There was a syntax errror in C{filename}.
+        There was a syntax error in C{filename}.
 
         @param filename: The path to the file with the syntax error.
         @ptype filename: C{unicode}
         @param msg: An explanation of the syntax error.
         @ptype msg: C{unicode}
         @param lineno: The line number where the syntax error occurred.
         @ptype lineno: C{int}
-        @param offset: The column on which the syntax error occurred.
+        @param offset: The column on which the syntax error occurred, or None.
         @ptype offset: C{int}
         @param text: The source code containing the syntax error.
         @ptype text: C{unicode}
         """
         line = text.splitlines()[-1]
         if offset is not None:
             offset = offset - (len(text) - len(line))
-        self._stderr.write('%s:%d: %s\n' % (filename, lineno, msg))
+            self._stderr.write('%s:%d:%d: %s\n' %
+                               (filename, lineno, offset + 1, msg))
+        else:
+            self._stderr.write('%s:%d: %s\n' % (filename, lineno, msg))
         self._stderr.write(line)
         self._stderr.write('\n')
         if offset is not None:
-            self._stderr.write(" " * (offset + 1) + "^\n")
+            self._stderr.write(re.sub(r'\S', ' ', line[:offset]) +
+                               "^\n")
 
     def flake(self, message):
         """
         pyflakes found something wrong with the code.
 
         @param: A L{pyflakes.messages.Message}.
         """
         self._stdout.write(str(message))
--- a/pylib/pyflakes/pyflakes/scripts/pyflakes.py
+++ b/pylib/pyflakes/pyflakes/scripts/pyflakes.py
@@ -1,7 +1,8 @@
 """
 Implementation of the command-line I{pyflakes} tool.
 """
 from __future__ import absolute_import
 
 # For backward compatibility
+__all__ = ['check', 'checkPath', 'checkRecursive', 'iterSourceCode', 'main']
 from pyflakes.api import check, checkPath, checkRecursive, iterSourceCode, main
--- a/pylib/pyflakes/pyflakes/test/harness.py
+++ b/pylib/pyflakes/pyflakes/test/harness.py
@@ -13,29 +13,60 @@ if sys.version_info < (2, 7):
 else:
     skip = unittest.skip
     skipIf = unittest.skipIf
 PyCF_ONLY_AST = 1024
 
 
 class TestCase(unittest.TestCase):
 
+    withDoctest = False
+
     def flakes(self, input, *expectedOutputs, **kw):
         tree = compile(textwrap.dedent(input), "<test>", "exec", PyCF_ONLY_AST)
-        w = checker.Checker(tree, **kw)
+        w = checker.Checker(tree, withDoctest=self.withDoctest, **kw)
         outputs = [type(o) for o in w.messages]
         expectedOutputs = list(expectedOutputs)
         outputs.sort(key=lambda t: t.__name__)
         expectedOutputs.sort(key=lambda t: t.__name__)
         self.assertEqual(outputs, expectedOutputs, '''\
 for input:
 %s
 expected outputs:
 %r
 but got:
 %s''' % (input, expectedOutputs, '\n'.join([str(o) for o in w.messages])))
         return w
 
-    if sys.version_info < (2, 7):
+    if not hasattr(unittest.TestCase, 'assertIs'):
 
         def assertIs(self, expr1, expr2, msg=None):
             if expr1 is not expr2:
                 self.fail(msg or '%r is not %r' % (expr1, expr2))
+
+    if not hasattr(unittest.TestCase, 'assertIsInstance'):
+
+        def assertIsInstance(self, obj, cls, msg=None):
+            """Same as self.assertTrue(isinstance(obj, cls))."""
+            if not isinstance(obj, cls):
+                self.fail(msg or '%r is not an instance of %r' % (obj, cls))
+
+    if not hasattr(unittest.TestCase, 'assertNotIsInstance'):
+
+        def assertNotIsInstance(self, obj, cls, msg=None):
+            """Same as self.assertFalse(isinstance(obj, cls))."""
+            if isinstance(obj, cls):
+                self.fail(msg or '%r is an instance of %r' % (obj, cls))
+
+    if not hasattr(unittest.TestCase, 'assertIn'):
+
+        def assertIn(self, member, container, msg=None):
+            """Just like self.assertTrue(a in b)."""
+            if member not in container:
+                self.fail(msg or '%r not found in %r' % (member, container))
+
+    if not hasattr(unittest.TestCase, 'assertNotIn'):
+
+        def assertNotIn(self, member, container, msg=None):
+            """Just like self.assertTrue(a not in b)."""
+            if member in container:
+                self.fail(msg or
+                          '%r unexpectedly found in %r' % (member, container))
--- a/pylib/pyflakes/pyflakes/test/test_api.py
+++ b/pylib/pyflakes/pyflakes/test/test_api.py
@@ -3,31 +3,47 @@ Tests for L{pyflakes.scripts.pyflakes}.
 """
 
 import os
 import sys
 import shutil
 import subprocess
 import tempfile
 
+from pyflakes.checker import PY2
 from pyflakes.messages import UnusedImport
 from pyflakes.reporter import Reporter
 from pyflakes.api import (
+    main,
     checkPath,
     checkRecursive,
     iterSourceCode,
 )
 from pyflakes.test.harness import TestCase, skipIf
 
 if sys.version_info < (3,):
     from cStringIO import StringIO
 else:
     from io import StringIO
     unichr = chr
 
+try:
+    sys.pypy_version_info
+    PYPY = True
+except AttributeError:
+    PYPY = False
+
+try:
+    WindowsError
+    WIN = True
+except NameError:
+    WIN = False
+
+ERROR_HAS_COL_NUM = ERROR_HAS_LAST_LINE = sys.version_info >= (3, 2) or PYPY
+
 
 def withStderrTo(stderr, f, *args, **kwargs):
     """
     Call C{f} with C{sys.stderr} redirected to C{stderr}.
     """
     (outer, sys.stderr) = (sys.stderr, stderr)
     try:
         return f(*args, **kwargs)
@@ -39,16 +55,67 @@ class Node(object):
     """
     Mock an AST node.
     """
     def __init__(self, lineno, col_offset=0):
         self.lineno = lineno
         self.col_offset = col_offset
 
 
+class SysStreamCapturing(object):
+
+    """
+    Context manager capturing sys.stdin, sys.stdout and sys.stderr.
+
+    The file handles are replaced with a StringIO object.
+    On environments that support it, the StringIO object uses newlines
+    set to os.linesep.  Otherwise newlines are converted from \\n to
+    os.linesep during __exit__.
+    """
+
+    def _create_StringIO(self, buffer=None):
+        # Python 3 has a newline argument
+        try:
+            return StringIO(buffer, newline=os.linesep)
+        except TypeError:
+            self._newline = True
+            # Python 2 creates an input only stream when buffer is not None
+            if buffer is None:
+                return StringIO()
+            else:
+                return StringIO(buffer)
+
+    def __init__(self, stdin):
+        self._newline = False
+        self._stdin = self._create_StringIO(stdin or '')
+
+    def __enter__(self):
+        self._orig_stdin = sys.stdin
+        self._orig_stdout = sys.stdout
+        self._orig_stderr = sys.stderr
+
+        sys.stdin = self._stdin
+        sys.stdout = self._stdout_stringio = self._create_StringIO()
+        sys.stderr = self._stderr_stringio = self._create_StringIO()
+
+        return self
+
+    def __exit__(self, *args):
+        self.output = self._stdout_stringio.getvalue()
+        self.error = self._stderr_stringio.getvalue()
+
+        if self._newline and os.linesep != '\n':
+            self.output = self.output.replace('\n', os.linesep)
+            self.error = self.error.replace('\n', os.linesep)
+
+        sys.stdin = self._orig_stdin
+        sys.stdout = self._orig_stdout
+        sys.stderr = self._orig_stderr
+
+
 class LoggingReporter(object):
     """
     Implementation of Reporter that just appends any error to a list.
     """
 
     def __init__(self, log):
         """
         Construct a C{LoggingReporter}.
@@ -154,21 +221,21 @@ class TestReporter(TestCase):
         """
         C{syntaxError} reports that there was a syntax error in the source
         file.  It reports to the error stream and includes the filename, line
         number, error message, actual line of source and a caret pointing to
         where the error is.
         """
         err = StringIO()
         reporter = Reporter(None, err)
-        reporter.syntaxError('foo.py', 'a problem', 3, 4, 'bad line of source')
+        reporter.syntaxError('foo.py', 'a problem', 3, 7, 'bad line of source')
         self.assertEqual(
-            ("foo.py:3: a problem\n"
+            ("foo.py:3:8: a problem\n"
              "bad line of source\n"
-             "     ^\n"),
+             "       ^\n"),
             err.getvalue())
 
     def test_syntaxErrorNoOffset(self):
         """
         C{syntaxError} doesn't include a caret pointing to the error if
         C{offset} is passed as C{None}.
         """
         err = StringIO()
@@ -187,22 +254,22 @@ class TestReporter(TestCase):
         the last line.
         """
         err = StringIO()
         lines = [
             'bad line of source',
             'more bad lines of source',
         ]
         reporter = Reporter(None, err)
-        reporter.syntaxError('foo.py', 'a problem', 3, len(lines[0]) + 5,
+        reporter.syntaxError('foo.py', 'a problem', 3, len(lines[0]) + 7,
                              '\n'.join(lines))
         self.assertEqual(
-            ("foo.py:3: a problem\n" +
+            ("foo.py:3:7: a problem\n" +
              lines[-1] + "\n" +
-             "     ^\n"),
+             "      ^\n"),
             err.getvalue())
 
     def test_unexpectedError(self):
         """
         C{unexpectedError} reports an error processing a source file.
         """
         err = StringIO()
         reporter = Reporter(None, err)
@@ -307,101 +374,150 @@ def baz():
         # Sanity check - SyntaxError.text should be multiple lines, if it
         # isn't, something this test was unprepared for has happened.
         def evaluate(source):
             exec(source)
         try:
             evaluate(source)
         except SyntaxError:
             e = sys.exc_info()[1]
-            self.assertTrue(e.text.count('\n') > 1)
+            if not PYPY:
+                self.assertTrue(e.text.count('\n') > 1)
         else:
             self.fail()
 
         sourcePath = self.makeTempFile(source)
+
+        if PYPY:
+            message = 'EOF while scanning triple-quoted string literal'
+        else:
+            message = 'invalid syntax'
+
         self.assertHasErrors(
             sourcePath,
             ["""\
-%s:8: invalid syntax
+%s:8:11: %s
     '''quux'''
-           ^
-""" % (sourcePath,)])
+          ^
+""" % (sourcePath, message)])
 
     def test_eofSyntaxError(self):
         """
         The error reported for source files which end prematurely causing a
         syntax error reflects the cause for the syntax error.
         """
         sourcePath = self.makeTempFile("def foo(")
+        if PYPY:
+            result = """\
+%s:1:7: parenthesis is never closed
+def foo(
+      ^
+""" % (sourcePath,)
+        else:
+            result = """\
+%s:1:9: unexpected EOF while parsing
+def foo(
+        ^
+""" % (sourcePath,)
+
+        self.assertHasErrors(
+            sourcePath,
+            [result])
+
+    def test_eofSyntaxErrorWithTab(self):
+        """
+        The error reported for source files which end prematurely causing a
+        syntax error reflects the cause for the syntax error.
+        """
+        sourcePath = self.makeTempFile("if True:\n\tfoo =")
+        column = 5 if PYPY else 7
+        last_line = '\t   ^' if PYPY else '\t     ^'
+
         self.assertHasErrors(
             sourcePath,
             ["""\
-%s:1: unexpected EOF while parsing
-def foo(
-         ^
-""" % (sourcePath,)])
+%s:2:%s: invalid syntax
+\tfoo =
+%s
+""" % (sourcePath, column, last_line)])
 
     def test_nonDefaultFollowsDefaultSyntaxError(self):
         """
         Source which has a non-default argument following a default argument
         should include the line number of the syntax error.  However these
         exceptions do not include an offset.
         """
         source = """\
 def foo(bar=baz, bax):
     pass
 """
         sourcePath = self.makeTempFile(source)
-        last_line = '        ^\n' if sys.version_info >= (3, 2) else ''
+        last_line = '       ^\n' if ERROR_HAS_LAST_LINE else ''
+        column = '8:' if ERROR_HAS_COL_NUM else ''
         self.assertHasErrors(
             sourcePath,
             ["""\
-%s:1: non-default argument follows default argument
+%s:1:%s non-default argument follows default argument
 def foo(bar=baz, bax):
-%s""" % (sourcePath, last_line)])
+%s""" % (sourcePath, column, last_line)])
 
     def test_nonKeywordAfterKeywordSyntaxError(self):
         """
         Source which has a non-keyword argument after a keyword argument should
         include the line number of the syntax error.  However these exceptions
         do not include an offset.
         """
         source = """\
 foo(bar=baz, bax)
 """
         sourcePath = self.makeTempFile(source)
-        last_line = '             ^\n' if sys.version_info >= (3, 2) else ''
+        last_line = '            ^\n' if ERROR_HAS_LAST_LINE else ''
+        column = '13:' if ERROR_HAS_COL_NUM or PYPY else ''
+
+        if sys.version_info >= (3, 5):
+            message = 'positional argument follows keyword argument'
+        else:
+            message = 'non-keyword arg after keyword arg'
+
         self.assertHasErrors(
             sourcePath,
             ["""\
-%s:1: non-keyword arg after keyword arg
+%s:1:%s %s
 foo(bar=baz, bax)
-%s""" % (sourcePath, last_line)])
+%s""" % (sourcePath, column, message, last_line)])
 
     def test_invalidEscape(self):
         """
         The invalid escape syntax raises ValueError in Python 2
         """
         ver = sys.version_info
         # ValueError: invalid \x escape
         sourcePath = self.makeTempFile(r"foo = '\xyz'")
         if ver < (3,):
             decoding_error = "%s: problem decoding source\n" % (sourcePath,)
+        elif PYPY:
+            # pypy3 only
+            decoding_error = """\
+%s:1:6: %s: ('unicodeescape', b'\\\\xyz', 0, 2, 'truncated \\\\xXX escape')
+foo = '\\xyz'
+     ^
+""" % (sourcePath, 'UnicodeDecodeError')
         else:
-            last_line = '       ^\n' if ver >= (3, 2) else ''
+            last_line = '      ^\n' if ERROR_HAS_LAST_LINE else ''
             # Column has been "fixed" since 3.2.4 and 3.3.1
             col = 1 if ver >= (3, 3, 1) or ((3, 2, 4) <= ver < (3, 3)) else 2
             decoding_error = """\
-%s:1: (unicode error) 'unicodeescape' codec can't decode bytes \
+%s:1:7: (unicode error) 'unicodeescape' codec can't decode bytes \
 in position 0-%d: truncated \\xXX escape
 foo = '\\xyz'
 %s""" % (sourcePath, col, last_line)
         self.assertHasErrors(
             sourcePath, [decoding_error])
 
+    @skipIf(sys.platform == 'win32', 'unsupported on Windows')
     def test_permissionDenied(self):
         """
         If the source file is not readable, this is reported on standard
         error.
         """
         sourcePath = self.makeTempFile('')
         os.chmod(sourcePath, 0)
         count, errors = self.getErrors(sourcePath)
@@ -416,30 +532,61 @@ foo = '\\xyz'
         'flake'.
         """
         sourcePath = self.makeTempFile("import foo")
         count, errors = self.getErrors(sourcePath)
         self.assertEqual(count, 1)
         self.assertEqual(
             errors, [('flake', str(UnusedImport(sourcePath, Node(1), 'foo')))])
 
-    @skipIf(sys.version_info >= (3,), "not relevant")
+    def test_encodedFileUTF8(self):
+        """
+        If source file declares the correct encoding, no error is reported.
+        """
+        SNOWMAN = unichr(0x2603)
+        source = ("""\
+# coding: utf-8
+x = "%s"
+""" % SNOWMAN).encode('utf-8')
+        sourcePath = self.makeTempFile(source)
+        self.assertHasErrors(sourcePath, [])
+
+    def test_CRLFLineEndings(self):
+        """
+        Source files with Windows CR LF line endings are parsed successfully.
+        """
+        sourcePath = self.makeTempFile("x = 42\r\n")
+        self.assertHasErrors(sourcePath, [])
+
     def test_misencodedFileUTF8(self):
         """
         If a source file contains bytes which cannot be decoded, this is
         reported on stderr.
         """
         SNOWMAN = unichr(0x2603)
         source = ("""\
 # coding: ascii
 x = "%s"
 """ % SNOWMAN).encode('utf-8')
         sourcePath = self.makeTempFile(source)
+
+        if PYPY and sys.version_info < (3, ):
+            message = ('\'ascii\' codec can\'t decode byte 0xe2 '
+                       'in position 21: ordinal not in range(128)')
+            result = """\
+%s:0:0: %s
+x = "\xe2\x98\x83"
+        ^\n""" % (sourcePath, message)
+
+        else:
+            message = 'problem decoding source'
+            result = "%s: problem decoding source\n" % (sourcePath,)
+
         self.assertHasErrors(
-            sourcePath, ["%s: problem decoding source\n" % (sourcePath,)])
+            sourcePath, [result])
 
     def test_misencodedFileUTF16(self):
         """
         If a source file contains bytes which cannot be decoded, this is
         reported on stderr.
         """
         SNOWMAN = unichr(0x2603)
         source = ("""\
@@ -495,37 +642,40 @@ class IntegrationTests(TestCase):
         import pyflakes
         package_dir = os.path.dirname(pyflakes.__file__)
         return os.path.join(package_dir, '..', 'bin', 'pyflakes')
 
     def runPyflakes(self, paths, stdin=None):
         """
         Launch a subprocess running C{pyflakes}.
 
-        @param args: Command-line arguments to pass to pyflakes.
-        @param kwargs: Options passed on to C{subprocess.Popen}.
+        @param paths: Command-line arguments to pass to pyflakes.
+        @param stdin: Text to use as stdin.
         @return: C{(returncode, stdout, stderr)} of the completed pyflakes
             process.
         """
         env = dict(os.environ)
         env['PYTHONPATH'] = os.pathsep.join(sys.path)
         command = [sys.executable, self.getPyflakesBinary()]
         command.extend(paths)
         if stdin:
             p = subprocess.Popen(command, env=env, stdin=subprocess.PIPE,
                                  stdout=subprocess.PIPE, stderr=subprocess.PIPE)
-            (stdout, stderr) = p.communicate(stdin)
+            (stdout, stderr) = p.communicate(stdin.encode('ascii'))
         else:
             p = subprocess.Popen(command, env=env,
                                  stdout=subprocess.PIPE, stderr=subprocess.PIPE)
             (stdout, stderr) = p.communicate()
         rv = p.wait()
         if sys.version_info >= (3,):
             stdout = stdout.decode('utf-8')
             stderr = stderr.decode('utf-8')
+        # Workaround https://bitbucket.org/pypy/pypy/issues/2350
+        if PYPY and PY2 and WIN:
+            stderr = stderr.replace('\r\r\n', '\r\n')
         return (stdout, stderr, rv)
 
     def test_goodFile(self):
         """
         When a Python source file is all good, the return code is zero and no
         messages are printed to either stdout or stderr.
         """
         fd = open(self.tempfilepath, 'a')
@@ -538,27 +688,57 @@ class IntegrationTests(TestCase):
         When a Python source file has warnings, the return code is non-zero
         and the warnings are printed to stdout.
         """
         fd = open(self.tempfilepath, 'wb')
         fd.write("import contraband\n".encode('ascii'))
         fd.close()
         d = self.runPyflakes([self.tempfilepath])
         expected = UnusedImport(self.tempfilepath, Node(1), 'contraband')
-        self.assertEqual(d, ("%s\n" % expected, '', 1))
+        self.assertEqual(d, ("%s%s" % (expected, os.linesep), '', 1))
 
-    def test_errors(self):
+    def test_errors_io(self):
         """
         When pyflakes finds errors with the files it's given, (if they don't
         exist, say), then the return code is non-zero and the errors are
         printed to stderr.
         """
         d = self.runPyflakes([self.tempfilepath])
-        error_msg = '%s: No such file or directory\n' % (self.tempfilepath,)
+        error_msg = '%s: No such file or directory%s' % (self.tempfilepath,
+                                                         os.linesep)
         self.assertEqual(d, ('', error_msg, 1))
 
+    def test_errors_syntax(self):
+        """
+        When pyflakes finds errors with the files it's given, (if they don't
+        exist, say), then the return code is non-zero and the errors are
+        printed to stderr.
+        """
+        fd = open(self.tempfilepath, 'wb')
+        fd.write("import".encode('ascii'))
+        fd.close()
+        d = self.runPyflakes([self.tempfilepath])
+        error_msg = '{0}:1:{2}: invalid syntax{1}import{1}    {3}^{1}'.format(
+            self.tempfilepath, os.linesep, 5 if PYPY else 7, '' if PYPY else '  ')
+        self.assertEqual(d, ('', error_msg, True))
+
     def test_readFromStdin(self):
         """
         If no arguments are passed to C{pyflakes} then it reads from stdin.
         """
-        d = self.runPyflakes([], stdin='import contraband'.encode('ascii'))
+        d = self.runPyflakes([], stdin='import contraband')
         expected = UnusedImport('<stdin>', Node(1), 'contraband')
-        self.assertEqual(d, ("%s\n" % expected, '', 1))
+        self.assertEqual(d, ("%s%s" % (expected, os.linesep), '', 1))
+
+
+class TestMain(IntegrationTests):
+    """
+    Tests of the pyflakes main function.
+    """
+
+    def runPyflakes(self, paths, stdin=None):
+        try:
+            with SysStreamCapturing(stdin) as capture:
+                main(args=paths)
+        except SystemExit as e:
+            return (capture.output, capture.error, e.code)
+        else:
+            raise RuntimeError('SystemExit not raised')
new file mode 100644
--- /dev/null
+++ b/pylib/pyflakes/pyflakes/test/test_dict.py
@@ -0,0 +1,217 @@
+"""
+Tests for dict duplicate keys Pyflakes behavior.
+"""
+
+from sys import version_info
+
+from pyflakes import messages as m
+from pyflakes.test.harness import TestCase, skipIf
+
+
+class Test(TestCase):
+
+    def test_duplicate_keys(self):
+        self.flakes(
+            "{'yes': 1, 'yes': 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    @skipIf(version_info < (3,),
+            "bytes and strings with same 'value' are not equal in python3")
+    @skipIf(version_info[0:2] == (3, 2),
+            "python3.2 does not allow u"" literal string definition")
+    def test_duplicate_keys_bytes_vs_unicode_py3(self):
+        self.flakes("{b'a': 1, u'a': 2}")
+
+    @skipIf(version_info < (3,),
+            "bytes and strings with same 'value' are not equal in python3")
+    @skipIf(version_info[0:2] == (3, 2),
+            "python3.2 does not allow u"" literal string definition")
+    def test_duplicate_values_bytes_vs_unicode_py3(self):
+        self.flakes(
+            "{1: b'a', 1: u'a'}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    @skipIf(version_info >= (3,),
+            "bytes and strings with same 'value' are equal in python2")
+    def test_duplicate_keys_bytes_vs_unicode_py2(self):
+        self.flakes(
+            "{b'a': 1, u'a': 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    @skipIf(version_info >= (3,),
+            "bytes and strings with same 'value' are equal in python2")
+    def test_duplicate_values_bytes_vs_unicode_py2(self):
+        self.flakes("{1: b'a', 1: u'a'}")
+
+    def test_multiple_duplicate_keys(self):
+        self.flakes(
+            "{'yes': 1, 'yes': 2, 'no': 2, 'no': 3}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_keys_in_function(self):
+        self.flakes(
+            '''
+            def f(thing):
+                pass
+            f({'yes': 1, 'yes': 2})
+            ''',
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_keys_in_lambda(self):
+        self.flakes(
+            "lambda x: {(0,1): 1, (0,1): 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_keys_tuples(self):
+        self.flakes(
+            "{(0,1): 1, (0,1): 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_keys_tuples_int_and_float(self):
+        self.flakes(
+            "{(0,1): 1, (0,1.0): 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_keys_ints(self):
+        self.flakes(
+            "{1: 1, 1: 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_keys_bools(self):
+        self.flakes(
+            "{True: 1, True: 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_keys_bools_false(self):
+        # Needed to ensure 2.x correctly coerces these from variables
+        self.flakes(
+            "{False: 1, False: 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_keys_none(self):
+        self.flakes(
+            "{None: 1, None: 2}",
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_variable_keys(self):
+        self.flakes(
+            '''
+            a = 1
+            {a: 1, a: 2}
+            ''',
+            m.MultiValueRepeatedKeyVariable,
+            m.MultiValueRepeatedKeyVariable,
+        )
+
+    def test_duplicate_variable_values(self):
+        self.flakes(
+            '''
+            a = 1
+            b = 2
+            {1: a, 1: b}
+            ''',
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_variable_values_same_value(self):
+        # Current behaviour is not to look up variable values. This is to
+        # confirm that.
+        self.flakes(
+            '''
+            a = 1
+            b = 1
+            {1: a, 1: b}
+            ''',
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_duplicate_key_float_and_int(self):
+        """
+        These do look like different values, but when it comes to their use as
+        keys, they compare as equal and so are actually duplicates.
+        The literal dict {1: 1, 1.0: 1} actually becomes {1.0: 1}.
+        """
+        self.flakes(
+            '''
+            {1: 1, 1.0: 2}
+            ''',
+            m.MultiValueRepeatedKeyLiteral,
+            m.MultiValueRepeatedKeyLiteral,
+        )
+
+    def test_no_duplicate_key_error_same_value(self):
+        self.flakes('''
+        {'yes': 1, 'yes': 1}
+        ''')
+
+    def test_no_duplicate_key_errors(self):
+        self.flakes('''
+        {'yes': 1, 'no': 2}
+        ''')
+
+    def test_no_duplicate_keys_tuples_same_first_element(self):
+        self.flakes("{(0,1): 1, (0,2): 1}")
+
+    def test_no_duplicate_key_errors_func_call(self):
+        self.flakes('''
+        def test(thing):
+            pass
+        test({True: 1, None: 2, False: 1})
+        ''')
+
+    def test_no_duplicate_key_errors_bool_or_none(self):
+        self.flakes("{True: 1, None: 2, False: 1}")
+
+    def test_no_duplicate_key_errors_ints(self):
+        self.flakes('''
+        {1: 1, 2: 1}
+        ''')
+
+    def test_no_duplicate_key_errors_vars(self):
+        self.flakes('''
+        test = 'yes'
+        rest = 'yes'
+        {test: 1, rest: 2}
+        ''')
+
+    def test_no_duplicate_key_errors_tuples(self):
+        self.flakes('''
+        {(0,1): 1, (0,2): 1}
+        ''')
+
+    def test_no_duplicate_key_errors_instance_attributes(self):
+        self.flakes('''
+        class Test():
+            pass
+        f = Test()
+        f.a = 1
+        {f.a: 1, f.a: 1}
+        ''')
--- a/pylib/pyflakes/pyflakes/test/test_doctests.py
+++ b/pylib/pyflakes/pyflakes/test/test_doctests.py
@@ -1,18 +1,32 @@
+import sys
 import textwrap
 
 from pyflakes import messages as m
+from pyflakes.checker import (
+    DoctestScope,
+    FunctionScope,
+    ModuleScope,
+)
 from pyflakes.test.test_other import Test as TestOther
 from pyflakes.test.test_imports import Test as TestImports
 from pyflakes.test.test_undefined_names import Test as TestUndefinedNames
-from pyflakes.test.harness import skip
+from pyflakes.test.harness import TestCase, skip
+
+try:
+    sys.pypy_version_info
+    PYPY = True
+except AttributeError:
+    PYPY = False
 
 
-class Test(TestOther, TestImports, TestUndefinedNames):
+class _DoctestMixin(object):
+
+    withDoctest = True
 
     def doctestify(self, input):
         lines = []
         for line in textwrap.dedent(input).splitlines():
             if line.strip() == '':
                 pass
             elif (line.startswith(' ') or
                   line.startswith('except:') or
@@ -28,155 +42,330 @@ class Test(TestOther, TestImports, TestU
             def doctest_something():
                 """
                    %s
                 """
             ''')
         return doctestificator % "\n       ".join(lines)
 
     def flakes(self, input, *args, **kw):
-        return super(Test, self).flakes(self.doctestify(input),
-                                        *args, **kw)
+        return super(_DoctestMixin, self).flakes(self.doctestify(input), *args, **kw)
+
+
+class Test(TestCase):
+
+    withDoctest = True
+
+    def test_scope_class(self):
+        """Check that a doctest is given a DoctestScope."""
+        checker = self.flakes("""
+        m = None
+
+        def doctest_stuff():
+            '''
+                >>> d = doctest_stuff()
+            '''
+            f = m
+            return f
+        """)
+
+        scopes = checker.deadScopes
+        module_scopes = [
+            scope for scope in scopes if scope.__class__ is ModuleScope]
+        doctest_scopes = [
+            scope for scope in scopes if scope.__class__ is DoctestScope]
+        function_scopes = [
+            scope for scope in scopes if scope.__class__ is FunctionScope]
+
+        self.assertEqual(len(module_scopes), 1)
+        self.assertEqual(len(doctest_scopes), 1)
+
+        module_scope = module_scopes[0]
+        doctest_scope = doctest_scopes[0]
+
+        self.assertIsInstance(doctest_scope, DoctestScope)
+        self.assertIsInstance(doctest_scope, ModuleScope)
+        self.assertNotIsInstance(doctest_scope, FunctionScope)
+        self.assertNotIsInstance(module_scope, DoctestScope)
+
+        self.assertIn('m', module_scope)
+        self.assertIn('doctest_stuff', module_scope)
+
+        self.assertIn('d', doctest_scope)
+
+        self.assertEqual(len(function_scopes), 1)
+        self.assertIn('f', function_scopes[0])
 
-    def test_doubleNestingReportsClosestName(self):
-        """
-        Lines in doctest are a bit different so we can't use the test
-        from TestUndefinedNames
-        """
-        exc = super(Test, self).flakes('''
+    def test_nested_doctest_ignored(self):
+        """Check that nested doctests are ignored."""
+        checker = self.flakes("""
+        m = None
+
+        def doctest_stuff():
+            '''
+                >>> def function_in_doctest():
+                ...     \"\"\"
+                ...     >>> ignored_undefined_name
+                ...     \"\"\"
+                ...     df = m
+                ...     return df
+                ...
+                >>> function_in_doctest()
+            '''
+            f = m
+            return f
+        """)
+
+        scopes = checker.deadScopes
+        module_scopes = [
+            scope for scope in scopes if scope.__class__ is ModuleScope]
+        doctest_scopes = [
+            scope for scope in scopes if scope.__class__ is DoctestScope]
+        function_scopes = [
+            scope for scope in scopes if scope.__class__ is FunctionScope]
+
+        self.assertEqual(len(module_scopes), 1)
+        self.assertEqual(len(doctest_scopes), 1)
+
+        module_scope = module_scopes[0]
+        doctest_scope = doctest_scopes[0]
+
+        self.assertIn('m', module_scope)
+        self.assertIn('doctest_stuff', module_scope)
+        self.assertIn('function_in_doctest', doctest_scope)
+
+        self.assertEqual(len(function_scopes), 2)
+
+        self.assertIn('f', function_scopes[0])
+        self.assertIn('df', function_scopes[1])
+
+    def test_global_module_scope_pollution(self):
+        """Check that global in doctest does not pollute module scope."""
+        checker = self.flakes("""
         def doctest_stuff():
-            """
-                >>> def a():
-                ...     x = 1
-                ...     def b():
-                ...         x = 2 # line 7 in the file
-                ...         def c():
-                ...             x
-                ...             x = 3
-                ...             return x
-                ...         return x
-                ...     return x
+            '''
+                >>> def function_in_doctest():
+                ...     global m
+                ...     m = 50
+                ...     df = 10
+                ...     m = df
+                ...
+                >>> function_in_doctest()
+            '''
+            f = 10
+            return f
+
+        """)
+
+        scopes = checker.deadScopes
+        module_scopes = [
+            scope for scope in scopes if scope.__class__ is ModuleScope]
+        doctest_scopes = [
+            scope for scope in scopes if scope.__class__ is DoctestScope]
+        function_scopes = [
+            scope for scope in scopes if scope.__class__ is FunctionScope]
+
+        self.assertEqual(len(module_scopes), 1)
+        self.assertEqual(len(doctest_scopes), 1)
+
+        module_scope = module_scopes[0]
+        doctest_scope = doctest_scopes[0]
+
+        self.assertIn('doctest_stuff', module_scope)
+        self.assertIn('function_in_doctest', doctest_scope)
+
+        self.assertEqual(len(function_scopes), 2)
+
+        self.assertIn('f', function_scopes[0])
+        self.assertIn('df', function_scopes[1])
+        self.assertIn('m', function_scopes[1])
+
+        self.assertNotIn('m', module_scope)
+
+    def test_global_undefined(self):
+        self.flakes("""
+        global m
 
-            """
-        ''', m.UndefinedLocal).messages[0]
-        self.assertEqual(exc.message_args, ('x', 7))
+        def doctest_stuff():
+            '''
+                >>> m
+            '''
+        """, m.UndefinedName)
+
+    def test_nested_class(self):
+        """Doctest within nested class are processed."""
+        self.flakes("""
+        class C:
+            class D:
+                '''
+                    >>> m
+                '''
+                def doctest_stuff(self):
+                    '''
+                        >>> m
+                    '''
+                    return 1
+        """, m.UndefinedName, m.UndefinedName)
 
-    def test_futureImport(self):
-        """XXX This test can't work in a doctest"""
+    def test_ignore_nested_function(self):
+        """Doctest module does not process doctest in nested functions."""
+        # 'syntax error' would cause a SyntaxError if the doctest was processed.
+        # However doctest does not find doctest in nested functions
+        # (https://bugs.python.org/issue1650090). If nested functions were
+        # processed, this use of m should cause UndefinedName, and the
+        # name inner_function should probably exist in the doctest scope.
+        self.flakes("""
+        def doctest_stuff():
+            def inner_function():
+                '''
+                    >>> syntax error
+                    >>> inner_function()
+                    1
+                    >>> m
+                '''
+                return 1
+            m = inner_function()
+            return m
+        """)
+
+    def test_inaccessible_scope_class(self):
+        """Doctest may not access class scope."""
+        self.flakes("""
+        class C:
+            def doctest_stuff(self):
+                '''
+                    >>> m
+                '''
+                return 1
+            m = 1
+        """, m.UndefinedName)
 
     def test_importBeforeDoctest(self):
-        super(Test, self).flakes("""
+        self.flakes("""
         import foo
 
         def doctest_stuff():
             '''
                 >>> foo
             '''
         """)
 
     @skip("todo")
     def test_importBeforeAndInDoctest(self):
-        super(Test, self).flakes('''
+        self.flakes('''
         import foo
 
         def doctest_stuff():
             """
                 >>> import foo
                 >>> foo
             """
 
         foo
-        ''', m.Redefined)
+        ''', m.RedefinedWhileUnused)
 
     def test_importInDoctestAndAfter(self):
-        super(Test, self).flakes('''
+        self.flakes('''
         def doctest_stuff():
             """
                 >>> import foo
                 >>> foo
             """
 
         import foo
         foo()
         ''')
 
     def test_offsetInDoctests(self):
-        exc = super(Test, self).flakes('''
+        exc = self.flakes('''
 
         def doctest_stuff():
             """
                 >>> x # line 5
             """
 
         ''', m.UndefinedName).messages[0]
         self.assertEqual(exc.lineno, 5)
         self.assertEqual(exc.col, 12)
 
     def test_offsetInLambdasInDoctests(self):
-        exc = super(Test, self).flakes('''
+        exc = self.flakes('''
 
         def doctest_stuff():
             """
                 >>> lambda: x # line 5
             """
 
         ''', m.UndefinedName).messages[0]
         self.assertEqual(exc.lineno, 5)
         self.assertEqual(exc.col, 20)
 
     def test_offsetAfterDoctests(self):
-        exc = super(Test, self).flakes('''
+        exc = self.flakes('''
 
         def doctest_stuff():
             """
                 >>> x = 5
             """
 
         x
 
         ''', m.UndefinedName).messages[0]
         self.assertEqual(exc.lineno, 8)
         self.assertEqual(exc.col, 0)
 
     def test_syntaxErrorInDoctest(self):
-        exceptions = super(Test, self).flakes(
+        exceptions = self.flakes(
             '''
             def doctest_stuff():
                 """
                     >>> from # line 4
                     >>>     fortytwo = 42
                     >>> except Exception:
                 """
             ''',
             m.DoctestSyntaxError,
             m.DoctestSyntaxError,
             m.DoctestSyntaxError).messages
         exc = exceptions[0]
         self.assertEqual(exc.lineno, 4)
         self.assertEqual(exc.col, 26)
+
+        # PyPy error column offset is 0,
+        # for the second and third line of the doctest
+        # i.e. at the beginning of the line
         exc = exceptions[1]
         self.assertEqual(exc.lineno, 5)
-        self.assertEqual(exc.col, 16)
+        if PYPY:
+            self.assertEqual(exc.col, 13)
+        else:
+            self.assertEqual(exc.col, 16)
         exc = exceptions[2]
         self.assertEqual(exc.lineno, 6)
-        self.assertEqual(exc.col, 18)
+        if PYPY:
+            self.assertEqual(exc.col, 13)
+        else:
+            self.assertEqual(exc.col, 18)
 
     def test_indentationErrorInDoctest(self):
-        exc = super(Test, self).flakes('''
+        exc = self.flakes('''
         def doctest_stuff():
             """
                 >>> if True:
                 ... pass
             """
         ''', m.DoctestSyntaxError).messages[0]
         self.assertEqual(exc.lineno, 5)
-        self.assertEqual(exc.col, 16)
+        if PYPY:
+            self.assertEqual(exc.col, 13)
+        else:
+            self.assertEqual(exc.col, 16)
 
     def test_offsetWithMultiLineArgs(self):
-        (exc1, exc2) = super(Test, self).flakes(
+        (exc1, exc2) = self.flakes(
             '''
             def doctest_stuff(arg1,
                               arg2,
                               arg3):
                 """
                     >>> assert
                     >>> this
                 """
@@ -184,26 +373,70 @@ class Test(TestOther, TestImports, TestU
             m.DoctestSyntaxError,
             m.UndefinedName).messages
         self.assertEqual(exc1.lineno, 6)
         self.assertEqual(exc1.col, 19)
         self.assertEqual(exc2.lineno, 7)
         self.assertEqual(exc2.col, 12)
 
     def test_doctestCanReferToFunction(self):
-        super(Test, self).flakes("""
+        self.flakes("""
         def foo():
             '''
                 >>> foo
             '''
         """)
 
     def test_doctestCanReferToClass(self):
-        super(Test, self).flakes("""
+        self.flakes("""
         class Foo():
             '''
                 >>> Foo
             '''
             def bar(self):
                 '''
                     >>> Foo
                 '''
         """)
+
+    def test_noOffsetSyntaxErrorInDoctest(self):
+        exceptions = self.flakes(
+            '''
+            def buildurl(base, *args, **kwargs):
+                """
+                >>> buildurl('/blah.php', ('a', '&'), ('b', '=')
+                '/blah.php?a=%26&b=%3D'
+                >>> buildurl('/blah.php', a='&', 'b'='=')
+                '/blah.php?b=%3D&a=%26'
+                """
+                pass
+            ''',
+            m.DoctestSyntaxError,
+            m.DoctestSyntaxError).messages
+        exc = exceptions[0]
+        self.assertEqual(exc.lineno, 4)
+        exc = exceptions[1]
+        self.assertEqual(exc.lineno, 6)
+
+    def test_singleUnderscoreInDoctest(self):
+        self.flakes('''
+        def func():
+            """A docstring
+
+            >>> func()
+            1
+            >>> _
+            1
+            """
+            return 1
+        ''')
+
+
+class TestOther(_DoctestMixin, TestOther):
+    """Run TestOther with each test wrapped in a doctest."""
+
+
+class TestImports(_DoctestMixin, TestImports):
+    """Run TestImports with each test wrapped in a doctest."""
+
+
+class TestUndefinedNames(_DoctestMixin, TestUndefinedNames):
+    """Run TestUndefinedNames with each test wrapped in a doctest."""
--- a/pylib/pyflakes/pyflakes/test/test_imports.py
+++ b/pylib/pyflakes/pyflakes/test/test_imports.py
@@ -1,32 +1,158 @@
 
 from sys import version_info
 
 from pyflakes import messages as m
+from pyflakes.checker import (
+    FutureImportation,
+    Importation,
+    ImportationFrom,
+    StarImportation,
+    SubmoduleImportation,
+)
 from pyflakes.test.harness import TestCase, skip, skipIf
 
 
+class TestImportationObject(TestCase):
+
+    def test_import_basic(self):
+        binding = Importation('a', None, 'a')
+        assert binding.source_statement == 'import a'
+        assert str(binding) == 'a'
+
+    def test_import_as(self):
+        binding = Importation('c', None, 'a')
+        assert binding.source_statement == 'import a as c'
+        assert str(binding) == 'a as c'
+
+    def test_import_submodule(self):
+        binding = SubmoduleImportation('a.b', None)
+        assert binding.source_statement == 'import a.b'
+        assert str(binding) == 'a.b'
+
+    def test_import_submodule_as(self):
+        # A submodule import with an as clause is not a SubmoduleImportation
+        binding = Importation('c', None, 'a.b')
+        assert binding.source_statement == 'import a.b as c'
+        assert str(binding) == 'a.b as c'
+
+    def test_import_submodule_as_source_name(self):
+        binding = Importation('a', None, 'a.b')
+        assert binding.source_statement == 'import a.b as a'
+        assert str(binding) == 'a.b as a'
+
+    def test_importfrom_relative(self):
+        binding = ImportationFrom('a', None, '.', 'a')
+        assert binding.source_statement == 'from . import a'
+        assert str(binding) == '.a'
+
+    def test_importfrom_relative_parent(self):
+        binding = ImportationFrom('a', None, '..', 'a')
+        assert binding.source_statement == 'from .. import a'
+        assert str(binding) == '..a'
+
+    def test_importfrom_relative_with_module(self):
+        binding = ImportationFrom('b', None, '..a', 'b')
+        assert binding.source_statement == 'from ..a import b'
+        assert str(binding) == '..a.b'
+
+    def test_importfrom_relative_with_module_as(self):
+        binding = ImportationFrom('c', None, '..a', 'b')
+        assert binding.source_statement == 'from ..a import b as c'
+        assert str(binding) == '..a.b as c'
+
+    def test_importfrom_member(self):
+        binding = ImportationFrom('b', None, 'a', 'b')
+        assert binding.source_statement == 'from a import b'
+        assert str(binding) == 'a.b'
+
+    def test_importfrom_submodule_member(self):
+        binding = ImportationFrom('c', None, 'a.b', 'c')
+        assert binding.source_statement == 'from a.b import c'
+        assert str(binding) == 'a.b.c'
+
+    def test_importfrom_member_as(self):
+        binding = ImportationFrom('c', None, 'a', 'b')
+        assert binding.source_statement == 'from a import b as c'
+        assert str(binding) == 'a.b as c'
+
+    def test_importfrom_submodule_member_as(self):
+        binding = ImportationFrom('d', None, 'a.b', 'c')
+        assert binding.source_statement == 'from a.b import c as d'
+        assert str(binding) == 'a.b.c as d'
+
+    def test_importfrom_star(self):
+        binding = StarImportation('a.b', None)
+        assert binding.source_statement == 'from a.b import *'
+        assert str(binding) == 'a.b.*'
+
+    def test_importfrom_star_relative(self):
+        binding = StarImportation('.b', None)
+        assert binding.source_statement == 'from .b import *'
+        assert str(binding) == '.b.*'
+
+    def test_importfrom_future(self):
+        binding = FutureImportation('print_function', None, None)
+        assert binding.source_statement == 'from __future__ import print_function'
+        assert str(binding) == '__future__.print_function'
+
+
 class Test(TestCase):
 
     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_unusedImport_relative(self):
+        self.flakes('from . import fu', m.UnusedImport)
+        self.flakes('from . import fu as baz', m.UnusedImport)
+        self.flakes('from .. import fu', m.UnusedImport)
+        self.flakes('from ... import fu', m.UnusedImport)
+        self.flakes('from .. import fu as baz', m.UnusedImport)
+        self.flakes('from .bar import fu', m.UnusedImport)
+        self.flakes('from ..bar import fu', m.UnusedImport)
+        self.flakes('from ...bar import fu', m.UnusedImport)
+        self.flakes('from ...bar import fu as baz', m.UnusedImport)
+
+        checker = self.flakes('from . import fu', m.UnusedImport)
+
+        error = checker.messages[0]
+        assert error.message == '%r imported but unused'
+        assert error.message_args == ('.fu', )
+
+        checker = self.flakes('from . import fu as baz', m.UnusedImport)
+
+        error = checker.messages[0]
+        assert error.message == '%r imported but unused'
+        assert error.message_args == ('.fu as baz', )
+
     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_aliasedImportShadowModule(self):
+        """Imported aliases can shadow the source of the import."""
+        self.flakes('from moo import fu as moo; moo')
+        self.flakes('import fu as fu; fu')
+        self.flakes('import fu.bar as fu; fu')
+
     def test_usedImport(self):
         self.flakes('import fu; print(fu)')
         self.flakes('from baz import fu; print(fu)')
         self.flakes('import fu; del fu')
 
+    def test_usedImport_relative(self):
+        self.flakes('from . import fu; assert fu')
+        self.flakes('from .bar import fu; assert fu')
+        self.flakes('from .. import fu; assert fu')
+        self.flakes('from ..bar import fu as baz; assert baz')
+
     def test_redefinedWhileUnused(self):
         self.flakes('import fu; fu = 3', m.RedefinedWhileUnused)
         self.flakes('import fu; fu, bar = 3', m.RedefinedWhileUnused)
         self.flakes('import fu; [fu, bar] = 3', m.RedefinedWhileUnused)
 
     def test_redefinedIf(self):
         """
         Test that importing a module twice within an if
@@ -49,30 +175,30 @@ class Test(TestCase):
         if i==1:
             import os
         else:
             import os
         os.path''')
 
     def test_redefinedTry(self):
         """
-        Test that importing a module twice in an try block
+        Test that importing a module twice in a try block
         does raise a warning.
         """
         self.flakes('''
         try:
             import os
             import os
         except:
             pass
         os.path''', m.RedefinedWhileUnused)
 
     def test_redefinedTryExcept(self):
         """
-        Test that importing a module twice in an try
+        Test that importing a module twice in a try
         and except block does not raise a warning.
         """
         self.flakes('''
         try:
             import os
         except:
             import os
         os.path''')
@@ -167,16 +293,50 @@ class Test(TestCase):
         self.flakes('''
         import fu
         def bar():
             def baz():
                 def fu():
                     pass
         ''', m.RedefinedWhileUnused, m.UnusedImport)
 
+    def test_redefinedInNestedFunctionTwice(self):
+        """
+        Test that shadowing a global name with a nested function definition
+        generates a warning.
+        """
+        self.flakes('''
+        import fu
+        def bar():
+            import fu
+            def baz():
+                def fu():
+                    pass
+        ''',
+                    m.RedefinedWhileUnused, m.RedefinedWhileUnused,
+                    m.UnusedImport, m.UnusedImport)
+
+    def test_redefinedButUsedLater(self):
+        """
+        Test that a global import which is redefined locally,
+        but used later in another scope does not generate a warning.
+        """
+        self.flakes('''
+        import unittest, transport
+
+        class GetTransportTestCase(unittest.TestCase):
+            def test_get_transport(self):
+                transport = 'transport'
+                self.assertIsNotNone(transport)
+
+        class TestTransportMethodArgs(unittest.TestCase):
+            def test_send_defaults(self):
+                transport.Transport()
+        ''')
+
     def test_redefinedByClass(self):
         self.flakes('''
         import fu
         class fu:
             pass
         ''', m.RedefinedWhileUnused)
 
     def test_redefinedBySubclass(self):
@@ -197,29 +357,45 @@ class Test(TestCase):
         """
         self.flakes('''
         import fu
         class bar:
             fu = 1
         print(fu)
         ''')
 
+    def test_importInClass(self):
+        """
+        Test that import within class is a locally scoped attribute.
+        """
+        self.flakes('''
+        class bar:
+            import fu
+        ''')
+
+        self.flakes('''
+        class bar:
+            import fu
+
+        fu
+        ''', m.UndefinedName)
+
     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)
+        ''', m.UnusedImport, m.RedefinedWhileUnused)
 
         self.flakes('''
         import fu
         def fun(fu):
             print(fu)
         print(fu)
         ''')
 
@@ -300,17 +476,17 @@ class Test(TestCase):
             print(fu)
         ''')
 
     def test_redefinedByFor(self):
         self.flakes('''
         import fu
         for fu in range(2):
             pass
-        ''', m.RedefinedWhileUnused)
+        ''', m.ImportShadowedByLoopVar)
 
     def test_shadowedByFor(self):
         """
         Test that shadowing a global name with a for loop variable generates a
         warning.
         """
         self.flakes('''
         import fu
@@ -325,16 +501,23 @@ class Test(TestCase):
         tuple unpack generates a warning.
         """
         self.flakes('''
         import fu
         fu.bar()
         for (x, y, z, (a, b, c, (fu,))) in ():
             pass
         ''', m.ImportShadowedByLoopVar)
+        # Same with a list instead of a tuple
+        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
         ''')
 
@@ -427,18 +610,21 @@ class Test(TestCase):
     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]')
 
+    @skipIf(version_info >= (3,),
+            'in Python 3 list comprehensions execute in a separate scope')
     def test_redefinedByListComp(self):
-        self.flakes('import fu; [1 for fu in range(1)]', m.RedefinedWhileUnused)
+        self.flakes('import fu; [1 for fu in range(1)]',
+                    m.RedefinedInListComp)
 
     def test_usedInTryFinally(self):
         self.flakes('''
         import fu
         try: pass
         finally: fu
         ''')
 
@@ -456,37 +642,64 @@ class Test(TestCase):
         ''')
 
         self.flakes('''
         import fu
         while fu: pass
         ''')
 
     def test_usedInGlobal(self):
+        """
+        A 'global' statement shadowing an unused import should not prevent it
+        from being reported.
+        """
         self.flakes('''
         import fu
         def f(): global fu
         ''', m.UnusedImport)
 
+    def test_usedAndGlobal(self):
+        """
+        A 'global' statement shadowing a used import should not cause it to be
+        reported as unused.
+        """
+        self.flakes('''
+            import foo
+            def f(): global foo
+            def g(): foo.is_used()
+        ''')
+
+    def test_assignedToGlobal(self):
+        """
+        Binding an import to a declared global should not cause it to be
+        reported as unused.
+        """
+        self.flakes('''
+            def f(): global foo; import foo
+            def g(): foo.is_used()
+        ''')
+
     @skipIf(version_info >= (3,), 'deprecated syntax')
     def test_usedInBackquote(self):
         self.flakes('import fu; `fu`')
 
     def test_usedInExec(self):
         if version_info < (3,):
             exec_stmt = 'exec "print 1" in fu.bar'
         else:
             exec_stmt = 'exec("print(1)", fu.bar)'
         self.flakes('import fu; %s' % exec_stmt)
 
     def test_usedInLambda(self):
         self.flakes('import fu; lambda: fu')
 
     def test_shadowedByLambda(self):
-        self.flakes('import fu; lambda fu: fu', m.UnusedImport)
+        self.flakes('import fu; lambda fu: fu',
+                    m.UnusedImport, m.RedefinedWhileUnused)
+        self.flakes('import fu; lambda fu: fu\nfu()')
 
     def test_usedInSliceObj(self):
         self.flakes('import fu; "meow"[::fu]')
 
     def test_unusedInNestedScope(self):
         self.flakes('''
         def bar():
             import fu
@@ -494,17 +707,17 @@ class Test(TestCase):
         ''', m.UnusedImport, m.UndefinedName)
 
     def test_methodsDontUseClassScope(self):
         self.flakes('''
         class bar:
             import fu
             def fun(self):
                 fu
-        ''', m.UnusedImport, m.UndefinedName)
+        ''', m.UndefinedName)
 
     def test_nestedFunctionsNestScope(self):
         self.flakes('''
         def a():
             def b():
                 fu
             import fu
         ''')
@@ -514,17 +727,99 @@ class Test(TestCase):
         def a():
             import fu
             class b:
                 def c(self):
                     print(fu)
         ''')
 
     def test_importStar(self):
-        self.flakes('from fu import *', m.ImportStarUsed)
+        """Use of import * at module level is reported."""
+        self.flakes('from fu import *', m.ImportStarUsed, m.UnusedImport)
+        self.flakes('''
+        try:
+            from fu import *
+        except:
+            pass
+        ''', m.ImportStarUsed, m.UnusedImport)
+
+        checker = self.flakes('from fu import *',
+                              m.ImportStarUsed, m.UnusedImport)
+
+        error = checker.messages[0]
+        assert error.message.startswith("'from %s import *' used; unable ")
+        assert error.message_args == ('fu', )
+
+        error = checker.messages[1]
+        assert error.message == '%r imported but unused'
+        assert error.message_args == ('fu.*', )
+
+    def test_importStar_relative(self):
+        """Use of import * from a relative import is reported."""
+        self.flakes('from .fu import *', m.ImportStarUsed, m.UnusedImport)
+        self.flakes('''
+        try:
+            from .fu import *
+        except:
+            pass
+        ''', m.ImportStarUsed, m.UnusedImport)
+
+        checker = self.flakes('from .fu import *',
+                              m.ImportStarUsed, m.UnusedImport)
+
+        error = checker.messages[0]
+        assert error.message.startswith("'from %s import *' used; unable ")
+        assert error.message_args == ('.fu', )
+
+        error = checker.messages[1]
+        assert error.message == '%r imported but unused'
+        assert error.message_args == ('.fu.*', )
+
+        checker = self.flakes('from .. import *',
+                              m.ImportStarUsed, m.UnusedImport)
+
+        error = checker.messages[0]
+        assert error.message.startswith("'from %s import *' used; unable ")
+        assert error.message_args == ('..', )
+
+        error = checker.messages[1]
+        assert error.message == '%r imported but unused'
+        assert error.message_args == ('from .. import *', )
+
+    @skipIf(version_info < (3,),
+            'import * below module level is a warning on Python 2')
+    def test_localImportStar(self):
+        """import * is only allowed at module level."""
+        self.flakes('''
+        def a():
+            from fu import *
+        ''', m.ImportStarNotPermitted)
+        self.flakes('''
+        class a:
+            from fu import *
+        ''', m.ImportStarNotPermitted)
+
+        checker = self.flakes('''
+        class a:
+            from .. import *
+        ''', m.ImportStarNotPermitted)
+        error = checker.messages[0]
+        assert error.message == "'from %s import *' only allowed at module level"
+        assert error.message_args == ('..', )
+
+    @skipIf(version_info > (3,),
+            'import * below module level is an error on Python 3')
+    def test_importStarNested(self):
+        """All star imports are marked as used by an undefined variable."""
+        self.flakes('''
+        from fu import *
+        def f():
+            from bar import *
+            x
+        ''', m.ImportStarUsed, m.ImportStarUsed, m.ImportStarUsage)
 
     def test_packageImport(self):
         """
         If a dotted name is imported and used, no warning is reported.
         """
         self.flakes('''
         import fu.bar
         fu.bar
@@ -562,16 +857,45 @@ class Test(TestCase):
         fu.bar, fu.baz
         ''')
         self.flakes('''
         import fu.bar
         import fu.baz
         fu.bar, fu.baz
         ''')
 
+    def test_used_package_with_submodule_import(self):
+        """
+        Usage of package marks submodule imports as used.
+        """
+        self.flakes('''
+        import fu
+        import fu.bar
+        fu.x
+        ''')
+
+        self.flakes('''
+        import fu.bar
+        import fu
+        fu.x
+        ''')
+
+    def test_unused_package_with_submodule_import(self):
+        """
+        When a package and its submodule are imported, only report once.
+        """
+        checker = self.flakes('''
+        import fu
+        import fu.bar
+        ''', m.UnusedImport)
+        error = checker.messages[0]
+        assert error.message == '%r imported but unused'
+        assert error.message_args == ('fu.bar', )
+        assert error.lineno == 5 if self.withDoctest else 3
+
     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('''
@@ -613,26 +937,37 @@ class Test(TestCase):
     def test_importingForImportError(self):
         self.flakes('''
         try:
             import fu
         except ImportError:
             pass
         ''')
 
-    @skip("todo: requires evaluating attribute access")
     def test_importedInClass(self):
         """Imports in class scope can be used through self."""
         self.flakes('''
         class c:
             import i
             def __init__(self):
                 self.i
         ''')
 
+    def test_importUsedInMethodDefinition(self):
+        """
+        Method named 'foo' with default args referring to module named 'foo'.
+        """
+        self.flakes('''
+        import foo
+
+        class Thing(object):
+            def foo(self, parser=foo.parse_foo):
+                pass
+        ''')
+
     def test_futureImport(self):
         """__future__ is special."""
         self.flakes('from __future__ import division')
         self.flakes('''
         "docstring is allowed before future import"
         from __future__ import division
         ''')
 
@@ -645,16 +980,37 @@ class Test(TestCase):
         from __future__ import division
         ''', m.LateFutureImport)
         self.flakes('''
         from foo import bar
         from __future__ import division
         bar
         ''', m.LateFutureImport)
 
+    def test_futureImportUsed(self):
+        """__future__ is special, but names are injected in the namespace."""
+        self.flakes('''
+        from __future__ import division
+        from __future__ import print_function
+
+        assert print_function is not division
+        ''')
+
+    def test_futureImportUndefined(self):
+        """Importing undefined names from __future__ fails."""
+        self.flakes('''
+        from __future__ import print_statement
+        ''', m.FutureFeatureNotDefined)
+
+    def test_futureImportStar(self):
+        """Importing '*' from __future__ fails."""
+        self.flakes('''
+        from __future__ import *
+        ''', m.FutureFeatureNotDefined)
+
 
 class TestSpecialAll(TestCase):
     """
     Tests for suppression of unused import warnings by C{__all__}.
     """
     def test_ignoredInFunction(self):
         """
         An C{__all__} definition does not suppress unused import warnings in a
@@ -663,34 +1019,50 @@ class TestSpecialAll(TestCase):
         self.flakes('''
         def foo():
             import bar
             __all__ = ["bar"]
         ''', m.UnusedImport, m.UnusedVariable)
 
     def test_ignoredInClass(self):
         """
-        An C{__all__} definition does not suppress unused import warnings in a
-        class scope.
+        An C{__all__} definition in a class does not suppress unused import warnings.
         """
         self.flakes('''
+        import bar
         class foo:
-            import bar
             __all__ = ["bar"]
         ''', m.UnusedImport)
 
     def test_warningSuppressed(self):
         """
         If a name is imported and unused but is named in C{__all__}, no warning
         is reported.
         """
         self.flakes('''
         import foo
         __all__ = ["foo"]
         ''')
+        self.flakes('''
+        import foo
+        __all__ = ("foo",)
+        ''')
+
+    def test_augmentedAssignment(self):
+        """
+        The C{__all__} variable is defined incrementally.
+        """
+        self.flakes('''
+        import a
+        import c
+        __all__ = ['a']
+        __all__ += ['b']
+        if 1 < 3:
+            __all__ += ['c', 'd']
+        ''', m.UndefinedExport, m.UndefinedExport)
 
     def test_unrecognizable(self):
         """
         If C{__all__} is defined in a way that can't be recognized statically,
         it is ignored.
         """
         self.flakes('''
         import foo
@@ -720,16 +1092,24 @@ class TestSpecialAll(TestCase):
         """
         Do not report undefined if import * is used
         """
         self.flakes('''
         from foolib import *
         __all__ = ["foo"]
         ''', m.ImportStarUsed)
 
+    def test_importStarNotExported(self):
+        """Report unused import when not needed to satisfy __all__."""
+        self.flakes('''
+        from foolib import *
+        a = 1
+        __all__ = ['a']
+        ''', m.ImportStarUsed, m.UnusedImport)
+
     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):
@@ -764,17 +1144,17 @@ class TestSpecialAll(TestCase):
         @decorate
         def f():
             return "hello"
         ''', m.UndefinedName)
 
 
 class Python26Tests(TestCase):
     """
-    Tests for checking of syntax which is valid in PYthon 2.6 and newer.
+    Tests for checking of syntax which is valid in Python 2.6 and newer.
     """
 
     @skipIf(version_info < (2, 6), "Python >= 2.6 only")
     def test_usedAsClassDecorator(self):
         """
         Using an imported name as a class decorator results in no warnings,
         but using an undefined name as a class decorator results in an
         undefined name warning.
--- a/pylib/pyflakes/pyflakes/test/test_other.py
+++ b/pylib/pyflakes/pyflakes/test/test_other.py
@@ -8,25 +8,26 @@ 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)
 
-    @skip("todo: this requires finding all assignments in the function body first")
     def test_localReferencedBeforeAssignment(self):
         self.flakes('''
         a = 1
         def f():
             a; a=1
         f()
-        ''', m.UndefinedName)
+        ''', m.UndefinedLocal, m.UnusedVariable)
 
+    @skipIf(version_info >= (3,),
+            'in Python 3 list comprehensions execute in a separate scope')
     def test_redefinedInListComp(self):
         """
         Test that shadowing a variable in a list comprehension raises
         a warning.
         """
         self.flakes('''
         a = 1
         [1 for a, b in [(1, 2)]]
@@ -216,16 +217,18 @@ class Test(TestCase):
         """
         self.flakes('''
         if False:
             a = 1
         else:
             [a for a in '12']
         ''')
 
+    @skipIf(version_info >= (3,),
+            'in Python 3 list comprehensions execute in a separate scope')
     def test_redefinedElseInListComp(self):
         """
         Test that shadowing a variable in a list comprehension in
         an else (or if) block raises a warning.
         """
         self.flakes('''
         if False:
             pass
@@ -336,16 +339,683 @@ class Test(TestCase):
         """
         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)
+
+    @skipIf(version_info < (3, 3), "Python >= 3.3 only")
+    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)
+
+    @skipIf(version_info < (3, 3), "Python >= 3.3 only")
+    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
+        ''')
+
+    def test_continueInFinally(self):
+        # 'continue' inside 'finally' is a special syntax error
+        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)
+
+    @skipIf(version_info < (3,), "Python 3 only")
+    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)
+
+    @skipIf(version_info < (3, ), "Python 3 only")
+    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
@@ -459,16 +1129,25 @@ class Test(TestCase):
         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()
+        ''')
+
 
 class TestUnusedAssignment(TestCase):
     """
     Tests for warning about unused assignments.
     """
 
     def test_unusedVariable(self):
         """
@@ -497,16 +1176,40 @@ class TestUnusedAssignment(TestCase):
         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():
@@ -587,28 +1290,50 @@ class TestUnusedAssignment(TestCase):
 
     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
@@ -759,17 +1484,17 @@ class TestUnusedAssignment(TestCase):
         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
+        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('''
         from __future__ import with_statement
         baz
         with open('foo') as (bar, baz):
             pass
@@ -903,17 +1628,244 @@ class TestUnusedAssignment(TestCase):
         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
+        ''')
+
     @skipIf(version_info < (3, 3), 'new in Python 3.3')
     def test_yieldFromUndefined(self):
         """
         Test C{yield from} statement
         """
         self.flakes('''
         def bar():
             yield from foo()
         ''', m.UndefinedName)
+
+    @skipIf(version_info < (3, 6), 'new in Python 3.6')
+    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}')
+        ''')
+
+
+class TestAsyncStatements(TestCase):
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_asyncDef(self):
+        self.flakes('''
+        async def bar():
+            return 42
+        ''')
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_asyncDefAwait(self):
+        self.flakes('''
+        async def read_data(db):
+            await db.fetch('SELECT ...')
+        ''')
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_asyncDefUndefined(self):
+        self.flakes('''
+        async def bar():
+            return foo()
+        ''', m.UndefinedName)
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_asyncFor(self):
+        self.flakes('''
+        async def read_data(db):
+            output = []
+            async for row in db.cursor():
+                output.append(row)
+            return output
+        ''')
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    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
+        ''')
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    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, 5), 'new in Python 3.5')
+    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)
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_asyncWith(self):
+        self.flakes('''
+        async def commit(session, data):
+            async with session.transaction():
+                await session.update(data)
+        ''')
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_asyncWithItem(self):
+        self.flakes('''
+        async def commit(session, data):
+            async with session.transaction() as trans:
+                await trans.begin()
+                ...
+                await trans.end()
+        ''')
+
+    @skipIf(version_info < (3, 5), 'new in Python 3.5')
+    def test_matmul(self):
+        self.flakes('''
+        def foo(a, b):
+            return a @ b
+        ''')
+
+    @skipIf(version_info < (3, 6), 'new in Python 3.6')
+    def test_formatstring(self):
+        self.flakes('''
+        hi = 'hi'
+        mom = 'mom'
+        f'{hi} {mom}'
+        ''')
+
+    @skipIf(version_info < (3, 6), 'new in Python 3.6')
+    def test_variable_annotations(self):
+        self.flakes('''
+        name: str
+        age: int
+        ''')
+        self.flakes('''
+        name: str = 'Bob'
+        age: int = 18
+        ''')
+        self.flakes('''
+        class C:
+            name: str
+            age: int
+        ''')
+        self.flakes('''
+        class C:
+            name: str = 'Bob'
+            age: int = 18
+        ''')
+        self.flakes('''
+        def f():
+            name: str
+            age: int
+        ''')
+        self.flakes('''
+        def f():
+            name: str = 'Bob'
+            age: int = 18
+            foo: not_a_real_type = None
+        ''', m.UnusedVariable, m.UnusedVariable, m.UnusedVariable)
+        self.flakes('''
+        def f():
+            name: str
+            print(name)
+        ''', m.UndefinedName)
+        self.flakes('''
+        foo: not_a_real_type
+        ''', m.UndefinedName)
+        self.flakes('''
+        foo: not_a_real_type = None
+        ''', m.UndefinedName)
+        self.flakes('''
+        class C:
+            foo: not_a_real_type
+        ''', m.UndefinedName)
+        self.flakes('''
+        class C:
+            foo: not_a_real_type = None
+        ''', m.UndefinedName)
+        self.flakes('''
+        def f():
+            class C:
+                foo: not_a_real_type
+        ''', m.UndefinedName)
+        self.flakes('''
+        def f():
+            class C:
+                foo: not_a_real_type = None
+        ''', m.UndefinedName)
new file mode 100644
--- /dev/null
+++ b/pylib/pyflakes/pyflakes/test/test_return_with_arguments_inside_generator.py
@@ -0,0 +1,34 @@
+
+from sys import version_info
+
+from pyflakes import messages as m
+from pyflakes.test.harness import TestCase, skipIf
+
+
+class Test(TestCase):
+    @skipIf(version_info >= (3, 3), 'new in Python 3.3')
+    def test_return(self):
+        self.flakes('''
+        class a:
+            def b():
+                for x in a.c:
+                    if x:
+                        yield x
+                return a
+        ''', m.ReturnWithArgsInsideGenerator)
+
+    @skipIf(version_info >= (3, 3), 'new in Python 3.3')
+    def test_returnNone(self):
+        self.flakes('''
+        def a():
+            yield 12
+            return None
+        ''', m.ReturnWithArgsInsideGenerator)
+
+    @skipIf(version_info >= (3, 3), 'new in Python 3.3')
+    def test_returnYieldExpression(self):
+        self.flakes('''
+        def a():
+            b = yield a
+            return b
+        ''', m.ReturnWithArgsInsideGenerator)
--- a/pylib/pyflakes/pyflakes/test/test_undefined_names.py
+++ b/pylib/pyflakes/pyflakes/test/test_undefined_names.py
@@ -1,23 +1,210 @@
 
 from _ast import PyCF_ONLY_AST
 from sys import version_info
 
 from pyflakes import messages as m, checker
-from pyflakes.test.harness import TestCase, skip, skipIf
+from pyflakes.test.harness import TestCase, skipIf, skip
 
 
 class Test(TestCase):
     def test_undefined(self):
         self.flakes('bar', m.UndefinedName)
 
     def test_definedInListComp(self):
         self.flakes('[a for a in range(10) if a]')
 
+    @skipIf(version_info < (3,),
+            'in Python 2 list comprehensions execute in the same scope')
+    def test_undefinedInListComp(self):
+        self.flakes('''
+        [a for a in range(10)]
+        a
+        ''',
+                    m.UndefinedName)
+
+    @skipIf(version_info < (3,),
+            'in Python 2 exception names stay bound after the except: block')
+    def test_undefinedExceptionName(self):
+        """Exception names can't be used after the except: block."""
+        self.flakes('''
+        try:
+            raise ValueError('ve')
+        except ValueError as exc:
+            pass
+        exc
+        ''',
+                    m.UndefinedName)
+
+    def test_namesDeclaredInExceptBlocks(self):
+        """Locals declared in except: blocks can be used after the block.
+
+        This shows the example in test_undefinedExceptionName is
+        different."""
+        self.flakes('''
+        try:
+            raise ValueError('ve')
+        except ValueError as exc:
+            e = exc
+        e
+        ''')
+
+    @skip('error reporting disabled due to false positives below')
+    def test_undefinedExceptionNameObscuringLocalVariable(self):
+        """Exception names obscure locals, can't be used after.
+
+        Last line will raise UnboundLocalError on Python 3 after exiting
+        the except: block. Note next two examples for false positives to
+        watch out for."""
+        self.flakes('''
+        exc = 'Original value'
+        try:
+            raise ValueError('ve')
+        except ValueError as exc:
+            pass
+        exc
+        ''',
+                    m.UndefinedName)
+
+    @skipIf(version_info < (3,),
+            'in Python 2 exception names stay bound after the except: block')
+    def test_undefinedExceptionNameObscuringLocalVariable2(self):
+        """Exception names are unbound after the `except:` block.
+
+        Last line will raise UnboundLocalError on Python 3 but would print out
+        've' on Python 2."""
+        self.flakes('''
+        try:
+            raise ValueError('ve')
+        except ValueError as exc:
+            pass
+        print(exc)
+        exc = 'Original value'
+        ''',
+                    m.UndefinedName)
+
+    def test_undefinedExceptionNameObscuringLocalVariableFalsePositive1(self):
+        """Exception names obscure locals, can't be used after. Unless.
+
+        Last line will never raise UnboundLocalError because it's only
+        entered if no exception was raised."""
+        self.flakes('''
+        exc = 'Original value'
+        try:
+            raise ValueError('ve')
+        except ValueError as exc:
+            print('exception logged')
+            raise
+        exc
+        ''')
+
+    def test_delExceptionInExcept(self):
+        """The exception name can be deleted in the except: block."""
+        self.flakes('''
+        try:
+            pass
+        except Exception as exc:
+            del exc
+        ''')
+
+    def test_undefinedExceptionNameObscuringLocalVariableFalsePositive2(self):
+        """Exception names obscure locals, can't be used after. Unless.
+
+        Last line will never raise UnboundLocalError because `error` is
+        only falsy if the `except:` block has not been entered."""
+        self.flakes('''
+        exc = 'Original value'
+        error = None
+        try:
+            raise ValueError('ve')
+        except ValueError as exc:
+            error = 'exception logged'
+        if error:
+            print(error)
+        else:
+            exc
+        ''')
+
+    @skip('error reporting disabled due to false positives below')
+    def test_undefinedExceptionNameObscuringGlobalVariable(self):
+        """Exception names obscure globals, can't be used after.
+
+        Last line will raise UnboundLocalError on both Python 2 and
+        Python 3 because the existence of that exception name creates
+        a local scope placeholder for it, obscuring any globals, etc."""
+        self.flakes('''
+        exc = 'Original value'
+        def func():
+            try:
+                pass  # nothing is raised
+            except ValueError as exc:
+                pass  # block never entered, exc stays unbound
+            exc
+        ''',
+                    m.UndefinedLocal)
+
+    @skip('error reporting disabled due to false positives below')
+    def test_undefinedExceptionNameObscuringGlobalVariable2(self):
+        """Exception names obscure globals, can't be used after.
+
+        Last line will raise NameError on Python 3 because the name is
+        locally unbound after the `except:` block, even if it's
+        nonlocal. We should issue an error in this case because code
+        only working correctly if an exception isn't raised, is invalid.
+        Unless it's explicitly silenced, see false positives below."""
+        self.flakes('''
+        exc = 'Original value'
+        def func():
+            global exc
+            try:
+                raise ValueError('ve')
+            except ValueError as exc:
+                pass  # block never entered, exc stays unbound
+            exc
+        ''',
+                    m.UndefinedLocal)
+
+    def test_undefinedExceptionNameObscuringGlobalVariableFalsePositive1(self):
+        """Exception names obscure globals, can't be used after. Unless.
+
+        Last line will never raise NameError because it's only entered
+        if no exception was raised."""
+        self.flakes('''
+        exc = 'Original value'
+        def func():
+            global exc
+            try:
+                raise ValueError('ve')
+            except ValueError as exc:
+                print('exception logged')
+                raise
+            exc
+        ''')
+
+    def test_undefinedExceptionNameObscuringGlobalVariableFalsePositive2(self):
+        """Exception names obscure globals, can't be used after. Unless.
+
+        Last line will never raise NameError because `error` is only
+        falsy if the `except:` block has not been entered."""
+        self.flakes('''
+        exc = 'Original value'
+        def func():
+            global exc
+            error = None
+            try:
+                raise ValueError('ve')
+            except ValueError as exc:
+                error = 'exception logged'
+            if error:
+                print(error)
+            else:
+                exc
+        ''')
+
     def test_functionsNeedGlobalScope(self):
         self.flakes('''
         class a:
             def b():
                 fu
         fu = 1
         ''')
 
@@ -57,58 +244,95 @@ class Test(TestCase):
         Use of the C{__path__} magic global should not emit an undefined name
         warning, if you refer to it from a file called __init__.py.
         """
         self.flakes('__path__', m.UndefinedName)
         self.flakes('__path__', filename='package/__init__.py')
 
     def test_globalImportStar(self):
         """Can't find undefined names with import *."""
-        self.flakes('from fu import *; bar', m.ImportStarUsed)
+        self.flakes('from fu import *; bar',
+                    m.ImportStarUsed, m.ImportStarUsage)
 
+    @skipIf(version_info >= (3,), 'obsolete syntax')
     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)
+        ''', m.ImportStarUsed, m.UndefinedName, m.UnusedImport)
 
     @skipIf(version_info >= (3,), 'obsolete syntax')
     def test_unpackedParameter(self):
         """Unpacked function parameters create bindings."""
         self.flakes('''
         def a((bar, baz)):
             bar; baz
         ''')
 
-    @skip("todo")
     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
         ''')
+        self.flakes('''
+        def c(): bar
+        def b(): global bar; bar = 1
+        ''')
+
+    def test_definedByGlobalMultipleNames(self):
+        """
+        "global" can accept multiple names.
+        """
+        self.flakes('''
+        def a(): global fu, bar; fu = 1; bar = 2
+        def b(): fu; bar
+        ''')
 
     def test_globalInGlobalScope(self):
         """
         A global statement in the global scope is ignored.
         """
         self.flakes('''
         global x
         def foo():
             print(x)
         ''', m.UndefinedName)
 
+    def test_global_reset_name_only(self):
+        """A global statement does not prevent other names being undefined."""
+        # Only different undefined names are reported.
+        # See following test that fails where the same name is used.
+        self.flakes('''
+        def f1():
+            s
+
+        def f2():
+            global m
+        ''', m.UndefinedName)
+
+    @skip("todo")
+    def test_unused_global(self):
+        """An unused global statement does not define the name."""
+        self.flakes('''
+        def f1():
+            m
+
+        def f2():
+            global m
+        ''', m.UndefinedName)
+
     def test_del(self):
         """Del deletes bindings."""
         self.flakes('a = 1; del a; a', m.UndefinedName)
 
     def test_delGlobal(self):
         """Del a global binding from a function."""
         self.flakes('''
         a = 1
@@ -117,16 +341,84 @@ class Test(TestCase):
             del a
         a
         ''')
 
     def test_delUndefined(self):
         """Del an undefined name."""
         self.flakes('del a', m.UndefinedName)
 
+    def test_delConditional(self):
+        """
+        Ignores conditional bindings deletion.
+        """
+        self.flakes('''
+        context = None
+        test = True
+        if False:
+            del(test)
+        assert(test)
+        ''')
+
+    def test_delConditionalNested(self):
+        """
+        Ignored conditional bindings deletion even if they are nested in other
+        blocks.
+        """
+        self.flakes('''
+        context = None
+        test = True
+        if False:
+            with context():
+                del(test)
+        assert(test)
+        ''')
+
+    def test_delWhile(self):
+        """
+        Ignore bindings deletion if called inside the body of a while
+        statement.
+        """
+        self.flakes('''
+        def test():
+            foo = 'bar'
+            while False:
+                del foo
+            assert(foo)
+        ''')
+
+    def test_delWhileTestUsage(self):
+        """
+        Ignore bindings deletion if called inside the body of a while
+        statement and name is used inside while's test part.
+        """
+        self.flakes('''
+        def _worker():
+            o = True
+            while o is not True:
+                del o
+                o = False
+        ''')
+
+    def test_delWhileNested(self):
+        """
+        Ignore bindings deletions if node is part of while's test, even when
+        del is in a nested block.
+        """
+        self.flakes('''
+        context = None
+        def _worker():
+            o = True
+            while o is not True:
+                while True:
+                    with context():
+                        del o
+                o = False
+        ''')
+
     def test_globalFromNestedScope(self):
         """Global names are available from nested scopes."""
         self.flakes('''
         a = 1
         def b():
             def c():
                 a
         ''')
@@ -192,17 +484,21 @@ class Test(TestCase):
                     x = 2 # line 5
                     def c():
                         x
                         x = 3
                         return x
                     return x
                 return x
         ''', m.UndefinedLocal).messages[0]
-        self.assertEqual(exc.message_args, ('x', 5))
+
+        # _DoctestMixin.flakes adds two lines preceding the code above.
+        expected_line_num = 7 if self.withDoctest else 5
+
+        self.assertEqual(exc.message_args, ('x', expected_line_num))
 
     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():
@@ -275,16 +571,52 @@ class Test(TestCase):
         print(a, b)
         ''')
         self.flakes('''
         a, *b, c = range(10)
         print(a, b, c)
         ''')
 
     @skipIf(version_info < (3,), 'new in Python 3')
+    def test_usedAsStarUnpack(self):
+        """
+        Star names in unpack are used if RHS is not a tuple/list literal.
+        """
+        self.flakes('''
+        def f():
+            a, *b = range(10)
+        ''')
+        self.flakes('''
+        def f():
+            (*a, b) = range(10)
+        ''')
+        self.flakes('''
+        def f():
+            [a, *b, c] = range(10)
+        ''')
+
+    @skipIf(version_info < (3,), 'new in Python 3')
+    def test_unusedAsStarUnpack(self):
+        """
+        Star names in unpack are unused if RHS is a tuple/list literal.
+        """
+        self.flakes('''
+        def f():
+            a, *b = any, all, 4, 2, 'un'
+        ''', m.UnusedVariable, m.UnusedVariable)
+        self.flakes('''
+        def f():
+            (*a, b) = [bool, int, float, complex]
+        ''', m.UnusedVariable, m.UnusedVariable)
+        self.flakes('''
+        def f():
+            [a, *b, c] = 9, 8, 7, 6, 5, 4
+        ''', m.UnusedVariable, m.UnusedVariable, m.UnusedVariable)
+
+    @skipIf(version_info < (3,), 'new in Python 3')
     def test_keywordOnlyArgs(self):
         """Keyword-only arg names are defined."""
         self.flakes('''
         def f(*, a, b=None):
             print(a, b)
         ''')
 
         self.flakes('''
@@ -323,18 +655,30 @@ class Test(TestCase):
         class A(metaclass=ABCMeta): pass
         ''')
 
     def test_definedInGenExp(self):
         """
         Using the loop variable of a generator expression results in no
         warnings.
         """
-        self.flakes('(a for a in %srange(10) if a)' %
-                    ('x' if version_info < (3,) else ''))
+        self.flakes('(a for a in [1, 2, 3] if a)')
+
+        self.flakes('(b for b in (a for a in [1, 2, 3] if a) if b)')
+
+    def test_undefinedInGenExpNested(self):
+        """
+        The loop variables of generator expressions nested together are
+        not defined in the other generator.
+        """
+        self.flakes('(b for b in (a for a in [1, 2, 3] if b) if b)',
+                    m.UndefinedName)
+
+        self.flakes('(b for b in (a for a in [1, 2, 3] if a) if a)',
+                    m.UndefinedName)
 
     def test_undefinedWithErrorHandler(self):
         """
         Some compatibility code checks explicitly for NameError.
         It should not trigger warnings.
         """
         self.flakes('''
         try:
@@ -379,16 +723,78 @@ class Test(TestCase):
             self.flakes('''
             class A:
                 T = range(10)
 
                 X = {x for x in T}
                 Y = {x:x for x in T}
             ''')
 
+    def test_definedInClassNested(self):
+        """Defined name for nested generator expressions in a class."""
+        self.flakes('''
+        class A:
+            T = range(10)
+
+            Z = (x for x in (a for a in T))
+        ''')
+
+    def test_undefinedInLoop(self):
+        """
+        The loop variable is defined after the expression is computed.
+        """
+        self.flakes('''
+        for i in range(i):
+            print(i)
+        ''', m.UndefinedName)
+        self.flakes('''
+        [42 for i in range(i)]
+        ''', m.UndefinedName)
+        self.flakes('''
+        (42 for i in range(i))
+        ''', m.UndefinedName)
+
+    @skipIf(version_info < (2, 7), 'Dictionary comprehensions do not exist')
+    def test_definedFromLambdaInDictionaryComprehension(self):
+        """
+        Defined name referenced from a lambda function within a dict/set
+        comprehension.
+        """
+        self.flakes('''
+        {lambda: id(x) for x in range(10)}
+        ''')
+
+    def test_definedFromLambdaInGenerator(self):
+        """
+        Defined name referenced from a lambda function within a generator
+        expression.
+        """
+        self.flakes('''
+        any(lambda: id(x) for x in range(10))
+        ''')
+
+    @skipIf(version_info < (2, 7), 'Dictionary comprehensions do not exist')
+    def test_undefinedFromLambdaInDictionaryComprehension(self):
+        """
+        Undefined name referenced from a lambda function within a dict/set
+        comprehension.
+        """
+        self.flakes('''
+        {lambda: id(y) for x in range(10)}
+        ''', m.UndefinedName)
+
+    def test_undefinedFromLambdaInComprehension(self):
+        """
+        Undefined name referenced from a lambda function within a generator
+        expression.
+        """
+        self.flakes('''
+        any(lambda: id(y) for x in range(10))
+        ''', m.UndefinedName)
+
 
 class NameTests(TestCase):
     """
     Tests for some extra cases of name handling.
     """
     def test_impossibleContext(self):
         """
         A Name node with an unrecognized context results in a RuntimeError being
--- a/pylib/pyflakes/setup.cfg
+++ b/pylib/pyflakes/setup.cfg
@@ -1,5 +1,8 @@
+[wheel]
+universal = 1
+
 [egg_info]
 tag_build = 
 tag_date = 0
 tag_svn_revision = 0
 
--- a/pylib/pyflakes/setup.py
+++ b/pylib/pyflakes/setup.py
@@ -35,21 +35,19 @@ def get_long_description():
 
 
 setup(
     name="pyflakes",
     license="MIT",
     version=get_version(),
     description="passive checker of Python programs",
     long_description=get_long_description(),
-    author="Phil Frost",
-    author_email="indigo@bitglue.com",
-    maintainer="Florent Xicluna",
-    maintainer_email="pyflakes-dev@lists.launchpad.net",
-    url="https://launchpad.net/pyflakes",
+    author="A lot of people",
+    author_email="code-quality@python.org",
+    url="https://github.com/PyCQA/pyflakes",
     packages=["pyflakes", "pyflakes.scripts", "pyflakes.test"],
     classifiers=[
         "Development Status :: 6 - Mature",
         "Environment :: Console",
         "Intended Audience :: Developers",
         "License :: OSI Approved :: MIT License",
         "Programming Language :: Python",
         "Programming Language :: Python :: 2",
--- a/test-requirements.txt
+++ b/test-requirements.txt
@@ -144,18 +144,18 @@ pyasn1==0.1.9 \
     --hash=sha256:28fee44217991cfad9e6a0b9f7e3f26041e21ebc96629e94e585ccd05d49fa65
 
 pycodestyle==2.2.0 \
     --hash=sha256:60c4e1c36f301ac539a550a29e9d16862069ec240472d86e5e71c4fc645829cb
 
 pycparser==2.14 \
     --hash=sha256:7959b4a74abdc27b312fed1c21e6caf9309ce0b29ea86b591fd2e99ecdf27f73
 
-pyflakes==0.8.1 \
-    --hash=sha256:ac4571695c10ce1536bcdba1a294b9f2d3e6cc9d0ea171b67d50a0864ce3e042
+pyflakes==1.5.0 \
+    --hash=sha256:cc5eadfb38041f8366128786b4ca12700ed05bbf1403d808e89d57d67a3875a7
 
 Pygments==2.1.1 \
     --hash=sha256:05aee25c433d6155defbfbcb6c2e2b0ebf29d28138604867b62a304bd6bbb41d
 
 pyOpenSSL==0.15.1 \
     --hash=sha256:88e45e6bb25dfed272a1ef2e728461d44b634c2cd689e989b6e56a349c5a3ae5
 
 pytest==3.0.2 \