Merge branch 'pyflakes_missing_codes' into 'master'

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.

See merge request !159
This commit is contained in:
Ian Cordasco 2016-11-29 13:02:15 +00:00
commit 348722d77b
4 changed files with 85 additions and 18 deletions

View file

@ -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

View file

@ -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 |
+------+---------------------------------------------------------------------+

View file

@ -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()

View file

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