================================== 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: .. prompt:: 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 |Flake8| declares in its :file:`setup.py`. This might look something like: .. code-block:: python #!/path/to/python # 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: .. prompt:: bash python -m flake8 Then you're relying on Python to find :mod:`flake8.__main__` and run that. In both cases, however, you end up in :func:`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 :meth:`~flake8.main.application.Application.run` which in turn calls: - :meth:`~flake8.main.application.Application.initialize` - :meth:`~flake8.main.application.Application.run_checks` - :meth:`~flake8.main.application.Application.report_errors` - :meth:`~flake8.main.application.Application.report_benchmarks` Our Git hook, however, runs these individually. Application Initialization -------------------------- :meth:`~flake8.main.application.Application.initialize` loads all of our :term:`plugin`\ s, registers the options for those plugins, parses the command-line arguments, makes our formatter (as selected by the user), makes our :class:`~flake8.style_guide.StyleGuide` and finally makes our :class:`file checker manager `. Running Our Checks ------------------ :meth:`~flake8.main.application.Application.run_checks` then creates an instance of :class:`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 :mod:`multiprocessing` **and** :option:`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 :term:`violation`\ s 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 :class:`~flake8.style_guide.StyleGuide`. This relies on a :class:`~flake8.style_guide.DecisionEngine` instance to determine whether the particular :term:`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., :option:`flake8 --benchmark`) then we print the benchmarks. Exiting ======= Once :meth:`~flake8.main.application.Application.run` has finished, we then call :meth:`~flake8.main.application.Application.exit` which looks at how many errors were reported and whether the user specified :option:`flake8 --exit-zero` and exits with the appropriate exit code. .. Replacements .. |Application| replace:: :class:`~flake8.main.application.Application`