]> crepu.dev Git - config.git/blob - djavu-asus/emacs/elpy/rpc-venv/lib/python3.11/site-packages/flake8/plugins/pyflakes.py
f62527e35a9c897b5514c1e562b517f608f5db4f
[config.git] / djavu-asus / emacs / elpy / rpc-venv / lib / python3.11 / site-packages / flake8 / plugins / pyflakes.py
1 """Plugin built-in to Flake8 to treat pyflakes as a plugin."""
2 from __future__ import annotations
3
4 import argparse
5 import ast
6 import logging
7 import os
8 from typing import Any
9 from typing import Generator
10
11 import pyflakes.checker
12
13 from flake8 import utils
14 from flake8.options.manager import OptionManager
15
16 LOG = logging.getLogger(__name__)
17
18 FLAKE8_PYFLAKES_CODES = {
19 "UnusedImport": "F401",
20 "ImportShadowedByLoopVar": "F402",
21 "ImportStarUsed": "F403",
22 "LateFutureImport": "F404",
23 "ImportStarUsage": "F405",
24 "ImportStarNotPermitted": "F406",
25 "FutureFeatureNotDefined": "F407",
26 "PercentFormatInvalidFormat": "F501",
27 "PercentFormatExpectedMapping": "F502",
28 "PercentFormatExpectedSequence": "F503",
29 "PercentFormatExtraNamedArguments": "F504",
30 "PercentFormatMissingArgument": "F505",
31 "PercentFormatMixedPositionalAndNamed": "F506",
32 "PercentFormatPositionalCountMismatch": "F507",
33 "PercentFormatStarRequiresSequence": "F508",
34 "PercentFormatUnsupportedFormatCharacter": "F509",
35 "StringDotFormatInvalidFormat": "F521",
36 "StringDotFormatExtraNamedArguments": "F522",
37 "StringDotFormatExtraPositionalArguments": "F523",
38 "StringDotFormatMissingArgument": "F524",
39 "StringDotFormatMixingAutomatic": "F525",
40 "FStringMissingPlaceholders": "F541",
41 "MultiValueRepeatedKeyLiteral": "F601",
42 "MultiValueRepeatedKeyVariable": "F602",
43 "TooManyExpressionsInStarredAssignment": "F621",
44 "TwoStarredExpressions": "F622",
45 "AssertTuple": "F631",
46 "IsLiteral": "F632",
47 "InvalidPrintSyntax": "F633",
48 "IfTuple": "F634",
49 "BreakOutsideLoop": "F701",
50 "ContinueOutsideLoop": "F702",
51 "YieldOutsideFunction": "F704",
52 "ReturnOutsideFunction": "F706",
53 "DefaultExceptNotLast": "F707",
54 "DoctestSyntaxError": "F721",
55 "ForwardAnnotationSyntaxError": "F722",
56 "RedefinedWhileUnused": "F811",
57 "UndefinedName": "F821",
58 "UndefinedExport": "F822",
59 "UndefinedLocal": "F823",
60 "DuplicateArgument": "F831",
61 "UnusedVariable": "F841",
62 "UnusedAnnotation": "F842",
63 "RaiseNotImplemented": "F901",
64 }
65
66
67 class FlakesChecker(pyflakes.checker.Checker):
68 """Subclass the Pyflakes checker to conform with the flake8 API."""
69
70 with_doctest = False
71 include_in_doctest: list[str] = []
72 exclude_from_doctest: list[str] = []
73
74 def __init__(self, tree: ast.AST, filename: str) -> None:
75 """Initialize the PyFlakes plugin with an AST tree and filename."""
76 filename = utils.normalize_path(filename)
77 with_doctest = self.with_doctest
78 included_by = [
79 include
80 for include in self.include_in_doctest
81 if include != "" and filename.startswith(include)
82 ]
83 if included_by:
84 with_doctest = True
85
86 for exclude in self.exclude_from_doctest:
87 if exclude != "" and filename.startswith(exclude):
88 with_doctest = False
89 overlapped_by = [
90 include
91 for include in included_by
92 if include.startswith(exclude)
93 ]
94
95 if overlapped_by:
96 with_doctest = True
97
98 super().__init__(tree, filename=filename, withDoctest=with_doctest)
99
100 @classmethod
101 def add_options(cls, parser: OptionManager) -> None:
102 """Register options for PyFlakes on the Flake8 OptionManager."""
103 parser.add_option(
104 "--builtins",
105 parse_from_config=True,
106 comma_separated_list=True,
107 help="define more built-ins, comma separated",
108 )
109 parser.add_option(
110 "--doctests",
111 default=False,
112 action="store_true",
113 parse_from_config=True,
114 help="also check syntax of the doctests",
115 )
116 parser.add_option(
117 "--include-in-doctest",
118 default="",
119 dest="include_in_doctest",
120 parse_from_config=True,
121 comma_separated_list=True,
122 normalize_paths=True,
123 help="Run doctests only on these files",
124 )
125 parser.add_option(
126 "--exclude-from-doctest",
127 default="",
128 dest="exclude_from_doctest",
129 parse_from_config=True,
130 comma_separated_list=True,
131 normalize_paths=True,
132 help="Skip these files when running doctests",
133 )
134
135 @classmethod
136 def parse_options(cls, options: argparse.Namespace) -> None:
137 """Parse option values from Flake8's OptionManager."""
138 if options.builtins:
139 cls.builtIns = cls.builtIns.union(options.builtins)
140 cls.with_doctest = options.doctests
141
142 if options.include_in_doctest or options.exclude_from_doctest:
143 LOG.warning(
144 "--include-in-doctest / --exclude-from-doctest will be "
145 "removed in a future version. see PyCQA/flake8#1747"
146 )
147
148 included_files = []
149 for included_file in options.include_in_doctest:
150 if included_file == "":
151 continue
152 if not included_file.startswith((os.sep, "./", "~/")):
153 included_files.append(f"./{included_file}")
154 else:
155 included_files.append(included_file)
156 cls.include_in_doctest = utils.normalize_paths(included_files)
157
158 excluded_files = []
159 for excluded_file in options.exclude_from_doctest:
160 if excluded_file == "":
161 continue
162 if not excluded_file.startswith((os.sep, "./", "~/")):
163 excluded_files.append(f"./{excluded_file}")
164 else:
165 excluded_files.append(excluded_file)
166 cls.exclude_from_doctest = utils.normalize_paths(excluded_files)
167
168 inc_exc = set(cls.include_in_doctest).intersection(
169 cls.exclude_from_doctest
170 )
171 if inc_exc:
172 raise ValueError(
173 f"{inc_exc!r} was specified in both the "
174 f"include-in-doctest and exclude-from-doctest "
175 f"options. You are not allowed to specify it in "
176 f"both for doctesting."
177 )
178
179 def run(self) -> Generator[tuple[int, int, str, type[Any]], None, None]:
180 """Run the plugin."""
181 for message in self.messages:
182 col = getattr(message, "col", 0)
183 yield (
184 message.lineno,
185 col,
186 "{} {}".format(
187 FLAKE8_PYFLAKES_CODES.get(type(message).__name__, "F999"),
188 message.message % message.message_args,
189 ),
190 message.__class__,
191 )