Escrevendo seu primeiro patch para Django

Introdução

Interessado em retribuir um pouco para a comunidade? Talvez você tenha encontrado uma falha no Django que você gostaria de ver corrigida, ou talvez exista uma pequena funcionalidade que poderia ser adicionada.

A melhor maneira de ver os seus próprios problemas serem resolvidos é contribuindo com o Django. Isto pode parecer assustador no começo, mas na verdade é bem simples. Nós lhe guiaremos por todo o processo para que você possa aprender através de exemplos.

Para quem se destina este tutorial?

Ver também

Se você está procurando por uma referência sobre como enviar pacotes, veja a Enviando patches documentação.

Para este tutorial, esperamos que você tenha ao menos um conhecimento básico de como o Django funciona. Isso significa que você precisa estar confortável com o tutoriai “Escrevendo sua primeira aplicação Django</intro/tutorial01>”. Além disso, você deve ter um bom conhecimento em Python. Mas se não tiver, “Dive Into Python” é um livro online fantástico (e gratuito) para iniciantes em Python.

Aqueles que não estão familiarizados com sistemas de controle de versão e Trac irão encontrar neste tutorial, e seus links inclusos, informações suficientes para iniciar. Entretanto, se você esta planejando contribuir com o Django regularmente, provavelmente você vai querer ler mais a respeito das destas diferentes ferramentas.

Para a maior parte, porém, este tutorial tenta explicar o máximo possível, tal que possa ser usado por um público mais amplo.

Onde obter ajuda:

Se você estiver enfrentando problemas durante este tutorial, por favor envie um mensagem par django-developers ou acesse `#django-dev on irc.freenode.net`__ para conversar com outros usuários de Django que podem ser capazes de ajudá-lo.

O que este tutorial cobre?

Nós iremos guir você para que contribua com um “patch” para o Django pela primeira vez. Ao final deste tutorial, você deve possuir o conhecimento básico tanto para as ferramentas quanto para os processos envolvidos. Nós iremos cobrir especialmente os seguintes tópicos:

  • Instalando Git.
  • Baixando uma cópia da versão de desenvolvimento do Django.
  • Executando suite de testes do Django.
  • Escrevendo um teste para o seu patch.
  • Escrevendo o código para o seu patch.
  • Testando o seu patch.
  • Submetendo um pull request.
  • Onde encontrar mais informações.

Uma vez que você terminar este tutorial, você pode olhar o restante da Documentação do Django sobre contribuição Ela contém muitas informações úteis e deve ser lida por quem deseja se tornar um contribuidor do Django. Caso tenha perguntas, a documentação provavelmente contem as respostas.

Python 3 é requerido!

A versão atual do Django não suporta Python 2.7. Baixe o Python 3 na página de downloads do Python <https://www.python.org/downloads/> ou no gerenciador de pacotes do seu sistema operacional.

Para usuários do Windows

Quando instalar o Python no Windows, tenha certeza que você marcou a opção “Add python.exe to Path”, então ele sempre vai estar disponível na linha de comando.

Código de Conduta

Como um contribuidor, você pode nos ajudar a manter a comunidade Django aberta e solidária. Por favor, leia e siga nosso ‘Código de conduta’ <https://www.djangoproject.com/conduct/>`_.

Instalando Git

Para este tutorial será necessário ter o Git instalado para fazer o download da versão corrente de desenvolvimento do Django e para gerar arquivos de “patch” para as mudanças que você faça.

Para verificar se o Git está instalado ou não no seu sistema, digite git na linha de comando. Se o resultado for uma mensagem dizendo que o comando não pode ser encontrado, você terá que fazer o download e instalar o Git. Dê uma olhada em `Git's download page`__.

Caso não esteja familiar com o Git, você sempre pode achar mais sobre seus comandos (uma vez que estiver instalado) digitando “git help” na linha de comando.

Obtendo uma cópia da versão de desenvolvimento do Django

O primeiro passo para contribuir com o Django é ter uma cópia dos arquivos do código fonte. Primeiro, faça um fork do projeto Django no GitHub. Então, a aprtir da linha de comando, use o comando cd para ir até o diretório onde você quer que fique sua cópia do projeto Django.

Baixe o código fonte do repositório do Django usando o seguinte comando:

