Configuring Flake8

Once you have learned how to invoke Flake8, you will soon want to learn how to configure it so you do not have to specify the same options every time you use it.

This section will show you how to make

flake8

Remember that you want to specify certain options without writing

flake8 --select E123,W456 --enable-extensions H111

Configuration Locations

Flake8 supports storing its configuration in your project in one of setup.cfg, tox.ini, or .flake8.

Values set at the command line have highest priority, then those in the project configuration file, and finally there are the defaults. However, there are additional command line options which can alter this.

Project Configuration

Flake8 is written with the understanding that people organize projects into sub-directories. Let’s take for example Flake8’s own project structure

flake8
├── docs
│   ├── build
│   └── source
│       ├── _static
│       ├── _templates
│       ├── dev
│       ├── internal
│       └── user
├── flake8
│   ├── formatting
│   ├── main
│   ├── options
│   └── plugins
└── tests
    ├── fixtures
    │   └── config_files
    ├── integration
    └── unit

In the top-level flake8 directory (which contains docs, flake8, and tests) there’s also tox.ini and setup.cfg files. In our case, we keep our Flake8 configuration in tox.ini. Regardless of whether you keep your config in .flake8, setup.cfg, or tox.ini we expect you to use INI to configure Flake8 (since each of these files already uses INI as a format). This means that any Flake8 configuration you wish to set needs to be in the flake8 section, which means it needs to start like so:

[flake8]

Each command-line option that you want to specify in your config file can be named in either of two ways:

  1. Using underscores (_) instead of hyphens (-)

  2. Simply using hyphens (without the leading hyphens)

Note

Not every Flake8 command-line option can be specified in the configuration file. See our list of options to determine which options will be parsed from the configuration files.

Let’s actually look at Flake8’s own configuration section:

[flake8]
extend-ignore = E203
exclude = .git,__pycache__,docs/source/conf.py,old,build,dist
max-complexity = 10

This is equivalent to:

flake8 --extend-ignore E203 \
         --exclude .git,__pycache__,docs/source/conf.py,old,build,dist \
         --max-complexity 10

In our case, if we wanted to, we could also do

[flake8]
extend-ignore = E203
exclude =
    .git,
    __pycache__,
    docs/source/conf.py,
    old,
    build,
    dist
max-complexity = 10

This allows us to add comments for why we’re excluding items, e.g.

[flake8]
extend-ignore = E203
exclude =
    # No need to traverse our git directory
    .git,
    # There's no value in checking cache directories
    __pycache__,
    # The conf file is mostly autogenerated, ignore it
    docs/source/conf.py,
    # The old directory contains Flake8 2.0
    old,
    # This contains our built documentation
    build,
    # This contains builds of flake8 that we don't want to check
    dist
max-complexity = 10

Note

Following the recommended settings for Python’s configparser, Flake8 does not support inline comments for any of the keys. So while this is fine:

[flake8]
per-file-ignores =
    # imported but unused
    __init__.py: F401

this is not:

[flake8]
per-file-ignores =
    __init__.py: F401 # imported but unused

Note

If you’re using Python 2, you will notice that we download the configparser backport from PyPI. That backport enables us to support this behaviour on all supported versions of Python.

Please do not open issues about this dependency to Flake8.

Note

You can also specify --max-complexity as max_complexity = 10.

This is also useful if you have a long list of error codes to ignore. Let’s look at a portion of a project’s Flake8 configuration in their tox.ini:

[flake8]
# it's not a bug that we aren't using all of hacking, ignore:
# H101: Use TODO(NAME)
# H202: assertRaises Exception too broad
# H233: Python 3.x incompatible use of print operator
# H301: one import per line
# H306: imports not in alphabetical order (time, os)
# H401: docstring should not start with a space
# H403: multi line docstrings should end on a new line
# H404: multi line docstring should start without a leading new line
# H405: multi line docstring summary not separated with an empty line
# H501: Do not use self.__dict__ for string formatting
extend-ignore = H101,H202,H233,H301,H306,H401,H403,H404,H405,H501

They use the comments to describe the check but they could also write this as:

[flake8]
# it's not a bug that we aren't using all of hacking
extend-ignore =
    # H101: Use TODO(NAME)
    H101,
    # H202: assertRaises Exception too broad
    H202,
    # H233: Python 3.x incompatible use of print operator
    H233,
    # H301: one import per line
    H301,
    # H306: imports not in alphabetical order (time, os)
    H306,
    # H401: docstring should not start with a space
    H401,
    # H403: multi line docstrings should end on a new line
    H403,
    # H404: multi line docstring should start without a leading new line
    H404,
    # H405: multi line docstring summary not separated with an empty line
    H405,
    # H501: Do not use self.__dict__ for string formatting
    H501

Or they could use each comment to describe why they’ve ignored the check. Flake8 knows how to parse these lists and will appropriately handle these situations.

Using Local Plugins

New in version 3.5.0.

Flake8 allows users to write plugins that live locally in a project. These plugins do not need to use setuptools or any of the other overhead associated with plugins distributed on PyPI. To use these plugins, users must specify them in their configuration file (i.e., .flake8, setup.cfg, or tox.ini). This must be configured in a separate INI section named flake8:local-plugins.

Users may configure plugins that check source code, i.e., extension plugins, and plugins that report errors, i.e., report plugins.

An example configuration might look like:

[flake8:local-plugins]
extension =
    MC1 = project.flake8.checkers:MyChecker1
    MC2 = project.flake8.checkers:MyChecker2
report =
    MR1 = project.flake8.reporters:MyReporter1
    MR2 = project.flake8.reporters:MyReporter2

Flake8 will also, however, allow for commas to separate the plugins for example:

[flake8:local-plugins]
extension =
    MC1 = project.flake8.checkers:MyChecker1,
    MC2 = project.flake8.checkers:MyChecker2
report =
    MR1 = project.flake8.reporters:MyReporter1,
    MR2 = project.flake8.reporters:MyReporter2

These configurations will allow you to select your own custom reporter plugin that you’ve designed or will utilize your new check classes.

If your package is installed in the same virtualenv that Flake8 will run from, and your local plugins are part of that package, you’re all set; Flake8 will be able to import your local plugins. However, if you are working on a project that isn’t set up as an installable package, or Flake8 doesn’t run from the same virtualenv your code runs in, you may need to tell Flake8 where to import your local plugins from. You can do this via the paths option in the local-plugins section of your config:

[flake8:local-plugins]
extension =
  MC1 = myflake8plugin:MyChecker1
paths =
  ./path/to

Relative paths will be interpreted relative to the config file. Multiple paths can be listed (comma separated just like exclude) as needed. If your local plugins have any dependencies, it’s up to you to ensure they are installed in whatever Python environment Flake8 runs in.

Note

These plugins otherwise follow the same guidelines as regular plugins.