Escribiendo su primer parche para Django

Introducción

¿Interesado en dar un poco a la comunidad? Quizás ha encontrado un bug en Django que le gustaría ver solucionado, o quizás hay una pequeña característica que quiera agregar.

Contribuir con Django en sí es la mejor forma de ver abordadas tus propias inquietudes. Esto puede parecer intimidante al principio, pero en realidad es bastante simple. Te guiaremos a través de todo el proceso para que puedas aprender mediante ejemplos.

¿Para quién es este tutorial?

Ver también

Si usted está buscando una referencia sobre cómo presentar parches, consulte la documentación Submitting patches.

Para este tutorial, esperamos que comprenda al menos el funcionamiento básico de Django. Esto significa que usted no tendría problemas estudiando los tutoriales existentes para crear su primera aplicación Django. Adicionalmente, debería tener una buena comprensión de Python. Si no es así, `Dive into Python`__ es un libro fantástico (y gratuito) disponible en línea para los programadores que comienzan en Python.

Aquellos de ustedes que no están familiarizados con los sistemas de control de versiones y Trac encontrarán que este tutorial y sus vínculos incluyen información suficiente para empezar. Sin embargo, es probable que quiera leer un poco más acerca de estas diferentes herramientas si usted planea contribuir a Django con regularidad.

Sin embargo, en su mayor parte, este tutorial trata de explicar tanto como sea posible, de modo que pueda ser de utilidad para la audiencia más amplia.

Dónde obtener ayuda:

Si presentas problemas leyendo este tutorial, por favor envíe un mensaje a django-developers o visita `#django-dev en irc.freenode.net`__ para chatear con otros usuarios de Django que podrían ayudarte.

¿Qué cubre esta guía?

Te mostraremos cómo contribuir con parches para Django por primera vez. Al final de este tutorial, contará con un entendimiento básico sobre las herramientas y procesos implicados. Específicamente, cubriremos lo siguiente:

  • Instalando Git.
  • Descargue una copia de la versión de desarrollo de Django
  • Conjunto de pruebas de funcionamiento de Django.
  • Escribiendo una prueba para su parche.
  • Escribiendo el código para su parche.
  • Probando su parche.
  • Enviar una solicitud de pull.
  • Dónde buscar más información.

Una vez que haya terminado el tutorial, puede revisar el resto de la documentación para contribuir con Django. Contiene una gran cantidad de información de lectura obligatoria para todo el que desee convertirse en colaborador habitual de Django. Si tiene preguntas, es probable que obtenga las respuestas.

¡Python 3 es requerido!

La versión actual de Django no soporta Python 2.7. Obtén Python 3 en la página de descargas de Python o con el gestor de paquetes de tu sistema operativo.

Para los usuarios de Windows

Al instalar Python en Windows, asegúrese de revisar la opción «Añadir python.exe a la Ruta», de modo que siempre esté disponible en la línea de comandos.

Código de Conducta

Como un colaborador, usted puede ayudarnos a mantener abierta e inclusiva la comunidad Django. Por favor lea y siga nuestro Código de conducta.

Instalando Git

Para este tutorial, necesitará instalar Git para descargar la versión actual de desarrollo de Django y generar archivos de revisión de los cambios que realice.

Para revisar si tiene o no instalado Git , ejecute git en la línea de comandos. Si recibe un mensaje diciendo que el comando no pudo ser encontrado, tendrá que descargarlo e instalarlo, consulte `la página de descarga de Git`__.

Si no estás familiarizado con Git, siempre se puede encontrar más información sobre sus comandos (una vez instalado) escribiendo git help en la línea de comandos.

Obtener una copia de la versión de desarrollo de Django

El primer paso para contribuir con Django es obtener una copia del código fuente. Primero, haz un fork a Django en GitHub. Después, desde la línea de comandos, utiliza en comando cd para navegar hasta el directorio donde querrás que se aloje tu copia local de Django.

Descargue el repositorio de código fuente de Django con el siguiente comando:

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

Una conexión de ancho de banda bajo?

Puedes añadir el argumento --depth 1 al comando git clone para evitar descargar todo el historial de commits de Django, el cual reduce la transferencia de datos de ~250MB a ~70MB

