# 7. Extendiendo distutils

Nota

Este documento está siendo conservado sólo hasta que la documentación de `setuptools` en https://setuptools.readthedocs.io/en/latest/setuptools.html cubra de forma independiente toda la información actualmente incluida acá.

Distutils se puede extender de diversas maneras. La mayoría de las extensiones toman la forma de nuevos comandos o reemplazos de comandos ya existentes. Se pueden escribir nuevos comandos para soportar nuevos tipos de paquetes específicos de la plataforma, por ejemplo, mientras que se pueden reemplazar comandos existentes para modificar los detalles de cómo funciona dicho comando en un paquete.

La mayoría de las extensiones de distutils están hechas dentro de los scripts `setup.py` donde se desea modificar los comandos existentes. Muchos simplemente añaden algunas extensiones de archivo que deben copiarse dentro de los paquetes, además de los archivos `.py`, para mayor comodidad.

La mayoría de las implementaciones de comandos distutils son subclases de la clase `distutils.cmd.Command`. Los nuevos comandos pueden heredar directamente de `Command`. Mientras que los comandos de reemplazo a menudo derivan de la clase `Command` de manera indirecta, subclasificando directamente el comando que están reemplazando. Se requiere que los comandos deriven de `Command`.

## 7.1. Integrando nuevos comandos

Existen diferentes formas de integrar nuevas implementaciones de comandos en distutils. La más difícil es forzar la inclusión de nuevas funciones en distutils y esperar (y requerir) una versión de Python que brinde ese soporte. Esto es realmente complicado por muchas razones.

La más común, y posiblemente la más lógica para casi todas las necesidades, es incluir las nuevas implementaciones con su script `setup.py` y hacer que la función `distutils.core.setup()` las utilice:

    from distutils.command.build_py import build_py as _build_py
    from distutils.core import setup

    class build_py(_build_py):
        """Specialized Python source builder."""

        # implement whatever needs to be different...

    setup(cmdclass={'build_py': build_py},
          ...)

Este enfoque es más valioso sí las nuevas implementaciones deben utilizarse para hacer uso de un paquete en particular, ya que todos los interesados en el paquete deberán tener la implementación del nuevo comando.

A partir de Python 2.4, hay una tercera opción disponible, destinada a permitir agregar nuevos comandos que sean compatibles con los scripts `setup.py` existentes, sin requerir modificaciones en la instalación de Python. Se espera que esto permita que las extensiones de terceros brinden soporte para sistemas de empaquetado adicionales, pero los comandos pueden ser usados en los mismos casos en los que los comandos de distutils son utilizados. Una nueva opción de configuración, `command_packages` (opción de la línea de comandos `--command-packages`), puede ser aplicada para especificar paquetes adicionales a ser buscados para módulos que implementen comandos. Como todas las opciones de distutils, esto puede especificarse en la línea de comandos o en un archivo de configuración. Esta opción sólo se puede configurar en la sección `[global]` de un archivo de configuración, o antes de cualquier comando en la línea de comandos. Si se establece en un archivo de configuración, se puede sobrescribir desde la línea de comandos. Establecer una cadena de caracteres vacía como valor de esta opción en la línea de comandos forzará el uso del valor predeterminado. Esto nunca debería ser establecido en un archivo de configuración proporcionado con un paquete.

Esta nueva opción puede ser usada para añadir cualquier cantidad de número de paquetes a la lista de paquetes buscados para las implementaciones de comandos; los nombres múltiples de paquetes deben ser separados por comas. Cuando no se especifica, la búsqueda sólo se realiza en el paquete `distutils.command`. Sin embargo, cuando `setup.py` se ejecuta con la opción `--command-packages distcmds,buildcmds`, se buscarán los paquetes `distutils.command`, `distcmds` y `buildcmds` en ese orden. Se espera que los nuevos comandos se implementen en módulos con idéntico nombre que el comando mediante clases que comparten el mismo nombre. Dado el ejemplo anterior de la opción de línea de comandos, el comando bdist_openpkg podría ser implementado por la clase `distcmds.bdist_openpkg.bdist_openpkg` o por la clase `buildcmds.bdist_openpkg.bdist_openpkg`.

## 7.2. Añadiendo nuevos tipos de distribución

Los comandos que crean distribuciones (archivos en el directorio `dist/`) necesitan añadir el par `(command, filename)` a `self.distribution.dist_files` para que de este modo upload pueda subirlo a PyPI. El elemento filename en el par no contiene información de la ruta, solo el nombre del archive en sí. En el modo ensayo, los pares aún deben ser añadidos para representar lo que se habría creado.