==================================
 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<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:

.. 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 <flake8.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`
