In this article, I will cover the following contents, based on the newest version of Flake8 at the time this article was written(version 3.2.1).
- About Flake8
- Plugins of Flake8
- How to make Flake8 plugins
Flake8 is implemented as a wrapper for the following tools:
Here we see a tool that didn’t appear in the article one year ago,
pycodestyle. This tool was renamed from
pep8. In using Flake8, you don’t need to be conscious about
pep8 being renamed to
pycodestyle, but it’s worth keeping in mind.
The indications from Flake8 are classified as follows, if you don’t have plugins installed:
- Exxx, Wxxx: Outputs from pycodestyle
Warnings of codes not following PEP8
- Fxxx: Outputs from PyFlakes
Warnings of codes that will cause an error when executing
- C901: McCabe
Warnings of codes with high cyclomatic complexity
Plugins of flake8
The standard Flake8 wraps the 3 tools listed above, but only
McCabe is used as a pure plugin of Flake8. (
McCabe can be used alone by itself, but
McCabe is also implemented so that it can be used via Flake8)
So, what exactly are the “plugins” for Flake8? What does it refer to?
Flake8 utilizes the Entry Points mechanism of setuptools to load third-party plugins. setuptools is a Python library that provides a mechanism for packaging, and is a de facto in the Python world.
The important point is that the plugins of Flake8 just use the mechanism from setuptools, and do not have their own plugin mechanism.
By this, it makes it possible for Flake8 plugin creators to easily make plugins by packaging with the standard mechanism. Also, it is beneficial for Flake8 users because they can use the plugins by just installing them to their own environment.
Flake8 scans the Entry Points of the following namespaces:
A namespace for Entry Points for code checks
A namespace for Entry Points for Auto Correct
A namespace for Entry Points for customizing the outputs of warnings
Major Flake8 plugins
How to Make Flake8 Plugins
Like this, Flake8 has a mechanism that makes making plugins easy. Let’s try making a plugin of our own.
How to make Flake8 plugins is explained in Flake8’s documentation. There are other articles I have used as reference. Check the links at the bottom of this article.
Preparing the environment
This time, we’ll use Python 3.5.2. First, create an independent environment for working and install Flake8.
$ python -m venv venv
$ source venv/bin/activate
$ pip install flake8
Defining Entry Points
So, let’s start writing our code. First, create a
setup.py file with the contents below. What’s important is the contents of the
entrt_points passed to
setup(). This will be the Entry Points as said above.
dict is passed to the
entry_points. Here, we want to Lint, so we pass this with
flake8.extension as the key. The corresponding value for
flake8.extension is a
list type, in which we write a
error_code = module:callable. This time, we’ll define a error code
X801. (The error code here doesn’t have to be an error code in the current implementation, but we’ll do so to make it easier to understand)
# -*- coding: utf-8 -*-
from setuptools import find_packages, setup
‘X801 = flake8_english_please.checker:english_checker’,
Implementation of Lint
Next, let’s write the code we’ll actually use for Lint. This time, we’ll implement a Lint named
english_checker, which will detect letters other than English (or rather ASCII) in comments. (I know, it’s not very practical…)
First, you need to create a directory structure for the Python package.
$ mkdir flake8_english_please
$ touch flake8_english_please/__init__.py
Next, we’ll create a
flake8_english_please/checker.py file with the following contents.
This lint will run checks per physical line.
A Lint which issues a warning when a non-ASCII character is detected in a comment
X801 = ‘X801 This is a country where we speak English’
def english_checker(physical_line, tokens):
for token_type, text, start, _, _ in tokens:
if token_type != tokenize.COMMENT:
for index, x in enumerate(text):
if not ord(x) < 128:
return (start + index, X801)
english_checker.name = ‘english_checker’
english_checker.version = ‘0.1.0’
The Lint implementation must specify one of the following as the first argument:
Used when recieving a Python AST and running a Lint per file.
runmethod is also OK.
In that case, implement so that it receives the
treein the constructor(
Used when running a Lint per physical line. (The present implementation)
Can only define functions
Used when running a Lint per logical line.
Can only define generators.
Additionally, you can request information you want from Flake8 as a second (or more) argument. For further information, refer to here.
By the way, in this example, we borrowed the warning message from TrumpScript.
Use the implemented plugin
Okay, let’s install our plugin.
$ python setup.py install
Now we’re ready to use our plugin.
To test, create a file like below (
example.py) and execute
# この関数は何かをします(This function does something)
# Hi! はい
$ flake8 example.py
If you can see the following output and the status code after executing the command is 1, our implementation is complete and running without a problem.
example.py:1:3: X801 This is a country where we speak English
example.py:3:7: X801 This is a country where we speak English
We implemented a very simple non-practical plugin this time, but I hope I showed how easy it is to implement a Flake8 plugin. If you have any good ideas, give it a go!
More articles about Python(pep8, pyflakes, flake8, haking, Pylint)
- About style guide of python and linter tool. pep8, pyflakes, flake8, haking, Pylint.
- Automatically Review Code for Python Projects Using flake8
For more information about Sider, please go to our website.