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 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.
If we wanted the extension or a check to be optional, you can add
off_by_default = True
to our entry point. For example, we could
update mccabe.py
with this variable as shown below:
# https://github.com/flintwork/mccabe/blob/0.2/mccabe.py#L225:L254
class McCabeChecker(object):
"""McCabe cyclomatic complexity checker."""
name = 'mccabe'
version = __version__
off_by_default = True
If we wanted to run the optional extension or check, we need to specify the
error and warnings via the --enable-extension
command line argument. In our
case, we could run flake8 --enable-extension=C90
which would enable our
off_by_default example version of the mccabe 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: