Linting Python Codes Better with Travis

Linting Python Codes Better with Travis

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:

  • understand what linting is
  • setup and Integrate TravisCI to our repositories
  • use Travis CI to lint Python codes using flake8 and pylint

What is Linting

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.

Setup TravisCI and Integrate TravisCI to your repositories

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.

Linting Python Codes with Travis CI

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

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

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.

Results

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.

Conclusion

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!