summaryrefslogtreecommitdiff
path: root/docs/extensions.rst
blob: 78020422b503af865f896ccf597b5ea2511203fb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
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
<https://bitbucket.org/tarek/flake8/issues>`_ to register the prefix in the
documentation.

.. TODO: describe the API required for the 3 kind of extensions:
   * physical line checkers
   * logical line checkers
   * AST checkers


A real example: McCabe
----------------------

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

.. code-block:: python

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

.. code-block:: python

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

* `flake8-debugger <https://github.com/JBKahn/flake8-debugger>`_

* `flake8-immediate <https://github.com/schlamar/flake8-immediate>`_

* `flake8-print <https://github.com/JBKahn/flake8-print>`_
  
* `flake8-todo <https://github.com/schlamar/flake8-todo>`_

* `pep8-naming <https://github.com/flintwork/pep8-naming>`_

* `radon <https://github.com/rubik/radon>`_

* `flake8-import-order <https://github.com/public/flake8-import-order>`_

.. links
.. _mccabe: https://github.com/flintwork/mccabe
.. _PyPI: https://pypi.python.org/pypi/