What Happens When You Run Flake8
Given Flake8 3.0’s new organization and structure, it might be a bit much
for some people to understand what happens from when you call flake8
on the
command-line to when it completes. This section aims to give you something of
a technical overview of what exactly happens.
Invocation
The exact way that we end up in our main
function for Flake8 depends on
how you invoke it. If you do something like:
flake8
Then your shell looks up where flake8
the executable lives and executes
it. In almost every case, this is a tiny python script generated by
setuptools
using the console script entry points that Flake8 declares
in its setup.py
. This might look something like:
#!/path/to/python<version>
# EASY-INSTALL-ENTRY-SCRIPT: 'flake8==3.0.0','console_scripts','flake8'
__requires__ = 'flake8==3.0.0'
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.exit(
load_entry_point('flake8==3.0.0', 'console_scripts', 'flake8')()
)
If instead you invoke it like:
python -m flake8
Then you’re relying on Python to find flake8.__main__
and run that. In
both cases, however, you end up in flake8.main.cli.main()
. This is the
primary way that users will end up starting Flake8. This function creates an
instance of Application
.
Application Logic
When we create our Application
instance, we record the start time and parse
our command-line arguments so we can configure the verbosity of Flake8’s
logging. For the most part, every path then calls
run()
which in turn calls:
Our Git hook, however, runs these individually.
Application Initialization
initialize()
loads all of our
plugins, registers the options for those plugins, parses the
command-line arguments, makes our formatter (as selected by the user), makes
our StyleGuide
and finally makes our
file checker manager
.
Running Our Checks
run_checks()
then creates an
instance of flake8.checker.FileChecker
for each file to be checked
after aggregating all of the files that are not excluded and match the
provided file-patterns. Then, if we’re on a system that supports
multiprocessing
and flake8 --jobs
is either auto
or
a number greater than 1, we will begin processing the files in subprocesses.
Otherwise, we’ll run the checks in parallel.
After we start running the checks, we start aggregating the reported violations in the main process. After the checks are done running, we record the end time.
Reporting Violations
Next, the application takes the violations from the file checker manager, and
feeds them through the StyleGuide
. This
relies on a DecisionEngine
instance to determine
whether the particular error code is selected or ignored and then
appropriately sends it to the formatter (or not).
Reporting Benchmarks
Finally, if the user has asked to see benchmarks (i.e., flake8
--benchmark
) then we print the benchmarks.
Exiting
Once run()
has finished, we then
call exit()
which looks at how
many errors were reported and whether the user specified flake8
--exit-zero
and exits with the appropriate exit code.