]>
crepu.dev Git - config.git/blob - djavu-asus/elpy/rpc-venv/lib/python3.11/site-packages/flake8/formatting/base.py
1 """The base class and interface for all formatting plugins."""
2 from __future__
import annotations
9 from flake8
.formatting
import _windows_color
10 from flake8
.statistics
import Statistics
11 from flake8
.violation
import Violation
15 """Class defining the formatter interface.
17 .. attribute:: options
19 The options parsed from both configuration files and the command-line.
21 .. attribute:: filename
23 If specified by the user, the path to store the results of the run.
25 .. attribute:: output_fd
27 Initialized when the :meth:`start` is called. This will be a file
28 object opened for writing.
30 .. attribute:: newline
32 The string to add to the end of a line. This is only used when the
33 output filename has been specified.
36 def __init__(self
, options
: argparse
.Namespace
) -> None:
37 """Initialize with the options parsed from config and cli.
39 This also calls a hook, :meth:`after_init`, so subclasses do not need
40 to call super to call this method.
43 User specified configuration parsed from both configuration files
44 and the command-line interface.
46 self
.options
= options
47 self
.filename
= options
.output_file
48 self
.output_fd
: IO
[str] |
None = None
50 self
.color
= options
.color
== "always" or (
51 options
.color
== "auto"
52 and sys
.stdout
.isatty()
53 and _windows_color
.terminal_supports_color
57 def after_init(self
) -> None:
58 """Initialize the formatter further."""
60 def beginning(self
, filename
: str) -> None:
61 """Notify the formatter that we're starting to process a file.
64 The name of the file that Flake8 is beginning to report results
68 def finished(self
, filename
: str) -> None:
69 """Notify the formatter that we've finished processing a file.
72 The name of the file that Flake8 has finished reporting results
76 def start(self
) -> None:
77 """Prepare the formatter to receive input.
79 This defaults to initializing :attr:`output_fd` if :attr:`filename`
82 dirname
= os
.path
.dirname(os
.path
.abspath(self
.filename
))
83 os
.makedirs(dirname
, exist_ok
=True)
84 self
.output_fd
= open(self
.filename
, "a")
86 def handle(self
, error
: Violation
) -> None:
87 """Handle an error reported by Flake8.
89 This defaults to calling :meth:`format`, :meth:`show_source`, and
90 then :meth:`write`. To extend how errors are handled, override this
94 This will be an instance of
95 :class:`~flake8.violation.Violation`.
97 line
= self
.format(error
)
98 source
= self
.show_source(error
)
99 self
.write(line
, source
)
101 def format(self
, error
: Violation
) -> str |
None:
102 """Format an error reported by Flake8.
104 This method **must** be implemented by subclasses.
107 This will be an instance of
108 :class:`~flake8.violation.Violation`.
110 The formatted error string.
112 raise NotImplementedError(
113 "Subclass of BaseFormatter did not implement" " format."
116 def show_statistics(self
, statistics
: Statistics
) -> None:
117 """Format and print the statistics."""
118 for error_code
in statistics
.error_codes():
119 stats_for_error_code
= statistics
.statistics_for(error_code
)
120 statistic
= next(stats_for_error_code
)
121 count
= statistic
.count
122 count
+= sum(stat
.count
for stat
in stats_for_error_code
)
123 self
._write
(f
"{count:<5} {error_code} {statistic.message}")
125 def show_benchmarks(self
, benchmarks
: list[tuple[str, float]]) -> None:
126 """Format and print the benchmarks."""
127 # NOTE(sigmavirus24): The format strings are a little confusing, even
128 # to me, so here's a quick explanation:
129 # We specify the named value first followed by a ':' to indicate we're
130 # formatting the value.
131 # Next we use '<' to indicate we want the value left aligned.
132 # Then '10' is the width of the area.
133 # For floats, finally, we only want only want at most 3 digits after
134 # the decimal point to be displayed. This is the precision and it
135 # can not be specified for integers which is why we need two separate
137 float_format
= "{value:<10.3} {statistic}".format
138 int_format
= "{value:<10} {statistic}".format
139 for statistic
, value
in benchmarks
:
140 if isinstance(value
, int):
141 benchmark
= int_format(statistic
=statistic
, value
=value
)
143 benchmark
= float_format(statistic
=statistic
, value
=value
)
144 self
._write
(benchmark
)
146 def show_source(self
, error
: Violation
) -> str |
None:
147 """Show the physical line generating the error.
149 This also adds an indicator for the particular part of the line that
150 is reported as generating the problem.
153 This will be an instance of
154 :class:`~flake8.violation.Violation`.
156 The formatted error string if the user wants to show the source.
157 If the user does not want to show the source, this will return
160 if not self
.options
.show_source
or error
.physical_line
is None:
163 # Because column numbers are 1-indexed, we need to remove one to get
164 # the proper number of space characters.
166 c
if c
.isspace() else " "
167 for c
in error
.physical_line
[: error
.column_number
- 1]
169 # Physical lines have a newline at the end, no need to add an extra
171 return f
"{error.physical_line}{indent}^"
173 def _write(self
, output
: str) -> None:
174 """Handle logic of whether to use an output file or print()."""
175 if self
.output_fd
is not None:
176 self
.output_fd
.write(output
+ self
.newline
)
177 if self
.output_fd
is None or self
.options
.tee
:
178 sys
.stdout
.buffer.write(output
.encode() + self
.newline
.encode())
180 def write(self
, line
: str |
None, source
: str |
None) -> None:
181 """Write the line either to the output file or stdout.
183 This handles deciding whether to write to a file or print to standard
184 out for subclasses. Override this if you want behaviour that differs
188 The formatted string to print or write.
190 The source code that has been formatted and associated with the
198 def stop(self
) -> None:
199 """Clean up after reporting is finished."""
200 if self
.output_fd
is not None:
201 self
.output_fd
.close()
202 self
.output_fd
= None