Source

flake8 / docs / extensions.rst

Writing an Extension for Flake8

Since Flake8 is now adding support for extensions, we require setuptools so we can manage extensions through entry points. If you are making an existing tool compatible with Flake8 but do not already require setuptools, you should probably add it to your list of requirements. Next, you'll need to edit your setup.py file so that upon installation, your extension is registered. If you define a class called PackageEntryClass then this would look something like the following:

setup(
    # ...
    entry_points={
        'flake8.extension': ['P10 = package.PackageEntryClass'],
    }
    # ...
)

If you intend to publish your extension, choose a unique code prefix following the convention for :ref:`error codes <error-codes>`. In addition, you can open a request in the issue tracker to register the prefix in the documentation.

A real example: McCabe

Below is an example from mccabe for how to write your setup.py file for your Flake8 extension.

# https://github.com/flintwork/mccabe/blob/0.2/setup.py#L38:L42
# -*- coding: utf-8 -*-
from setuptools import setup

# ...

setup(
    name='mccabe',

    # ...

    install_requires=[
        'setuptools',
    ],
    entry_points={
        'flake8.extension': [
            'C90 = mccabe:McCabeChecker',
        ],
    },

    # ...

)

In mccabe.py you can see that extra options are added to the parser when flake8 registers the extension:

# https://github.com/flintwork/mccabe/blob/0.2/mccabe.py#L225:L254
class McCabeChecker(object):
    """McCabe cyclomatic complexity checker."""
    name = 'mccabe'
    version = __version__
    _code = 'C901'
    _error_tmpl = "C901 %r is too complex (%d)"
    max_complexity = 0

    def __init__(self, tree, filename):
        self.tree = tree

    @classmethod
    def add_options(cls, parser):
        parser.add_option('--max-complexity', default=-1, action='store',
                          type='int', help="McCabe complexity threshold")
        parser.config_options.append('max-complexity')

    @classmethod
    def parse_options(cls, options):
        cls.max_complexity = options.max_complexity

    def run(self):
        if self.max_complexity < 0:
            return
        visitor = PathGraphingAstVisitor()
        visitor.preorder(self.tree, visitor)
        for graph in visitor.graphs.values():
            if graph.complexity() >= self.max_complexity:
                text = self._error_tmpl % (graph.entity, graph.complexity())
                yield graph.lineno, 0, text, type(self)

Since that is the defined entry point in the above setup.py, flake8 finds it and uses it to register the extension.

Existing Extensions

This is not at all a comprehensive listing of existing extensions but simply a listing of the ones we are aware of:

Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.