3 min read

Pre-commit demi kenyamanan bersama

Pre-commit demi kenyamanan bersama
Photo by mk. s / Unsplash

Dalam beberapa waktu terakhir saat saya setup project python setidaknya ada 3 hal yang harus ikut dipasang di awal:

  • isort: untuk konsisten runutan dari "import"
  • black: formating
  • flake8: linter

Dengan tambahan konfigurasi masing-masing seperti

#.isort.cfg
[isort]
line_length = 80
multi_line_output = 3
include_trailing_comma = true
#.flake8
[flake8]
max-line-length = 80
select = C,E,F,W,B,B950
ignore = E501,W503,E203

Jangan tanya dulu tentang konfigurasi di atas karena sayapun mendapatkan dari random blog di internet sudah lama sekali. Lalu saya pasang konfigurasi di vscode saya seperti ini

{
    "python.defaultInterpreterPath": "/path/to/virtualenv/python",
    "python.formatting.provider": "black",
    "python.formatting.blackArgs": [
        "--line-length=80"
    ],
    "python.sortImports.args": [
        "-rc",
        "-sp isort.cfg"
    ],
    "editor.formatOnSave": true,
    "python.linting.flake8Enabled": true,
    "python.linting.pylintEnabled": false,
    "[python]": {
        "editor.codeActionsOnSave": {
            "source.organizeImports": true
        }
    },
    "html.suggest.html5": true,
    "html.autoClosingTags": true,
}

Efeknya adalah setiap saya menulis kode python dan menyimpannya maka vscode akan mengubah format sesuai aturan yang sudah ditetapkan dan juga kita akan mendapatkan informasi warning secara langsung di bagian terminal. Contoh saya menulis kode seperti ini:

from blog.models import Content, Tags
from django.contrib import admin
# Register your models here.
admin.site.register(Tags)


def some_function_with_long_param(first, second, third, fourth, fifth, sixth, seventh, more
):
    greeting = 'hallo'
    return greeting

Saat saya melakukan save, vscode akan membantu untuk merapihkan jadi seperti ini

from django.contrib import admin

from blog.models import Content, Tags

# Register your models here.
admin.site.register(Tags)


def some_function_with_long_param(
    first, second, third, fourth, fifth, sixth, seventh, more
):
    greeting = "hallo"
    return greeting

Dan bonus warning di terminal seperti ini

'blog.models.Content' imported but unused

Dengan seperti ini saya mendapatkan benefit:

  • konsisten format
  • mengurangi kesalahan-kesalahan yang muncul saat ngoding.

Selesai? Betul selesai selama ngoding sendiri dan teman ngoding menggunakan vscode sehingga konfigurasi bisa copas dan kami akan sama-sama menggunakan format dan aturan baku yang sama. Tapi semua berubah saat ada yang menggunakan IDE lain dan tidak otomatis melakukan sesuai aturan yang sudah dibuat di config file.

pre-commit

Untuk mengetes linter bisa saja dipasang di repository sehingga saat melakukan push atau pull-request dicek dulu keabsahan linternya, tapi bagaimana jika ingin sebelum masuk repo bahkan orang sudah aware dengan perbedaan? Pre-commit ini bisa menjadi jawaban.

Sesuai namanya pre-commit membantu kita untuk melakukan suatu tugas sebelum programmer melakukan commit kepada berkas yang dikerjakan.

Pertama mari install dahulu pre-commit menggunakan package manager favorit masing-masing, di sini saya pakai pipenv

pipenv install pre-commit

Setelah terpasang buat berkas .pre-commit-config.yaml dan isikan sebagai berikut (sesuaikan versi dengan yang diinginkan)

repos:
-   repo: https://github.com/PyCQA/isort
    rev: 5.10.1
    hooks:
    - id: isort
-   repo: https://github.com/ambv/black
    rev: 22.6.0
    hooks:
    - id: black
      language_version: python3.9
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v2.3.0
    hooks:
    - id: flake8

Setelah selesai jalankan di root aplikasi pre-commit install sampai mendapatkan response pre-commit installed at .git/hooks/pre-commit

Instalasi selesai.

Sekarang saya coba di IDE yang berbeda, saya menggunakan pycharm community.

Kembali ke kode pertama yang belum kena format

from blog.models import Content, Tags
from django.contrib import admin
# Register your models here.
admin.site.register(Tags)


def some_function_with_long_param(first, second, third, fourth, fifth, sixth, seventh, more
):
    greeting = 'hallo'
    return greeting

Saat disimpan tidak otomatis mengubah format, tapi saat saya melakukan commit, pre-commit akan mengecek kesesuaian dan yang bisa diformat akan diformat dan yang tidak akan ditandai

git commit -am "precommit"
[INFO] Installing environment for https://github.com/PyCQA/isort.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/ambv/black.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
[INFO] Installing environment for https://github.com/pre-commit/pre-commit-hooks.
[INFO] Once installed this environment will be reused.
[INFO] This may take a few minutes...
isort....................................................................Failed
- hook id: isort
- files were modified by this hook

Fixing /home/ariesm/Work/ninja-api/blog/admin.py

black....................................................................Failed
- hook id: black
- files were modified by this hook

reformatted blog/admin.py

All done! ✨ 🍰 ✨
1 file reformatted.

Flake8...................................................................Failed
- hook id: flake8
- exit code: 1

blog/admin.py:3:1: F401 'blog.models.Content' imported but unused

Hasilnya kode kita seperti ini

from django.contrib import admin

from blog.models import Content, Tags

# Register your models here.
admin.site.register(Tags)


def some_function_with_long_param(
    first, second, third, fourth, fifth, sixth, seventh, more
):
    greeting = "hallo"
    return greeting

tapi ini belum bisa di-commit karena masih ada error yang tidak otomatis keformat yaitu flake8 blog/admin.py:3:1: F401 'blog.models.Content' imported but unused

Hapus atau gunakan Content sesuai anjuran dari flake, lalu lakukan commit lagi dan hasilnya.

from django.contrib import admin

from blog.models import Content, Tags

# Register your models here.
admin.site.register(Tags)
admin.site.register(Content)


def some_function_with_long_param(
    first, second, third, fourth, fifth, sixth, seventh, more
):
    greeting = "hallo"
    return greeting
isort....................................................................Passed
black....................................................................Passed
Flake8...................................................................Passed
[feat/scafolding d8a338d] precommit
 1 file changed, 2 insertions(+), 8 deletions(-)

Kode berhasil di-commit dan ketika dipush ke repo sudah tertib mengikuti aturan.

Referensi: https://rohitgupta.xyz/blog/keeping-python-code-clean-with-pre-commit-hooks-black-flake8-and-isort/