8. Estendendo Distutils

Distutils podem ser estendidos de várias maneiras. A maioria das extensões assume a forma de novos comandos ou substituições de comandos existentes. Novos comandos podem ser gravados para dar suporte a novos tipos de pacotes específicos da plataforma, por exemplo, enquanto substituições de comandos existentes podem ser feitas para modificar detalhes de como o comando opera em um pacote.

A maioria das extensões dos distutils é feita dentro de scripts setup.py que desejam modificar comandos existentes; muitos simplesmente adicionam algumas extensões de arquivo que devem ser copiadas em pacotes, além de .py como uma conveniência.

A maioria das implementações de comando distutils são subclasses da classe distutils.cmd.Command. Novos comandos podem herdar diretamente de Command, enquanto substituições geralmente derivam de Command indiretamente, subclassificando diretamente o comando que eles estão substituindo. Os comandos são necessários para derivar de Command.

8.1. Integrando novos comandos

Existem diferentes maneiras de integrar novas implementações de comando nos distutils. O mais difícil é fazer lobby para a inclusão dos novos recursos no próprio distutils e aguardar (e exigir) uma versão do Python que forneça esse suporte. Isso é realmente difícil por vários motivos.

O mais comum, e possivelmente o mais razoável para a maioria das necessidades, é incluir as novas implementações com o script setup.py e fazer com que a função distutils.core.setup() use-as:

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},
      ...)

Essa abordagem é mais valiosa se as novas implementações precisarem ser usadas para usar um pacote específico, pois todos os interessados no pacote precisarão ter a nova implementação de comando.

A partir do Python 2.4, uma terceira opção está disponível, destinada a permitir que novos comandos sejam adicionados, os quais podem ter suporte a scripts setup.py existentes sem exigir modificações na instalação do Python. Espera-se que isso permita que extensões de terceiros forneçam suporte a sistemas de empacotamento adicionais, mas os comandos podem ser usados ​​para qualquer coisa em que os comandos distutils possam ser usados. Uma nova opção de configuração, command_packages (opção da linha de comando --command-packages), pode ser usada para especificar pacotes adicionais a serem pesquisados ​​por módulos que implementam comandos. Como todas as opções do distutils, isso pode ser especificado na linha de comando ou em um arquivo de configuração. Esta opção só pode ser definida na seção [global] de um arquivo de configuração ou antes de qualquer comando na linha de comando. Se definido em um arquivo de configuração, ele poderá ser substituído na linha de comando; defini-lo como uma sequência vazia na linha de comando faz com que o padrão seja usado. Isso nunca deve ser definido em um arquivo de configuração fornecido com um pacote.

Esta nova opção pode ser usada para adicionar qualquer número de pacotes à lista de pacotes pesquisados para implementações de comandos; vários nomes de pacotes devem ser separados por vírgulas. Quando não especificada, a pesquisa é realizada apenas no pacote distutils.command. Quando setup.py é executado com a opção --command-packages distcmds,buildcmds, no entanto, os pacotes distutils.command, distcmds e buildcmds será pesquisado nessa ordem. Espera-se que novos comandos sejam implementados em módulos com o mesmo nome que o comando por classes que compartilham o mesmo nome. Dada a opção de linha de comando de exemplo acima, o comando bdist_openpkg pode ser implementado pela classe distcmds.bdist_openpkg.bdist_openpkg ou buildcmds.bdist_openpkg.bdist_openpkg.

8.2. Adicionando novos tipos de distribuição

Os comandos que criam distribuições (arquivos no diretório dist/) precisam adicionar pares (command, filename) ao self.distribution.dist_files para que upload possa ser carregado para o PyPI. O nome do arquivo no par não contém informações de caminho, apenas o nome do próprio arquivo. No modo de execução a seco, os pares ainda devem ser adicionados para representar o que teria sido criado.