Skip to content

Create sharable configuration presets for Flake8 #1105

Open
@asottile

Description

In GitLab by @sobolevn on Jul 20, 2019, 02:35

Problem

I am writing quite a complex plugin with lots of configuration options.
Moreover, I also depend on a lot of other plugins as dependencies.

Here's how my configuration looks like for an end user, contents of setup.cfg:

[flake8]
# Base flake8 configuration:
format = wemake
show-source = True
statistics = False
doctests = True
enable-extensions = G

# Plugins:
accept-encodings = utf-8
max-complexity = 6
max-line-length = 80
quotes = single

# Self settings:
max-imports = 14


# Exclude some pydoctest checks globally:
ignore = D100, D104, D401, W504, RST303, RST304

[isort]
# See https://github.com/timothycrosley/isort#multi-line-output-modes
multi_line_output = 3
include_trailing_comma = true
default_section = FIRSTPARTY
# Is the same as 80 in flake8:
line_length = 79

Notice, that I also use flake8-isort and [isort] option, there also might be other sections like [mypy] for flake8-mypy, or [bandit] for flake8-bandit or any other plugins when flake8 acts like a wrapper for other tools.

Currently, we will only talk about [flake8] section, since sadly we are not responsible for other tools.

I do not want my users to copy-paste these settings for several reasons:

  1. They usually make mistakes in this simple action :slight_smile:
  2. I am losing control over the default configuration: I will not be able to change something in their defaults even if I want to
  3. It brings a lot of copy-paste. That's totally inconvenient to use and maintain. One new feature or a bug might force you to go trough all your X project and edit the configuration.

Real world use-cases

Several other linters have this feature. Some of them even consider it as a key feature.

When working for EsLint for example, one can just create a module with a single javascript file and reuse it everywhere.

I propose the same for flake8.
Each user can create its own set of rules for an organisation / set of projects and reuse it without this amount of copy-paste.

Implementation details

Things to point out:

  1. It is not a breaking change, everything so work as-is, no major version bump is required
  2. Without new feature everything should work as-is
  3. New configuration option should take the lowest priority over existing config options

Configuration priority

Higher takes the priority over lower:

  1. CLI flags
  2. setup.cfg / .flake8
  3. New option: --sharable-configuration

Creating new sharable configuration

I guess that reusing entry points here is the best option.

# setup.py
# ...

setup(
   name='my-flake8-config'
   entry_points={
        'flake8.configuration': [
            'myconfig = some.path:ConfigurationClass',
        ],
    },

Then:

  1. Installing: pip install my-flake8-config
  2. Running: flake8 --sharable-configuration=myconfig
  3. Done!

Configuration class API

I am not sure about this. But my vision would be something like:

# some/path.py

class ConfigurationClass(object):
    def sharable_configuration(self):
        return {
           'quotes': 'single',
           # and any other options for `[flake8]` section
        }

Conclusion

This feature allows to transfer configuration in a reliable and clean way, brings no breaking changes, follows the best practices of other lint tools.

Original issue from wemake-python-styleguide: wemake-services/wemake-python-styleguide#164
The same feature I proposed for isort: PyCQA/isort#970

I am super excited to help!

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions