MEP11: Dependências de terceiros #

Este MEP tenta melhorar a maneira como as dependências de terceiros no matplotlib são tratadas.

Estado #

Concluído - precisa ser mesclado

Filiais e solicitações pull #

#1157: Use a resolução automática de dependências

Nº 1290: Desagregue o pyparsing

#1261: Atualização seis para 1.2

Resumo #

Um dos objetivos do matplotlib é mantê-lo o mais fácil possível de instalar. Para esse fim, algumas dependências de terceiros são incluídas na árvore de origem e, em determinadas circunstâncias, instaladas junto com o matplotlib. Este MEP visa resolver alguns problemas com essa abordagem, trazer alguma consistência, enquanto continua a tornar a instalação conveniente.

No momento em que foi feito inicialmente, setuptools , easy_install e PyPI não eram maduros o suficiente para serem confiáveis. No entanto, no momento, devemos ser capazes de aproveitar com segurança as versões "modernas" dessas ferramentas, distribua e pip .

Embora matplotlib tenha dependências de bibliotecas Python e bibliotecas C/C++, este MEP aborda apenas as bibliotecas Python para não confundir o problema. As bibliotecas C representam um conjunto de problemas maior e principalmente ortogonal.

Descrição detalhada #

matplotlib depende das seguintes bibliotecas Python de terceiros:

  • Numpy

  • dateutil (Python puro)

  • pytz (Python puro)

  • seis -- exigido por dateutil (Python puro)

  • pyparsing (Python puro)

  • PIL (opcional)

  • Estruturas de GUI: pygtk, gobject, tkinter, PySide, PyQt4, wx (todos opcionais, mas um é necessário para uma GUI interativa)

Comportamento atual #

Ao instalar a partir da fonte, um git checkout ou pip :

  • setup.pytenta . Se isso falhar, a instalação falhará.import numpy

  • Para cada um dos dateutil , pytz e six , setup.pytenta importá-los (do namespace de nível superior). Se isso falhar, matplotlib instala sua cópia local da biblioteca no namespace de nível superior.

  • pyparsing é sempre instalado dentro do namespace matplotlib.

Esse comportamento é mais surpreendente quando usado com pip , porque nenhuma resolução de dependência de pip é executada, embora provavelmente funcione para todos esses pacotes.

O fato de o pyparsing estar instalado no namespace matplotlib supostamente (#1290) confundiu alguns usuários fazendo-os pensar que é um módulo relacionado ao matplotlib e importá-lo de lá, em vez do nível superior.

Ao instalar usando o instalador do Windows, dateutil , pytz e six são instalados sempre no nível superior , substituindo potencialmente as cópias já instaladas dessas bibliotecas.

TODO: Descrever o comportamento com o instalador do OS-X.

Ao instalar usando um gerenciador de pacotes (Debian, RedHat, MacPorts etc.), esse comportamento realmente faz a coisa certa e não há patches especiais nos pacotes matplotlib para lidar com o fato de lidarmos com dateutil , pytz e six dessa maneira . No entanto, deve-se tomar cuidado para que qualquer abordagem adotada continue a funcionar nesse contexto.

Manter esses pacotes na árvore matplotlib e garantir que eles estejam atualizados é um fardo de manutenção. Novos recursos avançados que podem exigir uma biblioteca Python pura de terceiros têm uma barreira maior à inclusão devido a essa carga.

Comportamento desejado #

As dependências de terceiros são baixadas e instaladas de seus locais canônicos, aproveitando pip , distribui e PyPI .

dateutil , pytz e pyparsing devem ser transformados em dependências opcionais - embora obviamente alguns recursos falhariam se não fossem instalados. Isso permitirá que o usuário decida se deseja instalar um recurso específico.

Implementação #

Para instalar a partir do código-fonte e assumindo que o usuário tenha todos os compiladores e dependências de nível C, isso pode ser feito facilmente usando a distribuição e seguindo as instruções aqui . A única alteração prevista no código da biblioteca matplotlib será importar pyparsing do namespace de nível superior, em vez de dentro do matplotlib. Observe que a distribuição também nos permitirá remover a dependência direta de six , pois é, estritamente falando, apenas uma dependência direta de dateutil .

Para instalações binárias, há várias alternativas (aqui ordenadas do melhor/mais difícil para o pior/mais fácil):

  1. O instalador distutils wininst permite a execução de um script de pós-instalação. Pode ser possível obter este script para executar o pip para instalar as outras dependências. (Veja este tópico para alguém que já pisou nesse terreno antes).

  2. Continue a enviar dateutil , pytz , six e pyparsing em nosso instalador, mas use o script pós-instalação para instalá-los somente se ainda não puderem ser encontrados.

  3. Mova todos esses pacotes para dentro de um (novo) matplotlib.extern namespace para que fique claro para usuários externos que são pacotes externos. Adicione algumas importações condicionais na base de código principal do matplotlib para que dateutil (no nível superior) seja tentado primeiro e, com falha, matplotlib.extern.dateutilseja usado.

2 e 3 são indesejáveis, pois ainda exigem a manutenção de cópias desses pacotes em nossa árvore -- e isso é exacerbado pelo fato de serem menos usados ​​-- apenas nos instaladores binários. Nenhuma dessas 3 abordagens aborda o Numpy, que ainda terá que ser instalado manualmente usando um instalador.

TODO: Como isso se relaciona com o instalador do Mac OS-X?

Compatibilidade com versões anteriores #

No momento, o matplotlib pode ser instalado a partir do código-fonte em uma máquina sem dependências de terceiros e sem conexão com a Internet. Após essa alteração, uma conexão com a Internet (e um PyPI em funcionamento) será necessária para instalar o matplotlib pela primeira vez. (Atualizações subseqüentes do matplotlib ou trabalho de desenvolvimento serão executados sem acesso à rede).

Alternativas #

Distribuir ovos binários não parece uma solução utilizável. Isso requer a instalação do easy_install primeiro, e os usuários do Windows geralmente preferem o conhecido .exeou .msiinstalador que funciona imediatamente.