Ahora que tiene una copia local de Django, puede instalarla como si fuera a instalar cualquier paquete utilizando pip. La forma más conveniente de hacerlo es mediante un entorno virtual, que es una función incorporada en Python que le permite mantener un directorio separado de paquetes instalados para cada uno de sus proyectos para que no interfieran entre sí.

Es una buena idea mantener todos sus entornos virtuales en un solo lugar, por ejemplo, en `` virtualenvs /`` en su directorio de inicio.

Crea un nuevo entorno virtual ejecutando:

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

La ruta es donde se guardará el nuevo entorno en su computadora.

El último paso para configurar su entorno virtual es activarlo:

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

Si el comando source no está disponible, puede intentar usar un punto en su lugar:

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

Para los usuarios de Windows

Para activar su entorno virtual en Windows ejecute:

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

Debe activar el entorno virtual cada vez que abra una nueva ventana de terminal. virtualenvwrapper__ es una herramienta útil para hacer esto más conveniente.

El nombre del entorno virtual actualmente activado se muestra en la línea de comandos para ayudarlo a realizar un seguimiento de cuál está utilizando. Todo lo que instales a través de pip mientras se muestre este nombre se instalará en ese entorno virtual, aislado de otros entornos y paquetes del systema.

Continúa e instala la copia previamente clonada de Django:

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

The installed version of Django is now pointing at your local copy by installing in editable mode. You will immediately see any changes you make to it, which is of great help when writing your first patch.

Creating projects with a local copy of Django

It may be helpful to test your local changes with a Django project. First you have to create a new virtual environment, install the previously cloned local copy of Django in editable mode, and create a new Django project outside of your local copy of Django. You will immediately see any changes you make to Django in your new project, which is of great help when writing your first patch.

Ejecutando el conjunto de pruebas de Django por primera vez

Al contribuir con Django, es muy importante que los cambios en el código no introduzcan errores en otras áreas de Django. Una forma de comprobar que Django aún funciona después de realizar los cambios es ejecutando el conjunto de pruebas de Django. Si todas las pruebas aún pasan, entonces puede estar razonablemente seguro de que sus cambios funcionan y no ha roto otras partes de Django. Si nunca ha ejecutado la suite de prueba de Django antes, es una buena idea ejecutarla una vez antes para familiarizarse con su salida.

Antes de ejecutar el conjunto de pruebas, instale sus dependencias, primero cambiándo al directorio tests/ de Django y después ejecutando:

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

Si encuentra un error durante la instalación, puede que su sistema carezca de alguna dependencia para uno o más de los paquetes de Python. Consulte la documentación del paquete que falla o busque en la web el mensaje de error que encuentre.

Ahora estamos listos para ejecutar el conjunto de pruebas. Si estás utilizando GNU/Linux, macOS o alguna otra distribución de Unix, ejecuta:

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

Ahora siéntate y relájate. El conjunto completo de pruebas de Django tiene miles de pruebas diferentes, así que puede tardar al menos cinco minutos, dependiendo de la velocidad de su ordenador.

Mientras se ejecuta la suite de pruebas de Django, verá una secuencia de caracteres que representan el estado de cada prueba a medida que se completa. `` E`` indica que un error se planteó durante una prueba, y `` F`` indica las afirmaciones de una prueba fallida. Ambos de estos son considerados como fallas de prueba. Mientras tanto, `` x`` y `` s`` indicaron fallas esperadas y pruebas omitidas, respectivamente. Los puntos indican pruebas superadas.

Las pruebas omitidas se deben usualmente a la ausencia de bibliotecas externas requeridas para la ejecución de los test; ver Running all the tests para la lista de dependencias y estar seguro de instalar aquellas relacionadas con los cambios que estás haciendo (no necesitamos ninguna para esta tutorial). Algunas pruebas son especificas de un backend de base de datos particular y serán omitidas si no se está probando ese backend. SQLite es el backend por defecto para las pruebas. Para ejecutar las pruebas con un backend diferente ver Using another settings module.

Una vez que las pruebas finalicen, usted debe ser recibido con un mensaje que le informa si el conjunto de pruebas pasó o falló. Dado que aún no ha realizado ningún cambio en el código de Django, todo el conjunto de pruebas debe pasar. Si obtiene fallos o errores asegúrese de que ha seguido correctamente todos los pasos anteriores . Consulte: ref: Ejecutar pruebas unitarias para más información.

