Linting Python Codes Better with Travis

Search for a command to run...

No comments yet. Be the first to comment.
Python, Golang, Javascript, etc libraries require packaging. It's done to easily distribute code among users thereby avoiding problems in future development. In Python, a library is distributed through the Python Package Index (PyPI), a public hostin...

I want to tell a story of an amazing community called Bioinformatics Community but texts wouldn't be enough. Anyhoo, I blogged about my experience at BCC 2020 on OBF's website. This event was one of my highlights of the summer.

Recently, I needed to combine 2 or more PDF files into one. Merging these PDF files could be due to the company's demand or a need to track all files in one file. In this tutorial, I'd show you how I accomplished this particular task on my machine. T...

TL;DR This article uses Docker Compose to create and manage multiple container applications. It's entirely hands-on. Docker has made it easier to develop and package applications in reproducible environments. With Docker, you worry less about the inf...

GraphQL and Python Series (Expressive Introduction) This is part 1 of an ongoing series to introduce you to using GraphQL and Python. Hopefully, at the end of this series, you will be able to build a GraphQL Backend with Django and Graphene. GraphQL ...
When contributing to open source organizations, one will notice the need to follow coding standards and conventions to have your pull request reviewed and possibly merged. It's the same with mature companies, and a lot of startups too: they all like to follow the coding standards of their chosen programming language. This process is what is referred to as linting. When organizations lint their codes, everybody is happy because coding standards are followed. But can we have this same setup in our private accounts? Can operate like these organizations in our repositories? The answer is yes we can and I will show you if you stick around.
At the end of this tutorial we will:
Linting is referred to as the process of analyzing source code to flag programming errors and stylistic errors. Linting, when done properly, can detect formatting discrepancy, errors in your program and ensure you adhere to coding standards and conventions. Linters (a tool for linting) ensures you follow best practices, makes your code readable and easy to maintain and possibly save time. Organizations use CI tools to automate their linting and also ensure that future contributors to that codebase follow lint rules.
Every language uses their own set of lines so I'd just list three linters with three programming languages below:
Python: pylint, flake8, bandit
Golang: go-critic, go-vet, golangci-lint(this contains all the linters in Go language)
JavaScript: ESLint, JSLint.
For the focus of this tutorial, we will focus on linting python codes.
In the previous section, we talked about organizations using CI tools to automate their linting. But what is CI?
Continuous integration is a software development practise where developers regularly merge their code changes into a central repository, after which automated builds and tests are run. Continuous integration most often refers to the build or integration stage of the software release process and entails both an automation component (e.g. a CI or build service) and a cultural component (e.g. learning to integrate frequently). Travis CI (c'mon it's in the name) is one of those tools used by organizations to automate their testing for lint. A lot of open source organizations use Travis for their automation and we will mimic them in automating our check for lint.
Travis CI has all the required steps to set up in their documentation so it will be redundant to have to type it out here. Do check out their documentation here. Once you're done with this, Travis is all set up and linked with your account. To integrate Travis with your repositories, you need to add a .travis.yml file in your project-level directory to trigger a Travis CI build.
Now we made mention of linters in Python earlier, so we'd pick two from there and use: flake8 and pylint. We will check the following code with the packages.
import json
class Dog:
def __init__(self, name, age):
"""Initialize name and age attributes."""
self.dog_name = name
self.dog_age = age
self.name = "Rambo"
self.age = 12
def sit(self):
print(f"{self.dog_name} is now sitting")
def roll_over(self):
print(f"{self.dog_age} rolled over!")
my_dog = Dog("Maxwell", 6)
Save the above code in a new file called app.py Then we create a requirements.txt file with the contents below
pytest-pylint==0.16.1
pytest-flake8==1.0.5
We choose these packages because Travis CI will need to run a test and what better package to use that pytest package. Pytest is used for running tests and will be expanded upon in subsequent articles.
Note: The following sessions should be done individually. Use the flake8 package first, watch the results and after you fix it, return your code to the format above and test with pylint. This is done so you see the differences between both packages and you choose the one you love the most.
Flake8 is a tool for style guide enforcement. This means flake8's principal purpose to ensure you style your codes properly. It's "the wrapper which verifies pep8, pyflakes and circular complexity". To set it up in Travis, create a Travis YAML file as you were told above and add the following code to it.
language: python
python: "3.8"
install:
- pip install -r requirements.txt
scripts:
- pytest --flake8
language: this tells Travis to use a python as the programming language for this build.
python: here you choose the version you want to test your code with, it supports all python version from 2.7 to present but we're testing our codes with python version 3.8.
install: We're installing the packages we already defined in our requirements.txt file. We want to install the packages in Travis environment so it can be accessed.
scripts: Here, we're executing the pytest --flake8 package we installed. This package is pytest and flake8 rolled in one. Meaning it will test all .py files in the code against the flake8.
Pylint is a bit different from flake8, it's the full dose really: it checks style guide, programmatic errors and follows best practices.
Some even say pylint is too strict in its rules (well it's true and you'd see it) so some people use black instead of pylint.
We'd do the same setup as above
Edit the file .travis.yml above to use pylint,
language: python
python: "3.8"
install:
- pip install -r requirements.txt
scripts:
- pytest --pylint
It follows the same explanation as to the above and this time we're executing pylint to check instead of flake8.
When we commit the above code to the repository, Travis builds the environment needed to test the code against either flake8 or pylint. If you use the flake8 package, you should get the following error:
If you use the pylint package, you should get the following error:
Now pylint has an annoying C103: Constant name "my_dog" doesn't conform to UPPER_CASE naming style (invalid-name) rule.
I don't like so we will choose to ignore that particular error, and we do that by ...
So the final code for that passes both flake8 and pylint is as below:
"""This module is an attempt to practise class in python."""
class Dog:
"""A simple attempt to model a dog."""
def __init__(self, name, age):
"""Initialize name and age attributes."""
self.dog_name = name
self.dog_age = age
self.name = "Rambo"
self.age = 12
def sit(self):
"""Simulate a dog sitting in response to a command."""
print(f"{self.dog_name} is now sitting")
def roll_over(self):
"""Simulate a dog sitting in response to a command."""
print(f"{self.dog_age} rolled over!")
my_dog = Dog("Maxwell", 6)
Now if we push our codes to the git repository, the tests pass successfully. If you check the email linked to your git account, you should see a congratulatory message saying you've fixed the build.
We have seen what linting is, how to add Travis CI to our git environment, and used the linters in Python to test our code against Python rules. You should know you can also use Travis to test if your code does what it is supposed to do. That is called Test-Driven Development and we will talk a lot about that in our upcoming Pytest series.
Till then, enjoy the power of automation!