The Python Toolbox

Thu 01 February 2018 by Moshe Zadka

I have written before about Python tooling. However, as all software, things have changed -- and I wanted to write a new post, with my current understanding of best practices.

Testing

As of now, pytest has achieved official victory. Unless there are overwhelming reasons to use something else, strongly consider using it as your test runner. The only good reason is an existing project, with an existing test runner -- and even there, checking if pytest will just run your tests as is is worthwhile.

Even when using Twisted, unless you are implementing a new reactor, tests should be using in-memory reactors -- so the usefulness of trial is limited.

Static checking

In the static checking arena, flake8 and pylint are both still going strong. There are less and less reasons not to use both, especially if starting a project from scratch.

The flake8 plugin ecosystem is rich, and it is useful to look around and see if useful things are there. For example, the ebb-lint plugin is extremely strict about coding conventions -- hard to introduce to existing code bases, but wonderful when starting out a new one.

In the meantime, pylint has decent static code flow analysis which can often prevent bugs. Note, however, that Python static code analysis is hard, and pylint is not perfect. For example, it will often strugle with attrs-based classes.

Last but not least, mypy has made a showing in the field. It supports both Python 2 an 3, and allows annotating functions with types, in order to find mismatches before running the code. This is especially useful at API "boundaries", where the unit tests tend to cross less.

Test metarunners

The tox testing system is still the golden standard in Python. It can test complicated dependency matrixes, and allows configuring test commands flexibly. Its documentation is somewhat lacking, sadly -- it is often the case new tricks are only apparently after reading someone else's tox file.

Output

Building wheels, especially if the project has no native-code extensions, is nowadays considered standard. The best place to build wheels is in tox, when configuring a test that will build a wheel, install it, and then test against the installed wheel.

The best and most reliable way to upload wheels, and source distributions, to PyPI is to use twine. It used to be a good idea to test against the test PyPI server, but nowadays it is best to set up a devpi server for local testing.

When building applications, pex is a great output format. It allows a one-file install.

Future

The future is bright -- pip 10 is slated to come out, supporting the pyproject.toml format -- and hopefully the next post in the series will explain how to make packages using flit, with no setup.py.