Tenga en cuenta que la última versión de Django en master no siempre es estable. Cuando se desarrolla en master, puede comprobar `la integración continua de Django`__ para determinar si los fallos son propios de su sistema o se encuentran también presentes en la versión oficial. Si hace clic para ver una versión en particular, usted puede ver la «Matriz de configuración», que muestra los fallos analizados por la versión de Python y el backend de la base de datos.

Nota

Para este tutorial y el ticket en el que estamos trabajando, es suficiente probar contra SQLite, sin embargo, es posible (y a veces necesario) ejecutar las pruebas utilizando una base de datos diferente.

Trabajando en una característica

Para este tutorial, trabajaremos sobre un «falso ticket» como un caso de estudio. Estos son los datos imaginarios:

Ticket #99999 – Permitir hacer unas tostadas

Django debe proporcionar una función django.shortcuts.crear_tostadas() que devuelva 'tostadas'.

Bueno, ahora implemente la característica y sus tests asociados.

Crear una rama para su parche

Antes de hacer ningún cambio, cree una nueva rama para el ticket:

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

Puede elegir cualquier nombre que desee para la rama, por ejemplo «ticket_99999». Todos los cambios realizados en esta rama será específico para el ticket y no afecta la copia principal del código previamente clonado

Escribiendo algunas pruebas para su reporte

En la mayoría de los casos, para que un parche sea aceptado en Django tiene que incluir pruebas. Para los parches de corrección de bugs, esto significa escribir una prueba de regresión para asegurar que el bug no sea reintroducido en Django más adelante. Una prueba de regresión debe ser escrita de forma tal que falle mientras que todavía exista el bug y pase una vez que el bug se haya corregido. Para los parches que contienen nuevas características, tendrás que incluir pruebas que garanticen que dichas características estén funcionando correctamente. Los parches también deben fallar cuando la nueva característica no esté presente y por lo tanto, pasar una vez que haya sido aplicada.

Una buena forma de hacer esto, es escribir primero sus nuevas pruebas antes de realizar cualquier cambio en el código. Este estilo de desarrollo se llama `desarrollo guiado por pruebas`__ y se puede aplicar tanto a proyectos completos como a parches individuales. Después de escribir sus pruebas, ejecútelas para asegurarse de que en efecto fallan (ya que aún no ha corregido ese bug o añadido esa característica). Si sus nuevas pruebas no fallan, tendrá que arreglarlas de manera que lo hagan. Después de todo, una prueba de regresión que pasa sin importar si un error está presente, no es muy útil en prevenir que ese error se repita en el futuro.

Ahora a nuestro ejemplo práctico.

Escribiendo una prueba para el ticket #99999

Para resolver este ticket, agregaremos una función make_toast() al inicio de del módulo de django. Primero vamos a escribir una prueba que intente usar la función y verificar que su salida se vea correcta.

Navega a la carpeta tests/shortcuts/ y crea un nuevo fichero llamado test_make_toast.py. Añade el siguiente código:

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


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

Esta prueba comprueba que la función make_toast() devuelve 'toast'

Pero este asunto de las pruebas parece un poco difícil…

Si usted nunca había tenido que lidiar con las pruebas anteriormente, pueden parecer un poco difíciles de escribir a primera vista. Afortunadamente, las pruebas son un tema muy importante en la programación, así que hay mucha información disponible:

  • Un buen primer vistazo a las pruebas de escritura para Django se puede encontrar en la documentación en: doc:/topics/testing/overview.
  • Inmersión en Python (un libro en línea gratis para los desarrolladores principiantes de Python) incluye una gran `introducción a las pruebas unitarias`__.
  • Después de leer esos, si quieres algo un poco mas sustancioso para hincar el diente, siempre está la documentación de unittest de Python.

Ejecutando su nueva prueba

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.

Escribiendo el código para su ticket

Next we’ll be adding the make_toast() function.

Navigate to the django/ folder and open the shortcuts.py file. At the bottom, add:

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.

Ejecutando el conjunto de pruebas de Django por segunda vez