$ git clone git@github.com:YourGitHubName/django.git
...\> git clone git@github.com:YourGitHubName/django.git

Conexão com baixa largura de banda?

Você pode adicionar o argumento --depth 1 ao executar git clone para evitar baixar todo o histórico de commits do Django, o que pode reduzir os dados transferidos de ~250MB para ~70MB.

Agora que você tem uma cópia local do Django, você pode instalá-lo da mesma forma que você instalaria qualquer pacote usando pip. A maneira mais conveniente de fazer isso é usando um ambiente virtual que é um recurso embutido no Python que permite que você mantenha um diretório separado para os pacotes instalados de cada um dos seus projetos para que uns não interfiram com os outros.

É uma boa ideia manter todos os seus virtualenvs em um lugar, por exemplo em .virtualenvs/ no seu diretório pessoal.

Crie um novo ambiente virtual executando:

$ python3 -m venv ~/.virtualenvs/djangodev
...\> py -m venv %HOMEPATH%\.virtualenvs\djangodev

O caminho é o local onde o novo ambiente será salvo em seu computador.

O último passo para configurar o seu ambiente virtual é ativá-lo:

$ source ~/.virtualenvs/djangodev/bin/activate

Se o comando source não estiver disponível, você pode tentar usar um ponto em vez disso:

$ . ~/.virtualenvs/djangodev/bin/activate

Para usuários do Windows

Para ativar seu ambiente virtual no Windows, execute:

...\> %HOMEPATH%\.virtualenvs\djangodev\Scripts\activate.bat

Você precisa ativar o ambiente virtual sempre que abrir uma nova janela do terminal. virtualenvwrapper__ é uma ferramenta útil para tornar isto mais conveniente.

O nome do ambiente virtual atualmente ativado é mostrado na linha de comando para ajudar você a acompanhar qual deles você está usando. Qualquer coisa que você instalar através do pip enquanto esse nome é exibido será instalado nesse ambiente virtual, isolado de outros ambientes e dos pacotes globais do sistema.

Vá em frente e instale a cópia anteriormente clonada do Django:

$ pip install -e /path/to/your/local/clone/django/
...\> pip install -e \path\to\your\local\clone\django\

A versão instalada do Django agora está apontando para a sua cópia local. Você verá as mudanças que fizer de forma imediata, o que é uma grande ajuda quando se está escrevendo o primeiro patch

Executando a suíte de testes do Django pela primeira vez

Ao contribuir com o Django é muito importante que as suas mudanças de código não criem bugs nas outras áreas do projeto. Uma forma de verificar é testar se tudo continua funcionando depois de suas alterações, rodando a suite de testes do Django. Se todos os testes passarem, tudo indica que suas mudanças não quebraram outras partes do Django. Se você nunca executou a suite de testes do Django antes, é uma boa ideia testar de antemão para se familiarizar com suas saídas.

Antes de executar a suíte de testes, instale as dependências entrando no diretório de testes do Django com o comando cd tests/ e então executando:

$ pip install -r requirements/py3.txt
...\> pip install -r requirements\py3.txt

Se encontrar algum erro durante a instalação, talvez esteja faltando no seu sistema alguma dependência de um ou mais pacotes Python. Consulte a documentação de pacotes faltantes ou procure na Web a mensagem de erro que encontrou.

Agora nós estamos prontos para usar a suíte de testes. Se você estiver usando GNU/Linux, macOS ou algum outro tipo de Unix, execute:

$ ./runtests.py
...\> runtests.py 

Agora, sente-se e relaxe. A suíte de testes completa do Django tem milhares de testes e leva pelo menos alguns minutos para executar, dependendo da velocidade do seu computador.

While Django’s test suite is running, you’ll see a stream of characters representing the status of each test as it completes. E indicates that an error was raised during a test, and F indicates that a test’s assertions failed. Both of these are considered to be test failures. Meanwhile, x and s indicated expected failures and skipped tests, respectively. Dots indicate passing tests.

Normalmente testes são pulados quando faltam bibliotecas externas necessárias para executar o teste; veja Rodando todos os testes para uma lista de dependências e para se certificar de instalar qualquer dependência relacionada com suas mudanças (nós não necessitamos de nenhuma para este tutorial). Alguns testes são específicos para um backend de uma data base de dados e serão ignorados se não testado com aquele backend. SQLite é a base de dados backend padrão nas configurações. Para executar os testes usando diferentes backends, veja Usando outro módulo settings.

