summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLukasz Langa <ambv@fb.com>2016-11-27 17:42:00 -0800
committerLukasz Langa <ambv@fb.com>2016-11-28 10:34:38 -0800
commit2f1338c34277a39bd0f49145c372c804cd79552e (patch)
treed39043687f42fb676118060b7d45efb794afad7a
parentb8ce1334d099aee9c7d2ea72f75bf01ccbe2b040 (diff)
downloadflake8-2f1338c34277a39bd0f49145c372c804cd79552e.tar.gz
Assign missing codes to PyFlakes messages
Some PyFlakes messages weren't covered by unique messages, making them impossible to select/ignore. This is now fixed. To ensure we don't regress in the future, a test has been added that fails if there's any uncovered messages.
-rw-r--r--docs/source/release-notes/3.3.0.rst3
-rw-r--r--docs/source/user/error-codes.rst34
-rw-r--r--src/flake8/plugins/pyflakes.py51
-rw-r--r--tests/unit/test_pyflakes_codes.py15
4 files changed, 85 insertions, 18 deletions
diff --git a/docs/source/release-notes/3.3.0.rst b/docs/source/release-notes/3.3.0.rst
index ed9f171..fc7c2f4 100644
--- a/docs/source/release-notes/3.3.0.rst
+++ b/docs/source/release-notes/3.3.0.rst
@@ -6,6 +6,9 @@ You can view the `3.3.0 milestone`_ on GitLab for more details.
- Fix problem where hooks should only check \*.py files. (See also
`GitLab#268`_)
+- Added unique error codes for all missing PyFlakes messages (14 new
+ codes, see all :ref:`Error / Violation Codes <error_codes>`)
+
.. links
.. _3.3.0 milestone:
https://gitlab.com/pycqa/flake8/milestones/16
diff --git a/docs/source/user/error-codes.rst b/docs/source/user/error-codes.rst
index 8bff640..dbaf35e 100644
--- a/docs/source/user/error-codes.rst
+++ b/docs/source/user/error-codes.rst
@@ -1,3 +1,5 @@
+.. _error_codes:
+
=========================
Error / Violation Codes
=========================
@@ -22,6 +24,36 @@ generates its own :term:`error code`\ s for ``pyflakes``:
+------+---------------------------------------------------------------------+
| F405 | ``name`` may be undefined, or defined from star imports: ``module`` |
+------+---------------------------------------------------------------------+
+| F406 | 'from ``module`` import \*' only allowed at module level |
++------+---------------------------------------------------------------------+
+| F407 | an undefined ``__future__`` feature name was imported |
++------+---------------------------------------------------------------------+
++------+---------------------------------------------------------------------+
+| F601 | dictionary key ``name`` repeated with different values |
++------+---------------------------------------------------------------------+
+| F602 | dictionary key variable ``name`` repeated with different values |
++------+---------------------------------------------------------------------+
+| F621 | too many expressions in an assignment with star-unpacking |
++------+---------------------------------------------------------------------+
+| F622 | two or more starred expressions in an assignment ``(a, *b, *c = d)``|
++------+---------------------------------------------------------------------+
+| F631 | assertion test is a tuple, which are always ``True`` |
++------+---------------------------------------------------------------------+
++------+---------------------------------------------------------------------+
+| F701 | a ``break`` statement outside of a ``while`` or ``for`` loop |
++------+---------------------------------------------------------------------+
+| F702 | a ``continue`` statement outside of a ``while`` or ``for`` loop |
++------+---------------------------------------------------------------------+
+| F703 | a ``continue`` statement in a ``finally`` block in a loop |
++------+---------------------------------------------------------------------+
+| F704 | a ``yield`` or ``yield from`` statement outside of a function |
++------+---------------------------------------------------------------------+
+| F705 | a ``return`` statement with arguments inside a generator |
++------+---------------------------------------------------------------------+
+| F706 | a ``return`` statement outside of a function/method |
++------+---------------------------------------------------------------------+
+| F707 | an ``except:`` block as not the last exception handler |
++------+---------------------------------------------------------------------+
+------+---------------------------------------------------------------------+
| F811 | redefinition of unused ``name`` from line ``N`` |
+------+---------------------------------------------------------------------+
@@ -29,7 +61,7 @@ generates its own :term:`error code`\ s for ``pyflakes``:
+------+---------------------------------------------------------------------+
| F821 | undefined name ``name`` |
+------+---------------------------------------------------------------------+
-| F822 | undefined name ``name`` in __all__ |
+| F822 | undefined name ``name`` in ``__all__`` |
+------+---------------------------------------------------------------------+
| F823 | local variable ``name`` ... referenced before assignment |
+------+---------------------------------------------------------------------+
diff --git a/src/flake8/plugins/pyflakes.py b/src/flake8/plugins/pyflakes.py
index ca22302..65a31d0 100644
--- a/src/flake8/plugins/pyflakes.py
+++ b/src/flake8/plugins/pyflakes.py
@@ -17,27 +17,44 @@ import pyflakes.checker
from flake8 import utils
+FLAKE8_PYFLAKES_CODES = dict([line.split()[::-1] for line in (
+ 'F401 UnusedImport',
+ 'F402 ImportShadowedByLoopVar',
+ 'F403 ImportStarUsed',
+ 'F404 LateFutureImport',
+ 'F405 ImportStarUsage',
+ 'F406 ImportStarNotPermitted',
+ 'F407 FutureFeatureNotDefined',
+ 'F601 MultiValueRepeatedKeyLiteral',
+ 'F602 MultiValueRepeatedKeyVariable',
+ 'F621 TooManyExpressionsInStarredAssignment',
+ 'F622 TwoStarredExpressions',
+ 'F631 AssertTuple',
+ 'F701 BreakOutsideLoop',
+ 'F702 ContinueOutsideLoop',
+ 'F703 ContinueInFinally',
+ 'F704 YieldOutsideFunction',
+ 'F705 ReturnWithArgsInsideGenerator',
+ 'F706 ReturnOutsideFunction',
+ 'F707 DefaultExceptNotLast',
+ 'F721 DoctestSyntaxError',
+ 'F811 RedefinedWhileUnused',
+ 'F812 RedefinedInListComp',
+ 'F821 UndefinedName',
+ 'F822 UndefinedExport',
+ 'F823 UndefinedLocal',
+ 'F831 DuplicateArgument',
+ 'F841 UnusedVariable',
+)])
+
+
def patch_pyflakes():
"""Add error codes to Pyflakes messages."""
- codes = dict([line.split()[::-1] for line in (
- 'F401 UnusedImport',
- 'F402 ImportShadowedByLoopVar',
- 'F403 ImportStarUsed',
- 'F404 LateFutureImport',
- 'F405 ImportStarUsage',
- 'F810 Redefined',
- 'F811 RedefinedWhileUnused',
- 'F812 RedefinedInListComp',
- 'F821 UndefinedName',
- 'F822 UndefinedExport',
- 'F823 UndefinedLocal',
- 'F831 DuplicateArgument',
- 'F841 UnusedVariable',
- )])
-
for name, obj in vars(pyflakes.messages).items():
if name[0].isupper() and obj.message:
- obj.flake8_msg = '%s %s' % (codes.get(name, 'F999'), obj.message)
+ obj.flake8_msg = '%s %s' % (
+ FLAKE8_PYFLAKES_CODES.get(name, 'F999'), obj.message
+ )
patch_pyflakes()
diff --git a/tests/unit/test_pyflakes_codes.py b/tests/unit/test_pyflakes_codes.py
new file mode 100644
index 0000000..837e971
--- /dev/null
+++ b/tests/unit/test_pyflakes_codes.py
@@ -0,0 +1,15 @@
+"""Tests of pyflakes monkey patches."""
+
+import pyflakes
+
+from flake8.plugins import pyflakes as pyflakes_shim
+
+
+def test_all_pyflakes_messages_have_flake8_codes_assigned():
+ """Verify all PyFlakes messages have error codes assigned."""
+ messages = {
+ name
+ for name, obj in vars(pyflakes.messages).items()
+ if name[0].isupper() and obj.message
+ }
+ assert messages == set(pyflakes_shim.FLAKE8_PYFLAKES_CODES)