Precommits workflow for Python

If you are experienced in python, then over time you might have realized the importance of linting. As your .py file grew in line, PEP8 standard went low.

So before we get started, lets understand few things for those who are new to python,

What is lint and linting?

In computer language, linter is any tool that detects and flags error in programming languages, including style errors.

Linting is running those tools against your source to check for above errors. It may or may not fix those issues.

Why to use it?

  1. Can fix those errors automatically

  2. It makes code more readable

  3. It figures out error before runtime

  4. Saves time

What is PEP8?

PEP8 is nothing but a style guide for python. It describes a standard, which includes indentation, function naming, variable naming, comparison, spacing, max line length, imports to name few. Since 2001, its like standard for every good python developer.

There are many python linters, autopep8, black, yapf, flake8. But for today we will be working with black and flake8.

What are hooks?

Hooks are additional code that you use to alter the behavior when some thing happens

We will be using gits pre commit hooks for linting our code with black and flake8 at staging, if they pass the test, then and only then we will be able to commit the files

Getting started

Lets install pre commit in our environment,

pip3 install pre-commit

Execute the following

pre-commit install

Create a pre-commit-config.yaml with hooks that you want. We will create a pre commit hook to use black to format my code and flake8 to check compliance with PEP8.

repos:
    - repo: https://github.com/ambv/black
    rev: stable
    hooks:
        - id: black
            language_version: python3.6
    - repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v1.2.3
    hooks:
        - id: flake8

Now for the code formatter black, it quite strict as compared to autopep8. Its not highly customizable. Though it still recommends 88 character code length. But we will keep it to 79.

Create pyproject.toml file at the same level .git folder

[tool.black]
line-length = 79
include = '\.pyi?$'
exclude = '''
/(
    \.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
| dist
)/
'''

You can ofcourse customize it as you like

Now Flake8

Create a file for flake8 configuration

[flake8]
ignore = E203, E266, E501, W503, F403, F401
max-line-length = 79
max-complexity = 18
select = B,C,E,F,W,T4,B9

Those ignore values with E prefix are nothing but error codes to ignore

Results

Now when you run

git add some_file_txt.py
git commit -m "some usual commit"

Magic will happen and it will auto lint using black and flake will show error for unused variable, name etc.

You just have to fix the flake8 issues, black will do its job.

So again after fixing the issues, you will have to recommit the same files and black will pass. Flake8 might show some unfixed errors