Assim que os testes são finalizados, você deveria ser notificado com uma mensagem informando se a suíte de testes passou ou falhou. Uma vez que você não realizou mudanças no código do Django, toda a suíte de testes deveria passar. Se você receber notificação de falhas ou erros certifique-se de que você seguiu todos os passos anteriores de maneira apropriada. Ver executando-testes-de-unidade para mais informações.

Note that the latest Django master may not always be stable. When developing against master, you can check `Django's continuous integration builds`__ to determine if the failures are specific to your machine or if they are also present in Django’s official builds. If you click to view a particular build, you can view the “Configuration Matrix” which shows failures broken down by Python version and database backend.

Nota

Para este tutorial e para o ticket em que iremos trabalhar, testar usando o SQLite é suficiente. Entretanto, é possível (e às vezes necessário) usar um banco de dados diferente para testes.

Trabalhando em um recurso

Para este tutorial, nós iremos trabalhar em um “ticket falso” como um caso de estudo. Aqui estão os detalhes imaginários.

Ticket #99999 – Permitir fazer torradas.

Django deve prover uma função django.shortcuts.make_toast() que retorna 'toast'.

Nós iremos agora implementar este recurso e seus testes associados.

Criando uma branch para seu patch

Antes de fazer qualquer alteração, crie uma nova branch para o ticket:

$ git checkout -b ticket_99999
...\> git checkout -b ticket_99999

You can choose any name that you want for the branch, “ticket_99999” is an example. All changes made in this branch will be specific to the ticket and won’t affect the main copy of the code that we cloned earlier.

Escrevendo alguns testes para o seu ticket

Na maioria dos casos, para um patch ser aceito no Django, ele tem que incluir testes. Para patches de correção de erros, significa escrever um teste de regressão para garantir que o erro nunca mais seja reintroduzido no Django mais tarde. Um teste de regressão deve ser escrito de tal forma que irá falhar enquanto o erro ainda existir e passar uma vez que o erro foi corrigido. Para patches contendo novos recursos, você precisa incluir testes que garantem que os novos recursos estão funcionando corretamente. Eles também devem falhar quando o novo recurso não estiver presente, e em seguida passar, uma vez que foi implementado.

Uma boa maneira de fazer isso é escrever seus novos testes primeiro, antes de realizar quaisquer modificações no código. Este estilo de desenvolvimento é chamado `desenvolvimento orientado a testes`__ e pode ser aplicado tanto a projetos inteiros quanto a patches isolados. Após escrever seus testes você os roda para garantir que eles realmente falham (uma vez que você ainda não consertou o bug ou adicionou a nova funcionalidade). Se seus novos testes não falharem, você terá de corrigí-los para que falhem. Afinal, um teste de regressão que passa independentemente de um bug estar presente não é muito útil na prevenção de que um bug ocorra novamente no futuro.

Agora para nosso exemplo mão-na-massa.

Writing a test for ticket #99999

In order to resolve this ticket, we’ll add a make_toast() function to the top-level django module. First we are going to write a test that tries to use the function and check that its output looks correct.

Navigate to Django’s tests/shortcuts/ folder and create a new file test_make_toast.py. Add the following code:

from django.shortcuts import make_toast
from django.test import SimpleTestCase


class MakeToastTests(SimpleTestCase):
    def test_make_toast(self):
        self.assertEqual(make_toast(), 'toast')

Este testa verifica que o make_toast() returna 'toast'.

Mas esse lance de testar parece difícil…

Caso você nunca tenha lidado com testes anteriormente, num primeiro momento eles podem parecer um pouco difíceis de escrever . Felizmente, testes são um assunto muito extenso em programação de computadores, então existe muita informção por aí:

  • Uma boa introdução em testes para Django pode ser encontrada na documentação Writing and running tests.
  • Megulhando no Python (um livro gratuito online para desenvolvedores iniciantes de Python) inclui uma ótima `introdução ao Teste de Unidade`__.
  • Após essa leitura, se desejar algo a mais para se aprofundar, sempre há a documentação do Python sobre unittest.

