Given 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.
The exact way that we end up in our main
function for Flake8 depends on how you invoke it. If you do something like:
bash
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 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:
bash
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 ~flake8.main.application.Application
.
When we create our ~flake8.main.application.Application
instance, we record the start time and parse our command-line arguments so we can configure the verbosity of 's logging. For the most part, every path then calls ~flake8.main.application.Application.run
which in turn calls:
~flake8.main.application.Application.initialize
~flake8.main.application.Application.run_checks
~flake8.main.application.Application.report_errors
~flake8.main.application.Application.report_benchmarks
Our Git hook, however, runs these individually.
~flake8.main.application.Application.initialize
loads all of our plugin
s, registers the options for those plugins, parses the command-line arguments, makes our formatter (as selected by the user), makes our ~flake8.style_guide.StyleGuide
and finally makes our file checker manager <flake8.checker.Manager>
.
~flake8.main.application.Application.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 violation
s in the main process. After the checks are done running, we record the end time.
Next, the application takes the violations from the file checker manager, and feeds them through the ~flake8.style_guide.StyleGuide
. This relies on a ~flake8.style_guide.DecisionEngine
instance to determine whether the particular error code
is selected or ignored and then appropriately sends it to the formatter (or not).
Finally, if the user has asked to see benchmarks (i.e., flake8
--benchmark
) then we print the benchmarks.
Once ~flake8.main.application.Application.run
has finished, we then call ~flake8.main.application.Application.exit
which looks at how many errors were reported and whether the user specified flake8
--exit-zero
and exits with the appropriate exit code.