The Gates of Code Quality — Pylint

Ankit Choudhary
The Startup
Published in
7 min readSep 20, 2020

--

A Code linter, is a static code analysis tool used to flag programming errors, bugs, stylistic errors, and suspicious constructs. The term originates from a Unix utility that examined C language source code. Like Google, “lint” became a verb that meant static checking your source code.

Everyone knows that programming errors are bad. Some errors cause glitches that frustrate users. Others compromise the safety and security of a critical system.

Linting is an essential process and code linters are available across programming languages. In this blog, we will talk specifically about the Python Linter aka Pylint. Pylint checks your code against the norms stated in the styling guide for Python as stated in PEP-8.

Pylint is a tool that checks for errors in Python code, tries to enforce a coding standard and looks for code smells. It can also look for certain type errors, it can recommend suggestions about how particular blocks can be refactored and can offer you details about the code’s complexity.

Pylint will display a number of messages as it analyzes the code and it can also be used for displaying some statistics about the number of warnings and errors found in different files. The messages are classified under various categories such as errors and warnings.

Last but not least, the code is given an overall mark, based on the number and severity of the warnings and errors

Gates of Implementation: A check when performed at multiple stages ensures no leakage. However the rule book (we will talk about it in the later sections) applied to each stage must be the same to avoid conflicts. Performing Pylint Checks in multiple stages also avoids rework and last minute changes/deviations from deployments/releases.

1: This stage is the closest to all the groundwork and forms the first layer of straining your code against the quality filter. Pycharm stays the undebatable and undefeated champion of all the editors out there for Python. Integration of Pylint with Pycharm eases the lint checks with just the click of a button.

As and when you keep building your code, you should get habituated with the check-as-you-go way of running checks. For that, let’s leverage the “External Tool” feature of the editor. The steps to integrate Pylint in the editor have been beautifully shared in one of the stack overflow answers.

You can set up pylint to work with PyCharm by following the next steps:

Install pylint:

$ pip install pylint

Locate your pylint installation folder:

$ which pylint # MacOS/Linux
/usr/local/bin/pylint # this is just a possible output check yours
$ where pylint # Windows %LocalAppData%\Programs\Python\Python36–32\Scripts\pylint.exe # possible location

Open the PyCharm settings window with File -> Settings, then navigate to Tools -> External Tools in the sidebar. (Or search “external tools”)

Setup an external tool by clicking on the + sign and filling the fields accordingly. In Program use the path you got when running which pylint, for the other values you can use the same of the image.

To run pylint from Tools -> External Tools -> pylint:

Look your output in the PyCharm terminal:

2: The second gate enforces the 1st level of governance in the code quality. This gate prevents a developer from contributing any code (having lints) to the GIT repository. Git has various web-hooks that eases the development efforts. For the code linter, we will be using the pre-commit hook. It’s a simple script that gets triggered prior to any commit event.

The pre-commit hook is run first, before you even type in a commit message. It’s used to inspect the snapshot that’s about to be committed, to see if you’ve forgotten something, to make sure tests run, or to examine whatever you need to inspect in the code. Exiting non-zero from this hook aborts the commit, although you can bypass it with git commit --no-verify. You can do things like check for code style (run lint or something equivalent), check for trailing whitespace (the default hook does exactly this), or check for appropriate documentation on new methods.

A sample pre-commit hook for running Pylint has been shared here by Nick Fitzgerald. I recommend modifying this sample script slightly by implementing Python Argument Parser to enable dynamic value fetching from user instead of hard coding it within the code. For ex: you can set a default pass rank for the pylint checks while allowing the user to pass a value which would override the defaults. It also helps to choose the pylintrc file from the user if the need be.

So far, we saw the gates that help us in implementing and governing the lint checks, however these 2 steps are totally dependent on a user/developer as it becomes their sole responsibility to implement the quality filters.

Hence, the 3rd gate. This gate forms the final gate which strictly enforces the checks and cannot be bypassed.

3: The integration of pylint checks with the CI/CD pipeline forms the bulletproof shield against quality compromises. Run the linter within your CI pipeline (set to trigger by a Pull Request) and pass/fail the Pipeline based on the results of the lint checks, thereby prohibiting the succession of your code from lower to higher branches (feature -> dev, dev -> master, etc).

For my demonstration, I am using CodeFresh to orchestrate the CI pipeline. In the below example, I am building a Python package and publishing it to a artifactory manager, JFROG. This pipeline is triggered whenever there is a Pull Request raised from feature branch to dev branch and the results are sent back to Git using a service hook registered between Codefresh and Git.

Hence, the reviewer can refer the automated checks before proceeding with the actions to be taken on the Pull Request. You can also set the build of CI pipeline to be triggered upon the merging of a PR, totally depends on you!

What is Pylintrc?

You would have noticed that I mentioned “pylintrc” a few times so far. This is the rule book that I mentioned at the beginning of this blog. It’s a config file for the pylint that states the various checks to be performed/skipped explicitly by deviating from generic PEP-8.

For ex: PEP-8, states that the max length of a line to be limited to 79 chars:

Limit all lines to a maximum of 79 characters. For flowing long blocks of text with fewer structural restrictions (docstrings or comments), the line length should be limited to 72 characters.

However, most of the teams/projects consider this unnecessary and are fine with limiting the line length to 100/120 characters. This override must be specified in the pylintrc file as:

[FORMAT]
max-line-length=100

Similarly, if you want to skip checking for Module doc-strings along with the above specification, the pylintrc would look as:

[FORMAT]
max-line-length=100
[MASTER]
disable=
C0114, # missing-module-docstring

You can generate a default rc file by using the pylint flag --generate-rcfile and set the overrides as required.

pylint --generate-rcfile > .pylintrc

Alternatively, there are a lot of predefined pylintrc file available as open source. Feel free to refer any of those and tweak them according to your use case.

Invoking Pylint with a specific pylintrc file should be done as below:

pylint --rcfile <PATH_TO_RC_FILE> <PATH_TO_PY_MODULE/FILE>

One of my favorite quotes on computer programming:

Any fool can write code that a computer can understand. Good programmers write code that humans can understand.

— Martin Fowler, 2008.

I hope the above blog post helped you in getting started with code linters. I strongly feel that the best way to improve one’s coding habits is to read through the comments raised by the editors as you start developing and try to rectify those then and there. As you start following pylint messages, you would also learn better ways of implementing the same functionality. It definitely helps!

Coding with better standards and improved quality comes with practice and patience. The toughest task is to get started. Once you leave the shore and start sailing, trust the wind and it will propel you smoothly towards the zenith.

As I always believe, start with one step at a time!

--

--

Ankit Choudhary
The Startup

Programmer & Architect @ Deloitte in Python, Big Data, Azure/AWS by Profession. Biker, Chef & Philanthrope by Passion. Student Pilot.