Executando o seu novo teste

Since we haven’t made any modifications to django.shortcuts yet, our test should fail. Let’s run all the tests in the shortcuts folder to make sure that’s really what happens. cd to the Django tests/ directory and run:

$ ./runtests.py shortcuts
...\> runtests.py shortcuts

If the tests ran correctly, you should see one failure corresponding to the test method we added, with this error:

ImportError: cannot import name 'make_toast' from 'django.shortcuts'

If all of the tests passed, then you’ll want to make sure that you added the new test shown above to the appropriate folder and file name.

Escrevendo o código para o seu ticket

Em seguida nós adicionaremos a função make_toast().

Navegue até a pasta django/ e abra o arquivo shortcuts.py. No seu final adicione:

def make_toast():
    return 'toast'

Now we need to make sure that the test we wrote earlier passes, so we can see whether the code we added is working correctly. Again, navigate to the Django tests/ directory and run:

$ ./runtests.py shortcuts
...\> runtests.py shortcuts

Everything should pass. If it doesn’t, make sure you correctly added the function to the correct file.

Executando a suíte de testes do Django pela segunda vez

Depois de verificar que seu patch e seu teste estão funcionando corretamente, é uma boa ídeia executar toda a suite de testes do Django apenas para verificar se sua mudança não introduziu algum erro em outras áreas do Django. Ao passar com sucesso em toda a suite de testes, não garante que seu código esteja livre de erros, ele ajuda identificar muitos erros e regressões que poderiam passar despercebidos.

Para executar toda a suíte de testes do Django, `` cd`` no diretório `` testes / `` do Django e execute:

$ ./runtests.py
...\> runtests.py 

Escrevendo Documentação

This is a new feature, so it should be documented. Open the file docs/topics/http/shortcuts.txt and add the following at the end of the file:

``make_toast()``
================

.. versionadded:: 2.2

Returns ``'toast'``.

Since this new feature will be in an upcoming release it is also added to the release notes for the next version of Django. Open the release notes for the latest version in docs/releases/, which at time of writing is 2.2.txt. Add a note under the “Minor Features” header:

:mod:`django.shortcuts`
~~~~~~~~~~~~~~~~~~~~~~~

* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.

Para mais informações sobre escrita de documentação, incluindo uma explicação sobre o que versionadded significa, verifique Escrevendo a documentação. Essa página também inclui uma explicação sobre como construir uma cópia local da documentação, de maneira que você possa pré-visualizar o HTML que será gerado.

Visualizando suas alterações

Now it’s time to go through all the changes made in our patch. To stage all the changes ready for commit, run:

$ git add --all
...\> git add --all

Then display the differences between your current copy of Django (with your changes) and the revision that you initially checked out earlier in the tutorial with:

$ git diff --cached
...\> git diff --cached

Use as teclas direcionais para mover para cima e para baixo.

diff --git a/django/shortcuts.py b/django/shortcuts.py
index 7ab1df0e9d..8dde9e28d9 100644
--- a/django/shortcuts.py
+++ b/django/shortcuts.py
@@ -156,3 +156,7 @@ def resolve_url(to, *args, **kwargs):

     # Finally, fall back and assume it's a URL
     return to
+
+
+def make_toast():
+    return 'toast'
diff --git a/docs/releases/2.2.txt b/docs/releases/2.2.txt
index 7d85d30c4a..81518187b3 100644
--- a/docs/releases/2.2.txt
+++ b/docs/releases/2.2.txt
@@ -40,6 +40,11 @@ database constraints. Constraints are added to models using the
 Minor features
 --------------

+:mod:`django.shortcuts`
+~~~~~~~~~~~~~~~~~~~~~~~
+
+* The new :func:`django.shortcuts.make_toast` function returns ``'toast'``.
+
 :mod:`django.contrib.admin`
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~

diff --git a/docs/topics/http/shortcuts.txt b/docs/topics/http/shortcuts.txt
index 7b3a3a2c00..711bf6bb6d 100644
--- a/docs/topics/http/shortcuts.txt
+++ b/docs/topics/http/shortcuts.txt
@@ -271,3 +271,12 @@ This example is equivalent to::
         my_objects = list(MyModel.objects.filter(published=True))
         if not my_objects:
             raise Http404("No MyModel matches the given query.")
