Criação de Repositório Template para Projetos em Python - PyStarterKit

Introdução

Estou com um projeto na cabeça que vai me ajudar a resolver um problema que estou enfrentando há um tempo em um dos meus hobbies. Antes de começar, quis ajustar algumas coisas e melhorar a qualidade dos meus projetos em Python. Queria criar um projeto mais maduro tecnicamente, com boa documentação, boas práticas e processos bem definidos.

Com isso em mente, fui atrás de ferramentas que pudessem me ajudar nessa visão. Pesquisei bastante e encontrei algumas que poderiam ser úteis. Comecei a colocar a mão na massa para criar uma boa fundação para o meu projeto pessoal e, durante esse processo, gostei tanto do que estava fazendo que decidi criar um template para ser usado em todos os meus futuros projetos Python. Gostaria de compartilhar com vocês onde cheguei com o template até agora.

Ferramentas Utilizadas

Gerenciamento de Dependências e Versões de Python

Instalei Poetry para gerenciar as dependências e Pyenv para gerenciar as versões de Python. No meu projeto, o Pyenv gerencia a versão do Python especificada no .python-version, enquanto as dependências são gerenciadas pelo Poetry, especificadas no pyproject.toml. As dependências são instaladas em um ambiente separado, também gerenciado pelo Poetry.

Pre-Commit Hooks

Instalei Pre-commit para gerenciar hooks de pré-commit, Black para formatação de código, e Flake8 para garantir a conformidade com a PEP8. Pre-commit hooks são scripts que rodam automaticamente a cada commit e verificam se há erros no código, economizando tempo durante code reviews e processos de CI. Atualmente, estou rodando Black, Flake8 e Commitlint com o pre-commit-config.yaml, além de alguns hooks gerais.

Configuração do Pre-Commit YAML

repos:
-   repo: https://github.com/pre-commit/pre-commit-hooks
    rev: v4.6.0
    hooks:
    -   id: trailing-whitespace
    -   id: end-of-file-fixer
    -   id: check-added-large-files
    -   id: check-ast
    -   id: check-json
    -   id: check-toml
    -   id: check-yaml
-   repo: https://github.com/psf/black
    rev: 24.4.2
    hooks:
    - id: black
-   repo: https://github.com/PyCQA/flake8
    rev: 7.1.0
    hooks:
    - id: flake8
-   repo: https://github.com/opensource-nepal/commitlint
    rev: v1.0
    hooks:
    - id: commitlint

O Pre-commit foi instalado apenas no Poetry, enquanto Black e Flake8 foram instalados tanto no Poetry quanto no VS Code, pois rodam em contextos diferentes. Para testar se estava funcionando, fiz um commit e o retorno foi:

trim trailing whitespace.................................................Passed
fix end of files.........................................................Passed
check for added large files..............................................Passed
check python ast.....................................(no files to check)Skipped
check json...........................................(no files to check)Skipped
check toml...........................................(no files to check)Skipped
check yaml...........................................(no files to check)Skipped
black................................................(no files to check)Skipped
flake8...............................................(no files to check)Skipped
check python ast.....................................(no files to check)Skipped
check json...........................................(no files to check)Skipped
check toml...........................................(no files to check)Skipped
check yaml...........................................(no files to check)Skipped
black................................................(no files to check)Skipped
flake8...............................................(no files to check)Skipped
commitlint...............................................................Passed

Com isso, percebi que o pre-commit estava funcionando. Antes desse check final, um dos commits deu um erro por falta do “fix end of files”, mas ele corrigiu automaticamente o arquivo e só precisei fazer git add . e git commit -m novamente.

Testes Automatizados

Instalei Pytest para poder escrever e executar testes. Embora nunca tenha usado antes, quero começar a ter esse primeiro contato com testes mais propriamente ditos, já que normalmente criava arquivos logs para me ajudar com testes e debugs.

Automação de Commits

No decorrer dessa preparação inicial, senti a necessidade de automatizar meus commits. Sempre tento seguir as regras convencionais de commit, mas pode ser um pouco chato, pois não estou acostumado e preciso ficar pedindo ajuda ao CoPilot. Pesquisando, descobri que muitos automatizam o processo com Commitizen e Commitlint.

Commitizen

Commitizen é uma ferramenta de linha de comando que ajuda a criar mensagens de commit seguindo um formato específico. Ele faz várias perguntas sobre as mudanças e, com base nas respostas, monta a mensagem de acordo com o formato especificado.

Commitlint

Commitlint verifica se o commit está de acordo com o formato especificado e é instalado no commit hook, rodando toda vez que realizo um novo commit. Se o commit não seguir o formato, ele impede o commit.

Vocês não têm ideia de como estou amando pre-commits. Não acredito que vivi tanto tempo sem conhecer essa ferramenta. A capacidade de verificar e corrigir erros antes dos commits é incrível, sem falar na capacidade de corrigir automaticamente os erros.

Atualização do Template

O processo de criação do repositório em si não teve muitos problemas, mesmo utilizando várias ferramentas diferentes. O repositório já estava criado há um tempo e, recentemente, atualizei com o Commitizen e Commitlint. O maior problema foi nessa atualização, pois como ficou muito tempo sem ser usado, tudo estava desatualizado. No processo de atualização dos pacotes, acabei não atualizando o pre-commit hook junto, então o Commitizen estava pegando o path antigo do meu executável Python. Esse problema foi resolvido com um simples pre-commit autoupdate

Recursos do Repositório Template

  • Gerenciamento de Versão do Python: Gerenciado com Pyenv.
  • Gerenciamento de Dependências: Gerenciado com Poetry.
  • Formatação de Código: Configurado com Black.
  • Linting: Configurado com Flake8.
  • Testes: Testes unitários configurados com Pytest.
  • Hooks Pré-commit: Configurados com Pre-commit.
  • Padronização de Mensagens de Commit: Commitizen configurado para padronizar mensagens de commit.
  • Linting de Mensagens de Commit: Commitlint configurado para linting de mensagens de commit de acordo com os padrões de commit convencionais.

Considerações Finais

Estou extremamente satisfeito com o resultado atual e sinto que com essas ferramentas, a maturidade dos meus códigos vai estar em outro nível. Os commits realizados após a instalação do Commitizen e Commitlint já estão dando uma cara absurda de bom para o histórico de commit.

Você pode usar esse template caso esteja fazendo um projeto em Python e garanto que ele vai ajudar. O link para o repositório é: PyStarterKit. No README conto os passos para fazer com que tudo funcione corretamente na sua máquina. Estou com a ideia de criar um bash script para automatizar toda essa configuração e deixá-la ainda mais simples, mas isso fica para uma atualização futura. Estou com muita vontade de iniciar meu projeto logo! Se você acha que esse template pode melhorar, estou aberto a colaborações!

Por fim, agradeço por acompanhar até aqui. Espero que esse templeate seja útil para você também. Fique à vontade para deixar comentários, sugestões ou compartilhar suas experiências. Vamos juntos melhorar a qualidade dos nossos projetos em Python!

Até a próxima!