Aprimorando qualidade de código Python com black, flake8, isort e interrogate
Automatizando o pipeline de qualidade de código antes de dar o commit
Contexto
Ao commitar código Python usando o git, ferramenta de versionamento amplamente usada pela comunidade, é necessário garantir que o código:
- tenha uma boa aparência (formatação);
- esteja organizado;
- esteja de acordo com o guia de estilo da PEP 8;
- inclua documentação (docstring);
Porém, fazer essa checagem antes de cada commit é muito chato e entediante!
Não seria legal se essa tarefa repetitiva e maçante pudesse ser automatizada antes de cada commit?
É neste momento que o pre-commit vem a calhar!
O que é o pre-commit?
pre-commit
é um framework que permite fazer várias verificações antes de commitar um código.
É possível adicionar diversos plugins ao seu pipeline de verificação do pre-commit
. Quando um commit for dado, o pipeline roda todas as verificações e, se houver alguma falha, o commit não é feito, alertando o que está inconsistente.
É possível instalar o pre-commit
da seguinte forma:
pip install pre-commit
Maravilha! Basta agora alguns plugins ao pipeline de verificação do pre-commit
.
black
O black
é uma biblioteca que formata o código de acordo com a PEP 8.
Para instalar o black
:
pip install black
Ao aplicar o black
em um arquivo ou pasta, ele formatará de forma automática.
$ black nome_do_script.py
Ao executar o comando acima, o black
fará a formatação completa. É possível ver alguns exemplos da própria documentação oficial do black
:
# in:j = [1,
2,
3
]# out:j = [1, 2, 3]
Outro exemplo:
# in:
ImportantClass.important_method(exc, limit, lookup_lines, capture_locals, extra_argument)
# out:
ImportantClass.important_method(
exc, limit, lookup_lines, capture_locals, extra_argument
)
Ou seja, não é necessário mais a preocupação com formatação do código.
Para adicionar o black
ao pipeline do pre-commit
é só criar um arquivo .pre-commit-config.yaml
e colocar o código abaixo:
repos:
- repo: https://github.com/ambv/black
rev: 20.8b1
hooks:
- id: black
Para configurar quais arquivos serão inclusos ou não na verificação ao rodar o black
, é possível criar um arquivo chamado pyproject.toml
e colocar o seguinte trecho nele:
[tool.black]
line-lenght = 79
include = '\.piy?$'
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
)/
'''
flake8
flake8
é uma framework que checa o estilo e qualidade de código Python. Ele verificar vários outros pontos não cobertos pelo black
.
Para instalar o flake8
:
pip install flake8
Da mesma forma, é possível aplicar o flake8
da seguinte forma:
flake8 nome_do_script.py
E para configurá-lo no pipeline do pre-commit
, é só inserir o trecho abaixo no arquivo .pre-commit-config.yaml
:
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4
hooks:
- id: flake8
Da mesma forma que o black
também é possível configurar o flake8
criando o arquivo .flake8
e inserindo o seguinte conteúdo nele:
[flake8]
ignore = E203, E266, E501, W503, F403, F401
max-line-lenght = 79
max-complexity = 18
select = B,C,E,F,W,T4,B9
isort
isort
é uma biblioteca Python para formatar automaticamente as importações de acordo com a PEP 8: em ordem alfabética e organizada por seções e tipos.
Instalação do isort
:
pip install isort
Aplicando o isort
:
isort nome_do_script.py
Da própria documentação do isort
, temos o seguinte exemplo:
Antes da aplicação do isort
from my_lib import Object
import os
from my_lib import Object3
from my_lib import Object2
import sys
from third_party
import lib15, lib1, lib2, lib3, lib4, lib5, lib6, lib7, lib8, lib9, lib10, lib11, lib12, lib13, lib14
import sys
from __future__ import absolute_import
from third_party import lib3 print("Hey")
print("yo")
Após a aplicação do isort
:
from __future__ import absolute_import import os
import sys from third_party import (lib1, lib2, lib3, lib4, lib5, lib6, lib7, lib8, lib9, lib10, lib11, lib12, lib13, lib14, lib15)from my_lib import Object, Object2, Object3 print("Hey")
print("yo")
Observa-se que há uma organização completa dos imports por ordem alfabética e por seções:
- funções built-in primeiro
- pacotes externos na sequencia
- somente depois módulos ou pacotes próprios
Para adicionar o isort
ao pipeline do pre-commit
, adiciona-se o trecho de código ao arquivo .pre-commit-config.yaml
:
- repo: https://github.com/timothycrosley/isort
rev: 5.7.0
hooks:
- id: isort
interrogate
interrogate
é um framework para verificar a ausência de documentações (docstring) no código.
Para instalar:
pip install interrogate
É comum esquecer de documentar funções, classes e módulos com docstring, conforme o exemplo abaixo:
class OperacaoMatematica:
def __init__(self, num) -> None
self.num = num
def soma_dois(self):
return self.num + 2 def triplica(self):
return self.num * 3
Ao invés de procurar manualmente por todas as docstrings esquecidas, podemos rodar o interrogate
:
interrogate --v exemplo.py
O terminal apresentará quais módulos, classes e funções não tem documentação. E agora basta adicionar as documentações ausentes.
"""Exemplo de uso do interrogate."""class OperacaoMatematica:
"""Realiza operação matemática."""
def __init__(self, num) -> None
self.num = num
def soma_dois(self):
"""Soma dois."""
return self.num + 2 def triplica(self):
"""Multiplica por três."""
return self.num * 3
A docstring do método __init__
ainda está ausente, porém não é necessária. É possível usar a flag -i
para que o interrogate
ignore-o:
interrogate --v -i exemplo.py
Para adicionar o interrogate
ao pipeline do pre-commit
, adiciona-se o trecho de código ao arquivo .pre-commit-config.yaml
:
- repo: https://github.com/econchick/interrogate
rev: 1.4.0
hooks:
- id: interrogate
args: [--vv, -i, --fail-under=80]
Para editar as configurações padrão do interrogate
basta adicioná-las ao arquivo pyproject.toml
:
[tool.interrogate]
ignore-init-method = true
ignore-init-module = false
ignore-magic = false
ignore-semiprivate = false
ignore-private = false
ignore-property-decorator = false
ignore-module = true
ignore-nested-functions = false
ignore-nested-classes = true
ignore-setters = false
fail-under = 95
exclude = ["setup.py", "docs", "build"]
ignore-regex = ["^get$", "^mock_.*", ".*BaseClass.*"]
verbose = 0
quiet = false
whitelist-regex = []
color = true
generate-badge = "."
badge-format = "svg"
Último passo — adicionar o pre-commit
aos hooks do git
Ao final, o arquivo .pre-commit-config.yaml
terá o seguinte conteúdo:
repos:
- repo: https://github.com/ambv/black
rev: 20.8b1
hooks:
- id: black
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4
hooks:
- id: flake8
- repo: https://github.com/timothycrosley/isort
rev: 5.7.0
hooks:
- id: isort
- repo: https://github.com/econchick/interrogate
rev: 1.4.0
hooks:
- id: interrogate
args: [--vv, -i, --fail-under=80]
Para adicionar o pre-commit
aos hooks do git:
pre-commit install
Em caso de sucesso, aparecerá a seguinte mensagem:
pre-commit installed at .git/hooks/pre-commit
Commit
Basta commitar o código que todas as verificações serão feitas antes de o commit ser dado. Caso quaisquer uma das validações falhe, o commit é cancelado.
git commit -m "feat: adiciona hooks do pre-commit"
Pulando a verificação
Nem sempre deseja-se que a verificação seja feita. É possível adicionar a flag --no-verify
ao commitar, para pular a verificação.
git commit -m "feat: adiciona hooks do pre-commit" --no-verify
Resumo
- Contextualização
- Introdução ao pre-commit e seus hooks
- Hook do black (formatação PEP 8)
- Hook do flake 8 (qualidade de código)
- Hook do isort (formatação de imports)
- Hook do interrogate (documentação de código)
- Adição de todos os hooks ao git
- Commitando
- Pulando a verificação
Gostou? Espero ter contribuido minimamente com sua jornada em qualidade de código!