+
+``make_toast()``
+================
+
+.. function:: make_toast()
+
+.. versionadded:: 2.2
+
+Returns ``'toast'``.
diff --git a/tests/shortcuts/test_make_toast.py b/tests/shortcuts/test_make_toast.py
new file mode 100644
index 0000000000..6f4c627b6e
--- /dev/null
+++ b/tests/shortcuts/test_make_toast.py
@@ -0,0 +1,7 @@
+from django.shortcuts import make_toast
+from django.test import SimpleTestCase
+
+
+class MakeToastTests(SimpleTestCase):
+    def test_make_toast(self):
+        self.assertEqual(make_toast(), 'toast')

Uma vez que você tenha terminado de revisar o patch, pressione a tecla q para retornar à linha de comando. Se o conteúdo do patch estiver ok é hora de commitar as mudanças.

Cometendo as alterações no patch

Para cometer as alterações:

$ git commit
...\> git commit

Isso abre um editor de texto para digitar a mensagem do commit. Siga o guia de mensagens de commits e escreva uma mensagem tipo:

Fixed #99999 -- Added a shortcut function to make toast.

Enviando o commit e fazendo um pull request

After committing the patch, send it to your fork on GitHub (substitute “ticket_99999” with the name of your branch if it’s different):

$ git push origin ticket_99999
...\> git push origin ticket_99999

Você pode criar um pull request visitando a página do Django no GitHub. Você verá sua branch abaixo de “Your recently pushed branches”. Clique em “Compare & pull request” depois.

Por favor não faça isso para este tutorial, mas na próxima pagina que mostra uma prévia do patch, você clicaria em “Create pull request”.

Próximos passos

Parabéns, você aprendeu como fazer um pull request para Django! Detalhes de técnicas mais avançadas que você pode precisar estão em Trabalhando com Git e GitHub.

Agora você pode contribuir para ajudar a melhorar a base de código do Django.

Mais informações para novos contribuidores

Antes que você mergulhe na escrita de patches para o Django há mais algumas informações sobre contribuição que você provavelmente deveria dar uma olhada:

  • Você deve certificar-se de ler a documentação do Django em reinvidicando tickets e enviando patches. Ela abrange etiqueta Trac, como reivindicar bilhetes para si mesmo, estilo de codificação prevista para patches, e muitos outros detalhes importantes.
  • Os contribuidores de primeira viagem devem ler o documentação sobre contribuidores de primeira viagem. Ele tem muitos bons conselhos para aqueles que são novos para ajudar com Django.
  • Depois disso, se você ainda estiver ansioso para obter mais informações sobre como contribuir, você sempre pode navegar pelo resto da documentação do Django em contribuição. Ele contém um monte de informações úteis e deve ser sua primeira fonte para responder quaisquer perguntas que você possa ter.

Encontrando o seu primeiro ticket

Uma vez que tenha dado uma olhada nessa documentação, você estará pronto para ir procurar um ticket para escrever um “patch”. Preste especial atenção aos tickets marcados com o critério “easy pickings”. Estes tickets são em geral de natureza simples e bons para novos contribuidores. Uma vez que estiver familiarizado com contribuir para o Django, você pode ir adiante escrevendo “patches” para tickets mais difíceis e complicados.

Se você já quer começar agora (e ninguém iria culpá-lo!), tente dar uma olhada na lista de `tickets fáceis que precisam de patches`__ e os `tickets fáceis que têm patches que precisam de melhorias`__. Se você estiver familiarizado com a escrita de testes, você também pode olhar para a lista de `tickets simples que precisam de testes`__. Apenas lembre-se de seguir as orientações sobre a reivindicação de bilhetes que foram mencionados no link para a documentação do Django em reivindicar tickets e submeter patches.

O que vem depois de criar um pull request?

After a ticket has a patch, it needs to be reviewed by a second set of eyes. After submitting a pull request, update the ticket metadata by setting the flags on the ticket to say “has patch”, “doesn’t need tests”, etc, so others can find it for review. Contributing doesn’t necessarily always mean writing a patch from scratch. Reviewing existing patches is also a very helpful contribution. See Triangulando tickets for details.

Back to Top