1
"""Plugin built-in to Flake8 to treat pyflakes as a plugin."""
2
# -*- coding: utf-8 -*-
3
from __future__ import absolute_import
6
# The 'demandimport' breaks pyflakes and flake8.plugins.pyflakes
7
from mercurial import demandimport
11
demandimport.disable()
15
import pyflakes.checker
17
from flake8 import utils
20
FLAKE8_PYFLAKES_CODES = dict([line.split()[::-1] for line in (
22
'F402 ImportShadowedByLoopVar',
23
'F403 ImportStarUsed',
24
'F404 LateFutureImport',
25
'F405 ImportStarUsage',
26
'F406 ImportStarNotPermitted',
27
'F407 FutureFeatureNotDefined',
28
'F601 MultiValueRepeatedKeyLiteral',
29
'F602 MultiValueRepeatedKeyVariable',
30
'F621 TooManyExpressionsInStarredAssignment',
31
'F622 TwoStarredExpressions',
33
'F701 BreakOutsideLoop',
34
'F702 ContinueOutsideLoop',
35
'F703 ContinueInFinally',
36
'F704 YieldOutsideFunction',
37
'F705 ReturnWithArgsInsideGenerator',
38
'F706 ReturnOutsideFunction',
39
'F707 DefaultExceptNotLast',
40
'F721 DoctestSyntaxError',
41
'F811 RedefinedWhileUnused',
42
'F812 RedefinedInListComp',
44
'F822 UndefinedExport',
45
'F823 UndefinedLocal',
46
'F831 DuplicateArgument',
47
'F841 UnusedVariable',
52
"""Add error codes to Pyflakes messages."""
53
for name, obj in vars(pyflakes.messages).items():
54
if name[0].isupper() and obj.message:
55
obj.flake8_msg = '%s %s' % (
56
FLAKE8_PYFLAKES_CODES.get(name, 'F999'), obj.message
63
class FlakesChecker(pyflakes.checker.Checker):
64
"""Subclass the Pyflakes checker to conform with the flake8 API."""
67
version = pyflakes.__version__
69
include_in_doctest = []
70
exclude_from_doctest = []
72
def __init__(self, tree, filename):
73
"""Initialize the PyFlakes plugin with an AST tree and filename."""
74
filename = utils.normalize_paths(filename)[0]
75
with_doctest = self.with_doctest
76
included_by = [include for include in self.include_in_doctest
77
if include != '' and filename.startswith(include)]
81
for exclude in self.exclude_from_doctest:
82
if exclude != '' and filename.startswith(exclude):
84
overlaped_by = [include for include in included_by
85
if include.startswith(exclude)]
90
super(FlakesChecker, self).__init__(tree, filename,
91
withDoctest=with_doctest)
94
def add_options(cls, parser):
95
"""Register options for PyFlakes on the Flake8 OptionManager."""
97
'--builtins', parse_from_config=True, comma_separated_list=True,
98
help="define more built-ins, comma separated",
101
'--doctests', default=False, action='store_true',
102
parse_from_config=True,
103
help="check syntax of the doctests",
106
'--include-in-doctest', default='',
107
dest='include_in_doctest', parse_from_config=True,
108
comma_separated_list=True, normalize_paths=True,
109
help='Run doctests only on these files',
113
'--exclude-from-doctest', default='',
114
dest='exclude_from_doctest', parse_from_config=True,
115
comma_separated_list=True, normalize_paths=True,
116
help='Skip these files when running doctests',
121
def parse_options(cls, options):
122
"""Parse option values from Flake8's OptionManager."""
124
cls.builtIns = cls.builtIns.union(options.builtins)
125
cls.with_doctest = options.doctests
128
for included_file in options.include_in_doctest:
129
if included_file == '':
131
if not included_file.startswith((os.sep, './', '~/')):
132
included_files.append('./' + included_file)
134
included_files.append(included_file)
135
cls.include_in_doctest = utils.normalize_paths(included_files)
138
for excluded_file in options.exclude_from_doctest:
139
if excluded_file == '':
141
if not excluded_file.startswith((os.sep, './', '~/')):
142
excluded_files.append('./' + excluded_file)
144
excluded_files.append(excluded_file)
145
cls.exclude_from_doctest = utils.normalize_paths(excluded_files)
147
inc_exc = set(cls.include_in_doctest).intersection(
148
cls.exclude_from_doctest
151
raise ValueError('"%s" was specified in both the '
152
'include-in-doctest and exclude-from-doctest '
153
'options. You are not allowed to specify it in '
154
'both for doctesting.' % inc_exc)
157
"""Run the plugin."""
158
for message in self.messages:
159
col = getattr(message, 'col', 0)
160
yield (message.lineno,
162
(message.flake8_msg % message.message_args),