There are two important methodologies which can be used to assist you in writing clean, maintainable code. They are:
- Style Guides
- Test Driven Development (TDD)
In this series of posts we’ll cover what they are and how to set them up.
If you’ve been coding for any amount of time, you’ve likely heard of PEP8 - Style Guide for Python Code. If you haven’t, it’s a set of contentions for writing code. When followed, it enables coders to write in a common style. By doing so, they are able to more easily understand each other’s code.
To ensure that the guide is adhered to, several tools have been written which automate this process. To name a few:
While these are all great tools, they are highly configurable. While this may sound like a benefit, it can lead to disagreements. A simple example is, should strings be enclosed in single
(') or dobule
(") quotation marks? A solution to this problem is Black. Black is:
“The uncompromising Python code formatter. By using it, you agree to cede control over minutiae of hand-formatting. In return, Black gives you speed, determinism, and freedom from pycodestyle nagging about formatting. You will save time and mental energy for more important matters.”
Sounds great, doesn’t it? Let’s now look at how we use it.
Note: If you’d like to know more, Black’s style guide can be found here.
Setting up Black
First, we need to create initalise our Git repo:
/tmp$ mkdir demo /tmp/demo$ git init Initialized empty Git repository in /tmp/demo/.git/
Next we need to create our
/tmp/demo$ cat requirements-dev.txt pre-commit black
Note: Git pre-commit hooks enable us to run scripts before a commit is made. The
pre-commit Python library makes deploying these hooks extremely simple.
Now we need to install these packages:
pip install -r requirements-dev.txt --user
Next we’ll need to set up our
.pre-commit-config.yaml file as described here. For example:
/tmp/demo$ cat .pre-commit-config.yaml repos: - repo: https://github.com/ambv/black rev: stable hooks: - id: black language_version: python3.7
Finally, to install our pre-commit into the
.git/ directory, we’ll need to run the following command:
Create a file called
hello.py, and add the following line:
Now commit the change. If Black was set up correctly, you’ll see the following output:
/tmp/demo$ git commit -am 'update' black....................................................................Failed - hook id: black - files were modified by this hook reformatted hello.py All done! ✨ 🍰 ✨ 1 file reformatted.
From the output we can see that Black has reformatted our file. To see what it has changed, we can do a
/tmp/demo$ git diff diff --git a/hello.py b/hello.py index b376c99..11b15b1 100644 --- a/hello.py +++ b/hello.py @@ -1 +1 @@ -print('hello') +print("hello")
We can see that Black changed our single quotes to doubles. To accept the change, we simply re-add the affected file(s) and re-do the commit:
/tmp/demo$ git add hello.py /tmp/demo$ git commit -am 'Added hello file'
To verify that our commit was saved this time, we can check out git history:
/tmp/demo$ git log --oneline 12edeb9 (HEAD -> master) Added hello file
Note: We can have Black check our code without modifying by using the
--diff flag, like so:
/tmp/demo$ black --diff .
While Black is an “uncompromising Python code formatter”, it actually does offer a little flexibility. For example, if we’d like to change Black’s 88 character line length, we can. We simply create a
pyproject.toml file as described here. We then add the following to it:
[tool.black] line-length = 120
While pre-commit hooks are a great “last line of defence”, I’m not a fan of the two commit process we saw above. Furthermore, I also prefer immediate feedback. If you feel the same, then I highly recommend setting up an IDE integration.
As a PyCharm user, all I need to do is press
S and the code is updated right in front of my eyes.
Update: The next post in this series has been published: Test Driven Development (TDD) in Python
As always, if you have any questions or have a topic that you would like me to discuss, please feel free to post a comment at the bottom of this blog entry, e-mail at email@example.com, or drop me a message on Reddit (OzNetNerd).
Note: The opinions expressed in this blog are my own and not those of my employer.