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
.
via Setuptools¶
If you’re invoking Flake8 from your setup.py
then you actually end up in
flake8.main.setuptools_command.Flake8.run()
. This then collects the
files that are included in the package information and creates an instance of
Application
.
via Git or Mercurial¶
In both cases, they call their respective hook
functions which create
instances 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.