Python has taken the software development world fast and without mercy. According to StackOverflow 2019 survey, it is currently the second most popular backend language and the second most loved programming language. Not without a reason! Python has a simple syntax, is dynamically typed and supports a wide range of use cases – from scripting to web apps and machine learning.
However, these advantages can quickly turn against you. Dynamic typing, if not tested properly, can give you unexpected results. People writing Python coming from numerous backgrounds can obey different coding styles and waste time in code reviews adjusting to PEP8. Even your unit testing frameworks can diverge across the team!
(please settle on one if you work in such a team 😉)
This article is a summary of multiple Python tools that we use at 10Clouds to simplify our Python development.
Our starting point is always …
cookiecutter
Cookiecutter is a tool that allows you to automate the project setup page and get to the implementation of business logic straight away. By bundling it in docker containers we can deliver the first features of the system during the very first sprint.
Our custom django template is built on cookie cutter and whenever a new project is being started, some backend developer pastes this line into their terminal:
The repo is on our private GitHub, but we plan on open sourcing it soon! Readers of this blog will know about it first 😃
OK, so we have our app ready. We saved time on the setup, now let’s save some more on code reviews… it is not what you think though!
pylama
Pylama is a tool that will automatically grade your code and point out the common issues that would pop up first in the review. It will automatically check if the code is compliant with your code style guidelines, if the Cyclomatic Complexit is not too high and if the mypy types are on point. Pylama is primarily used as a pytest plugin, but if you want to audit your code without pytest, just proceed with
But what are the requirements? Well, the complexity of the code needs to be fixed by the programmer who knows the business logic. But don’t worry – there are more tools to help.
black
Black project started as an independent code which famously goes against PEP8 code style guidelines. It causes polarized opinions and doesn’t allow for any configuration. Some love it, some hate it, but since it has been recognized and recommended by the Python Software Foundation, black has become the default code formatter in many organizations. We are also embracing the black mindset and every new Pull Request needs to comply with black before anybody looks at it.
How does it work? Again, really simple:
Take some unformatted code, like this function:
run black on it:
and in return you get:
Tada! You don’t have to worry about code formatting ever again. What we also recommend is setting up a pre-commit hook that will prevent you from creating a non-black code. Mistakes like that can cause some unnecessary pain, so this two-minute-long setup is certainly worth it!
Black takes care of the big stuff, but doesn’t sort the imports. While this is not necessary, the process today is automatic and costless, thanks to…
isort
I sort so you don’t have to
is the quote you will find at the first page of isort README. This is a simple promise, that isort delivers perfectly. Let’s look at an example from their docs:
running $ isort example.py will modify the file’s content into:
and that’s it! Now your imports are clean and tidy.
mypy
Dynamic typing – probably Python’s best and worst feature. While it enables rapid prototyping, experimenting and easier general intro to the language, it certainly slows down the development in huge codebases. Back in times before mypy, I would write some unit tests that are now totally obsolete with the static type checking.
If you want to support enterprise clients or just work on a project that will require maintenance for years to come, mypy is your friend.
If you work on an existing project that falls into this category, ask your project manager for time to implement it. It will be worth it!
After all, this is not a huge API change. Writing a valid mypy Python code is as simple as adding following type annotations:
… but for every function in your codebase 😅
If you need to annotate a more complex type, like list, you will use a `typing` library.
In the snippet above we annotated a function to return a list of strings. You repeat this for any type you need and you got yourself a statically typed language!
pytest
And here we are! Now having all the code quality tools available, let’s make them a part of your CI. Pytest is perfect for it! Even better news is, that you can still keep your legacy tests written in unittest. Pytest will run them without hustle, while providing us with the plugins of tools mentioned above.
So, running the full CI would look like that:
Here we go 🎉
Such setup will make everybody happy to collaborate on your next Python project.
Summary
Life is too short to worry about type safety, formatting or sorted imports. Hopefully, you will never have to. If you are currently working on a Python project of any kind, give yourself a moment to implement these tools into your pipeline. You won’t regret it.