Una vez que haya verificado que su parche y su prueba funcionan correctamente, es una buena idea ejecutar todo el conjunto de pruebas de Django sólo para comprobar que su cambio no ha introducido ningún bug en otras áreas de Django. A pesar de que pasar con éxito todo el conjunto de pruebas no garantiza que su código está libre de errores, sí ayuda a identificar muchos bugs y regresiones que de otro modo podrían pasar desapercibidos.

Para ejecutar todo el conjunto de pruebas de Django, cambie al directorio tests/ de Django y ejecute:

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

Escribiendo la documentación

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 obtener más información sobre escribir la documentación, incluyendo una explicación de lo que se trata el fragmento versionadded, consulte Writing documentation. Esa página incluye también una explicación de cómo generar una copia de la documentación localmente, por lo que puede obtener una vista previa del código HTML que se generará.

Previsualizar sus cambios

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 las flechas del teclado para moverse arriba y abajo.

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')

Cuando hayas terminado de revisar el parche presiona q para volver a la línea de comandos. Si el contenido del parche se veía bien es tiempo de consumar los cambios.

Consumar los cambios en el parche

Para consumar los cambios:

$ git commit
...\> git commit

Esto abre un editor de texto para escribir el mensaje del commit. Sigue las guías para mensajes del commit y escribe un mensaje como:

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

Empujar el commit y hacer una solicitud de pull

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

Puedes crear una solicitud de pull visitando La página GitHub de Django. Vas a ver tu rama en «Your recently pushed branches». Has clic en «Compare & pull request».

Por favor no lo hagas para este tutorial, pero en la siguiente página muestra una vista previa del parche, deberías hacer clic en «Create pull request».

Próximos pasos

¡Enhorabuena, ha aprendido cómo hacer una solicitud de pull a Django! Encontrará detalles de técnicas más avanzadas que puede necesitar en Working with Git and GitHub.

Ahora puedes dar un buen uso a esas habilidades ayudando a mejorar la base de código de Django.

Más información para los nuevos colaboradores

Antes de que se involucre mucho en la escritura de parches para Django, hay algo más de información sobre cómo contribuir a la que probablemente debería echarle un vistazo:

  • Debe asegurarse de leer la documentación de Django sobre reclamar tickets y enviar parches. Esta incluye la etiqueta de Trac, cómo reclamar tickets para uno mismo, el estilo esperado de codificación para parches y muchos otros detalles importantes.
  • Las personas que colaboran por primera vez también deben leer la documentación para los colaboradores principiantes de Django. Tiene muchos buenos consejos para aquellos de nosotros que somos nuevos en esto de colaborar con Django.
  • Después de ellos, si todavía quiere más información sobre cómo contribuir, siempre se puede navegar por el resto de la documentación de Django sobre cómo contribuir. Este contiene un montón de información útil y debe ser su primera fuente para responder a cualquier pregunta que pueda tener.

Encontrando su primer ticket real

Una vez que haya revisado parte de esa información, estará listo para salir y encontrar un ticket al cual escribirle un parche. Preste especial atención a los tickets con el criterio de «easy pickings». Estos tickets son a menudo de carácter mucho más simples y son geniales para los que colaboran por primera vez. Una vez que esté familiarizado con como contribuir con Django, puede pasar a escribir parches para los tickets más difíciles y complicados.

Si lo que desea es empezar ya (¡Y nadie lo culparía!), trate de echar un vistazo a la lista de `los tickets sencillos que necesitan parches`__ y `los tickets sencillos que tienen parches que necesitan mejoras`__. Si se siente cómodo con la escritura de pruebas también puede ver la lista de “tickets sencillos que necesitan pruebas`__. Sólo recuerde seguir las directrices sobre cómo reclamar tickets que se mencionaron en el enlace a la documentación de Django sobre reclamar tickets y enviar parches.

¿Qué hay después de crear una solicitud de pull?

Después de que un ticket tiene un parche, necesita ser revisado por un segundo par de ojos. Después de enviar una solicitud de pull asegúrese de actualizar los metadatos del ticket mediante el establecimiento de banderas en el ticket para decir «tiene parche», «no necesita pruebas», etc, para que otros puedan encontrarlo para su revisión. Contribuir no necesariamente siempre significa escribir un parche desde cero. Revisar parches existentes es también una contribución muy útil. Consulte: doc:/internals/contributing/triaging-tickets para más detalles.

Back to Top