7.3. 4 plugins pré-commit para automatizar a revisão e formatação de código em Python#
7.3.1. Motivação#
Ao enviar seu código Python para o Git, você precisa ter certeza de que seu código:
parece legal
está organizado
está em conformidade com o guia de estilo PEP 8
inclui docstrings
No entanto, pode ser difícil verificar todos esses critérios antes de confirmar seu código. Não seria legal se você pudesse verificar e formatar automaticamente seu código toda vez que você confirmasse um novo código como abaixo?
É aí que o pré-commit é útil. Nesta seção, você aprenderá o que é pré-commit e quais plugins você pode adicionar a um pipeline de pré-commit.
7.3.2. O que é pré-commit?#
pre-commit é uma estrutura que permite identificar problemas simples em seu código antes de confirmá-lo.
Você pode adicionar plugins diferentes ao seu pipeline de pré-commit. Depois que seus arquivos forem confirmados, eles serão verificados por esses plugins. A menos que todas as verificações sejam aprovadas, nenhum código será confirmado.
Para instalar o pré-commit, digite:
pip install pre-commit
Legal! Agora vamos adicionar alguns plugins úteis ao nosso pipeline de pre-commit.
7.3.3. black#
black é um formatador de código em Python.
Para instalar o black, digite:
pip install black
Agora, para ver o que o black pode fazer, escreveremos uma função muito longa, como abaixo. Como há mais de 79 caracteres na primeira linha de código, isso viola o PEP 8.
Vamos tentar formatar o código usando black:
$ black long_function.py
E o código é formatado automaticamente como abaixo!
def very_long_function(
long_variable_name,
long_variable_name2,
long_variable_name3,
long_variable_name4,
long_variable_name5,
):
pass
Para adicionar o black a um pipeline de pré-confirmação, crie um arquivo chamado .pre-commit-config.yaml
e insira o seguinte código no arquivo:
repos:
- repo: https://github.com/ambv/black
rev: 20.8b1
hooks:
- id: black
Para escolher quais arquivos incluir e excluir ao executar o black, crie um arquivo chamado pyproject.toml
e adicione o seguinte código ao arquivo pyproject.toml
:
[tool.black]
line-length = 79
include = '\.pyi?$'
exclude = '''
/(
\.git
| \.hg
| \.mypy_cache
| \.tox
| \.venv
| _build
| buck-out
| build
)/
7.3.4. flake8#
flake8 é uma ferramenta python que verifica o estilo e a qualidade do seu código Python. Ele verifica vários problemas não cobertos pelo preto.
Para instalar o flake8, digite:
pip install flake8
Para ver o que o flake8 faz, vamos escrever um código que viole algumas diretrizes do PEP 8.
def very_long_function_name(var1, var2, var3,
var4, var5):
print(var1, var2, var3, var4, var5)
very_long_function_name(1, 2, 3, 4, 5)
Em seguida, verifique o código usando flake8:
$ flake8 flake_example.py
flake8_example.py:2:1: E128 continuation line under-indented for visual indent
flake8_example.py:5:1: E305 expected 2 blank lines after class or function definition, found 1
flake8_example.py:5:39: W292 no newline at end of file
Ah! flake8 detecta 3 erros de formatação PEP 8. Podemos usar esses erros como diretrizes para corrigir o código.
def very_long_function_name(var1, var2, var3, var4, var5):
print(var1, var2, var3, var4, var5)
very_long_function_name(1, 2, 3, 4, 5)
O código parece muito melhor agora!
Para adicionar flake8 ao pipeline de pré-confirmação, insira o seguinte código no arquivo .pre-commit-config.yaml
:
- repo: https://gitlab.com/pycqa/flake8
rev: 3.8.4
hooks:
- id: flake8
Para escolher quais erros ignorar ou editar outras configurações, crie um arquivo chamado .flake8
e adicione o seguinte código ao arquivo .flake8
:
[flake8]
ignore = E203, E266, E501, W503, F403, F401
max-line-length = 79
max-complexity = 18
select = B,C,E,F,W,T4,B9
7.3.5. isort#
isort é uma biblioteca Python que classifica automaticamente as bibliotecas importadas em ordem alfabética e as separa em seções e tipos.
Para instalar o isort, digite:
pip install isort
Vamos tentar usar isort para classificar importações confusas como abaixo:
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from flake8_example import very_long_function_name
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression, OrderedLogisticRegression, \
LinearRegression, LogisticRegressionCV, LinearRegressionCV
$ isort isort_example.py
Resultado:
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from flake8_example import very_long_function_name
from sklearn.linear_model import (
LinearRegression,
LinearRegressionCV,
LogisticRegression,
LogisticRegressionCV,
OrderedLogisticRegression,
)
from sklearn.model_selection import train_test_split
Legal! As importações estão muito mais organizadas agora.
Para adicionar isort ao pipeline de pré-confirmação, adicione o seguinte código ao arquivo .pre-commit-config.yaml
:
- repo: https://github.com/timothycrosley/isort
rev: 5.7.0
hooks:
- id: isort
7.3.6. interrogate#
interrogate verifica sua base de código em busca de docstrings ausentes.
Para instalar o interrogate, digite:
pip install interrogate
Às vezes, podemos esquecer de escrever docstrings para classes e funções como abaixo:
class MathOperation:
def __init__(self, num) -> None:
self.num = num
def plus_two(self):
return self.num + 2
def multiply_three(self):
return self.num * 3
Em vez de olhar manualmente para todas as nossas funções e classes em busca de docstrings ausentes, podemos executar o interrogate:
$ interrogate -vv interrogate_example.py
Resultado (output):
Legal! A partir da saída do terminal, sabemos quais arquivos, classes e funções não possuem docstrings. Como sabemos os locais das docstrings ausentes, é fácil adicioná-las.
"""Example for interrogate"""
class MathOperation:
"""Perform math operation"""
def __init__(self, num) -> None:
self.num = num
def plus_two(self):
"""Add 2"""
return self.num + 2
def multiply_three(self):
"""Multiply by 3"""
return self.num * 3
$ interrogate -vv interrogate_example.py
A docstring para o método __init__
está ausente, mas não é necessária. Podemos dizer ao interrogate para ignorar o método __init__
adicionando -i
ao argumento:
$ interrogate -vv -i interrogate_example.py
Legal! Para adicionar interrogação ao pipeline de pré-confirmação, insira o seguinte código no 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, insira o seguinte código no arquivo pyproject.toml
:
[tool.interrogate]
ignore-init-method = true
ignore-init-module = false
ignore-magic = false
ignore-semiprivate = false
ignore-private = false
ignore-property-decorators = 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"
7.3.7. Etapa Final — Adicionar pre-commit ao Git Hooks#
O código final em seu arquivo .pre-commit-config.yaml
deve ter a seguinte aparência:
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 ao git hooks, digite:
$ pre-commit install
Resultado (output):
pre-commit installed at .git/hooks/pre-commit
7.3.8. Commit#
Agora estamos prontos para dar o commit do novo código!
$ git commit -m 'add pre-commit examples'
E você deve ver algo como abaixo:
7.3.9. Pular verificação#
Para evitar que o pré-commit verifique um determinado commit, adicione –no-verify ao git commit:
$ git commit -m 'add pre-commit examples' --no-verify