DEV Community

Dimitri Merejkowsky
Dimitri Merejkowsky

Posted on • Originally published at dmerej.info on

Hello flake8

Originally published on my blog.

Introduction

In my last article I explained why I decided to no longer use pylint.

In a nutshell, most pylint warning are now caught by other linters, and all that’s left are some warnings.

In an other article I mentioned flake8 briefly, saying that I preferred a simple bash script to drive the execution of the various linters.

I was concerned that flake8 did not include pylint (now I no longer care of course). Also, I did not like the fact that flake8 forces a specific version for all the linters it runs.

Well, I was wrong (again).

flake8 is awesome

First off, I thought flake8 only combined the pyflakes and pycodestyle linters and nothing else 1. Well, it also includes mccabe by default.

Also, as explained in the FAQ, there are significant advantages in having the versions of the linters frozen this way.

Here are some other features I overlooked:

  • You can use the setup.cfg file to configure all the linters flake8 knows about
  • The output is consistent for all the linters
  • The checks of any linter can be be disabled on any line with just a # noqa comment

A nice surprise

The last time I upgraded pylint, I only got one new warning. It was on a line looking like this:

my_set = set([elem for elem in my_list if some_condition(elem)])
Enter fullscreen mode Exit fullscreen mode

The intent here is to build a unique set from a list of elements that satisfy a given condition.

pylint emitted the following warning:

R1718: Consider using a set comprehension (consider-using-set-comprehension)

Enter fullscreen mode Exit fullscreen mode

Indeed, the code can also be written like this, using a set comprehension instead:

my_set = {elem for elem in my_list if some_condition(elem)}
Enter fullscreen mode Exit fullscreen mode

Advantages:

  • The code is shorter
  • We no longer build a list (inside the square brackets) just to throw it immediately afterwards
  • The interpreter does not have to look up the set() function, so the code is faster

Well, there is already a flake8 plugin called flake8-comprehension that deals with these kind of issues.

In fact, there are a bunch of flake8 plugins available!

Plus, adding a new flake8 plugin is as easy as running pipenv install --dev <plugin name> and nothing else has to change :)

The future is bright

Itamar Turner-Trauring2, in the comment section on dev.to gave an interesting example:

# Note: I've taken the liberty of making the code a bit less abstract
def greet(prefix, name):
    print(prefix, name)

greeters = list()
prefixes = ["Hi", "Hello", "Howdy"]
for prefix in prefixes:
    greeters.append(lambda x: greet(prefix, x))

for greeter in greeters:
    greeter("world")
Enter fullscreen mode Exit fullscreen mode

You may think the following code would print:

Hi world
Hello world
Howdy world

Enter fullscreen mode Exit fullscreen mode

but instead it prints:

Howdy world
Howdy world
Howdy world

Enter fullscreen mode Exit fullscreen mode

This has to do with how the closures work in Python, and the bug is indeed caught by pylint:

$ pylint example.py
 W0640: Cell variable `prefix` defined in loop (cell-var-from-loop)

Enter fullscreen mode Exit fullscreen mode

I did not find a flake8 plugin that could catch this bug right away, but I found flake8-bugbear, a plugin to “find likely bugs and design problems”.

The plugin is well-written, well-tested and easy to contribute to.

I’ve already tried porting some pylint warnings to flake8-bugbear and so far it has been much easier than I thought. 3

Therefore, next time I find a bug that could have been caught by inspecting the AST (which is what both flake8-bugbear and pylint do), I know how to write or contribute to a flake8 plugin in order to automatically catch it during CI.

Thus, I can slowly build a complete replacement for pylint, with just the warnings I care about, and without the configuration issues and false positives.

Bright future indeed!

Thanks for reading this far :)

I'd love to hear what you have to say, so please feel free to leave a comment below, or check out my contact page for more ways to get in touch with me.


  1. The name of the project is somewhat misleading.  

  2. If you haven’t already, you should definitively check his blog and subscribe to the Software Clown mailing list. 

  3. Note that the pull request was actually not merged. In reality, I started by blindly adding a new check in flake8 before taking a look at the whole list of flake8 plugins. The pull request got closed because it turned out the check I added was already in the flake8-comprehensions plugin. Sometimes you have to lie to make a better story … 

Discussion (0)