Pipenv: [pergunta] Como integrar com setup.py?

Criado em 7 fev. 2017  ·  38Comentários  ·  Fonte: pypa/pipenv

Usando requirements.txt eu posso fazer isso:

from pip.req import parse_requirements
requirements = [str(r.req) for r in
                parse_requirements('requirements.txt', session=False)]
test_requirements = [str(r.req) for r in
                     parse_requirements('requirements-test.txt', session=False)]

Como posso fazer o mesmo usando o Pipfile?

Comentários muito úteis

Primeiro, aviso: Minha experiência é principalmente com pacotes lib. Posso perder alguns pontos. Tenho o direito de estar errado e estou pronto para usá-lo!
Além disso, isso me fez coçar a cabeça algumas vezes. Eu realmente gostaria de alguma revisão sobre isso.

Agora, vamos a isso.

Vou começar com esta declaração @elgertam :

[...] meu uso do Pipfile me leva a pensar que install_requires realmente é quase idêntico ao que vai no Pipfile. Se eu precisar de numpy, eu instalo numpy com pipenv e uma nova entrada vai para o grupo [packages] do meu Pipfile [...]

Você adicionou numpy ao seu ambiente, você não adicionou numpy às dependências do seu aplicativo.
São duas coisas diferentes. Continue lendo, você verá o que quero dizer.

Em outras palavras, meu uso é totalmente diferente do requirements.txt, que eu costumava gerar antes de confirmar usando pip freeze > requirements.txt.

Surpreendentemente, seu uso não é tão diferente se você pensar sobre isso:

  • Seu fluxo de trabalho anterior: pip install stuff -> pip freeze > requirements.txt -> alimentar install_requires de requirements.txt
  • Seu novo fluxo de trabalho (tentativa): pipenv install stuff -> Pipfile atualizado automaticamente -> tentando alimentar install_requires com o Pipfile .
  • Qual é a ideia pretendida: Adicionar coisas a install_requires -> pipenv install -> Ambiente e Pipfile.lock são atualizados.

E para que a maneira pretendida funcione, você quer um Pipfile que indique que você deseja instalar seu aplicativo.
Algo como o requests Pipfile vinculado por @isobit.

Ou, um exemplo:

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]
pytest = ">=2.8.0"
tox = "*"

[packages]
"-e ." = "*"

Seu Pipfile é para descrever seu ambiente, não as dependências de um pacote. Como você vê, o Pipfile acima define o que eu quero instalar, que é o pacote local em modo editável.

Isso pode parecer um pouco "inútil", pois agora é tudo conduzido por um único pacote, mas digamos que você queira instalar seu aplicativo, mas com requests[security] , mas não é uma dependência estrita do seu aplicativo, você faça pipenv install requests[security] , e então:

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]
pytest = ">=2.8.0"
tox = "*"

[packages]
"-e ." = "*"
requests = { extras = ['security'] }

E voilà, aqui está um exemplo da diferença entre seus requisitos abstratos e seus requisitos concretos. O mesmo vale se você quiser instalar gunicorn ou qualquer outra coisa necessária no ambiente, mas isso não faz parte do aplicativo em si.

O que estou perdendo aqui, @vphilippon? Por que os [packages] do Pipfile são muito restritos para uso em install_requires ou tests_require?

Se eu expliquei isso bem o suficiente, você pode ver que deveria ser o contrário.
Você coloca suas dependências em install_requires , você coloca seu pacote em Pipfile , e então você obtém um ambiente, com um Pipfile.lock para reprodutibilidade (pois ele resolverá e respeitará seu dependências do pacote).

Por test_require , admito que não tenho certeza se isso se encaixa em tudo isso. IIRC, é um recurso específico setuptools . Poderíamos argumentar que é um conjunto de dependências abstratas para teste e esperar que pipenv resolva e instale aquelas que fazem pipenv install --dev , para todos os pacotes, mas tenho a sensação de que não está certo. Eu não tenho uma ideia clara ou opinião sobre isso e a lógica em torno disso, desculpe.

Espero que tudo isso faça sentido de alguma forma.

Todos 38 comentários

Você deve conseguir fazer isso com o código abaixo. Isso carregará o Pipfile do seu projeto atual e retornará as dependências em uma lista compatível com pip.

from pipenv.project import Project
from pipenv.utils import convert_deps_to_pip

pfile = Project(chdir=False).parsed_pipfile
requirements = convert_deps_to_pip(pfile['packages'], r=False)
test_requirements = convert_deps_to_pip(pfile['dev-packages'], r=False)

Deixe-nos saber se você tiver mais alguma dúvida :)

O acima é muito útil. Eu tive problemas com setup.py dependendo do Pipenv ser instalado em um virtualenv antes que setup.py install (ou qualquer outra coisa) pudesse ser executado. As únicas soluções para esse problema que consigo pensar são vender o Pipenv em um projeto, o que parece menos que o ideal, ou até mesmo hackear o setup.py para instalar o Pipenv antes de tentar executar as importações from pipenv... , o que parece errado. Alguém tem alguma ideia ou solução melhor que essa?

Devemos ~assediar~ sugerir a outros na comunidade Python (PyPA, etc.) 😄

Ajudaria adicionar pipenv a setup_requires ? Parece que também pode ser necessário adicioná-lo a install_requires que parece lamentável.

Não faça isso.

@kennethreitz o que você quer dizer com "isto"? Você quer dizer a integração com setup.py, a solução @nateprewitt ou as duas últimas sugestões?

Então, como os usuários devem saber que precisam do pipenv instalado?

Como o pipenv é uma ferramenta usada para instalar coisas, não vice-versa, não há motivo para exigi-lo em seu setup.py. O que Kenneth está alertando é importar o pipenv no setup.py, pois é um aplicativo cli e pode causar problemas.

Em 17 de outubro de 2017, às 9h37, Iddan Ahahronson [email protected] escreveu:

Então, como os usuários devem saber que precisam do pipenv instalado?


Você está recebendo isso porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub ou silencie a conversa.

então como posso usar o código do @nateprewitt - em setup.py?

@iddan : Tentei resolver o problema de inicialização do Pipenv apenas vendendo uma versão do Pipenv no esqueleto do meu projeto (https://github.com/elgertam/cookiecutter-pypackage/blob/master/%7B%7Bcookiecutter.project_slug%7D %7D/setup.py). Até agora não tive nenhum problema, embora não possa dizer que tive muitas oportunidades de testá-lo em uma situação em que instalo um pacote usando setup.py .

Eu posso entender por que estaríamos preocupados em não executar uma CLI ao carregar setup.py, mas pelo que posso dizer, o código que estou usando (copiar e colar do post de @nateprewitt aqui) é bastante seguro.

Acho que esse hack não será mais necessário quando pip tiver componentes internos suficientes para entender o formato Pipfile.

@iddan , para ser claro, esse código é apenas para converter as dependências do Pipfiles em um formato de estilo requirements.txt que o pip lerá. Parece que Kenneth redigiu algo do post original, mas não tenho certeza do quê.

Pipenv é uma ferramenta de gerenciamento e implantação de ambiente, não para distribuição como setup.py. É altamente recomendável documentar que você está usando um Pipfile e possivelmente vincular a pipenv.org para obter instruções de instalação. Trate isso da mesma maneira que você trata o pip, não é esperado que um usuário instale o pip toda vez que instalar um novo pacote Python.

Eu entendo isso perfeitamente. O que eu não entendo é o que você espera que aconteça quando um usuário baixa um pacote usando este script e não tem o pipenv instalado

@nateprewitt , se quisermos distribuir um pacote então (pelos meios usuais, usando pip ), devemos manter uma cópia da lista de dependências em setup.py ou requirements.txt ? Eu esperava usar meu Pipfile como uma única fonte de verdade.

Para esclarecer, presumo que o código na primeira resposta deve ser executado como parte de uma compilação, em vez de realmente ser usado em um setup.py .

A menos que eu esteja muito enganado, o código em https://github.com/kennethreitz/pipenv/issues/209#issuecomment -278185133 é seguro para ser usado se você estiver construindo uma roda (=binary dist), mas não se você está construindo sdist (= source dist).

Para rodas, setup.py não é incluído no pacote (mas é avaliado em tempo de compilação, e os arquivos de metadados são construídos com base nas informações coletadas). Com rodas, setup.py nunca é executado na máquina onde o pacote está sendo instalado, apenas onde ele foi construído.

Com sdist, setup.py é realmente executado na máquina de instalação e, portanto pipenv precisa estar disponível lá.

Ai sim. @tuukkamustonen , meu caso de uso específico é um sdist. Como não quero exigir que o usuário do pacote instale pipenv antes de fazer um pip install , suponho que estou preso a derivar meu install_requires fora de setup.py (ou seja, manualmente ou como parte de uma compilação)?

Se estou lendo corretamente, acredito que Kenneth e os outros mantenedores não querem que tratemos Pipenv como uma dependência de projeto, como faríamos para pytest , ou mesmo uma dependência normal de pacote. Idealmente, parece que devemos instalar e atualizar Pipenv da mesma forma que o próprio pip , ou seja, pip é instalado quando o Python é instalado ou quando um virtualenv é criado. Foi isso que Kenneth quis dizer quando disse: "Não faça isso".

Dito isso, @isobit ecoou meus pensamentos de que Pipfile deveria ser a única fonte da verdade. Posso ver dois casos de uso convincentes para favorecer o Pipfile (e há outros): primeiro, um pipeline de CI/CD que depende do Pipfile para configurar o ambiente de compilação é muito mais robusto do que um que depende de requirements.txt; e segundo, um contribuidor pode tentar instalar cegamente um projeto baseado em Pipfile e pode ficar frustrado se python setup.py install não funcionar da maneira que ele espera. Considerando que nem o Pipenv nem o pip ciente do Pipfile são ferramentas padrão do Python ainda, e o Pipenv é de fato a implementação de referência para o Pipfile, temos poucas opções para resolver o problema:

1) Especifique na documentação do seu projeto que seu projeto depende de Pipenv . Você ainda pode depender de Pipenv em seu setup.py , e isso será interrompido se Pipenv não estiver instalado em seu ambiente Python. Concretamente, um colaborador do seu código teria que instalar manualmente Pipenv em seu virtualenv para instalar o projeto com setup.py .
2) Ainda tem setup.py dependente de requirements.txt , que você gera periodicamente com base em seu Pipfile . Isso permanece totalmente compatível com pip e setuptools , mas exige que qualquer mantenedor gere o requirements.txt sempre que o projeto for construído e implantado. Uma possível variação disso seria um pipeline de CI/CD atualizar o requirements.txt no momento da compilação.
3) Vendorize uma versão do Pipenv em um projeto e chame-o usando from _vendor.pipenv.project import Project... dentro setup.py . Uma variação disso pode ser importar apenas da versão do fornecedor quando a importação global falhar.
4) Alguma outra opção que não é apresentada aqui e que eu não sou inteligente o suficiente para pensar.

Estou usando pessoalmente (3) (consulte https://github.com/kennethreitz/pipenv/issues/209#issuecomment-300550425) até que o Pipfile se torne mais um padrão comum, momento em que não terei nenhum dos meus projetos dependem diretamente do código do Pipenv, já que o Pipenv parece claramente ser uma ferramenta para gerenciar um virtualenv baseado em um Pipfile, e não necessariamente uma biblioteca Pipfile em si.

Espero que isso esclareça o problema com base no que li aqui, mas se eu falei errado ou disse algo notório, por favor me avise @nateprewitt.

Tenho a sensação de que o problema aqui surge de um uso indevido original (IMO) do requirements.txt para começar. Isso é diferente do uso de pipenv .

Vou apontar para este maravilhoso artigo de Donald Stufft, setup.py vs requirements.txt:
https://caremad.io/posts/2013/07/setup-vs-requirement/

TL;DR (mas você realmente deveria ler): O setup.py de install_requires destina-se a detalhar os requisitos (dependências) de um pacote. O requirements.txt (que seria substituído pelo combo Pipfile / Pipfile.lock aqui) deve ser usado para listar quais pacotes exatos serão usados ​​para satisfazer o que é necessário, com base no metadados do setup.py , para tornar o ambiente reproduzível.
Preencher o install_requires do requirements.txt é como voltar atrás.

setup.py install_requires =/= requirements.txt (ou Pipfile / Pipfile.lock ).
Pipfile (ou melhor Pipfile.lock ) deve ser a única fonte de verdade dos pacotes a serem instalados no ambiente do aplicativo.
O setup.py de install_requires fornece metadados usados ​​para gerar um Pipfile.lock válido.

Acho que é daí que vem o atrito. Espero que isso faça sentido.

Gostei muito dessa resposta, Vincent, e concordo absolutamente que Pipfile.lock é um substituto completo (e melhor) para requirements.txt .

Tendo usado o Pipenv por alguns meses, porém, meu uso de Pipfile me leva a pensar que install_requires realmente é quase idêntico ao que vai no Pipfile . Se eu precisar numpy , eu pipenv install numpy e uma nova entrada entrará no grupo [packages] do meu Pipfile: numpy = "*" . Em outras palavras, meu uso é totalmente diferente de requirements.txt , que eu costumava gerar antes de confirmar usando pip freeze > requirements.txt .

Talvez esta seja apenas uma maneira peculiar que estou usando o Pipenv, e estou indo contra a corrente (também instalo meu virtualenv em .venv/ dentro do diretório do projeto, então sou um Pythonista desonesto), no qual caso eu possa facilmente cumprir com a convenção da comunidade Python de ter uma parede de separação entre setup.py e Pipfile | Pipfile.lock | requirements.txt .

O que estou perdendo aqui, @vphilippon?

Obrigado pela informação, @vphilippon. Talvez estejamos fazendo isso ao contrário, parece que o que realmente queremos é o inverso - uma maneira de usar deps abstratos de install_requires em nosso Pipfile, como Donald menciona em relação a -e . no requirements.txt . Parece que já havia um problema sobre isso (#339), mas não parecia ir a lugar nenhum.

Isso já está coberto pela sintaxe Pipfile? Acabei de notar que a biblioteca de solicitações Pipfile usa "e1839a8" = {path = ".", editable = true, extras=["socks"]} em sua seção de pacotes. Algo semelhante é aparente nos exemplos do Pipfile , mas não vejo nenhuma outra documentação.

Primeiro, aviso: Minha experiência é principalmente com pacotes lib. Posso perder alguns pontos. Tenho o direito de estar errado e estou pronto para usá-lo!
Além disso, isso me fez coçar a cabeça algumas vezes. Eu realmente gostaria de alguma revisão sobre isso.

Agora, vamos a isso.

Vou começar com esta declaração @elgertam :

[...] meu uso do Pipfile me leva a pensar que install_requires realmente é quase idêntico ao que vai no Pipfile. Se eu precisar de numpy, eu instalo numpy com pipenv e uma nova entrada vai para o grupo [packages] do meu Pipfile [...]

Você adicionou numpy ao seu ambiente, você não adicionou numpy às dependências do seu aplicativo.
São duas coisas diferentes. Continue lendo, você verá o que quero dizer.

Em outras palavras, meu uso é totalmente diferente do requirements.txt, que eu costumava gerar antes de confirmar usando pip freeze > requirements.txt.

Surpreendentemente, seu uso não é tão diferente se você pensar sobre isso:

  • Seu fluxo de trabalho anterior: pip install stuff -> pip freeze > requirements.txt -> alimentar install_requires de requirements.txt
  • Seu novo fluxo de trabalho (tentativa): pipenv install stuff -> Pipfile atualizado automaticamente -> tentando alimentar install_requires com o Pipfile .
  • Qual é a ideia pretendida: Adicionar coisas a install_requires -> pipenv install -> Ambiente e Pipfile.lock são atualizados.

E para que a maneira pretendida funcione, você quer um Pipfile que indique que você deseja instalar seu aplicativo.
Algo como o requests Pipfile vinculado por @isobit.

Ou, um exemplo:

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]
pytest = ">=2.8.0"
tox = "*"

[packages]
"-e ." = "*"

Seu Pipfile é para descrever seu ambiente, não as dependências de um pacote. Como você vê, o Pipfile acima define o que eu quero instalar, que é o pacote local em modo editável.

Isso pode parecer um pouco "inútil", pois agora é tudo conduzido por um único pacote, mas digamos que você queira instalar seu aplicativo, mas com requests[security] , mas não é uma dependência estrita do seu aplicativo, você faça pipenv install requests[security] , e então:

[[source]]
url = "https://pypi.python.org/simple"
verify_ssl = true

[dev-packages]
pytest = ">=2.8.0"
tox = "*"

[packages]
"-e ." = "*"
requests = { extras = ['security'] }

E voilà, aqui está um exemplo da diferença entre seus requisitos abstratos e seus requisitos concretos. O mesmo vale se você quiser instalar gunicorn ou qualquer outra coisa necessária no ambiente, mas isso não faz parte do aplicativo em si.

O que estou perdendo aqui, @vphilippon? Por que os [packages] do Pipfile são muito restritos para uso em install_requires ou tests_require?

Se eu expliquei isso bem o suficiente, você pode ver que deveria ser o contrário.
Você coloca suas dependências em install_requires , você coloca seu pacote em Pipfile , e então você obtém um ambiente, com um Pipfile.lock para reprodutibilidade (pois ele resolverá e respeitará seu dependências do pacote).

Por test_require , admito que não tenho certeza se isso se encaixa em tudo isso. IIRC, é um recurso específico setuptools . Poderíamos argumentar que é um conjunto de dependências abstratas para teste e esperar que pipenv resolva e instale aquelas que fazem pipenv install --dev , para todos os pacotes, mas tenho a sensação de que não está certo. Eu não tenho uma ideia clara ou opinião sobre isso e a lógica em torno disso, desculpe.

Espero que tudo isso faça sentido de alguma forma.

@vphilippon Você explicou muito bem e acho que me convenceu.

TL;DR: Especifique as dependências abstratas e absolutamente necessárias em setup.py , depois adicione contexto (e, portanto, concretude) em Pipfile e Pipfile.lock , incluindo o fantástico "-e ." = "*" entrada.

Um problema com https://github.com/kennethreitz/pipenv/issues/209#issuecomment -337409290 é que, quando queremos implantar nosso aplicativo em um servidor, não estamos obtendo um ambiente reproduzível.

Quero dizer, normalmente, ao desenvolver uma _library_ que será usada em outros projetos, queremos que nosso install_requires seja bem solto (=sem vinculação a versões exatas). sim. Mas quando estamos criando um aplicativo da Web (ou qualquer aplicativo) e implantando-o em um servidor remoto ou contêiner docker, provavelmente queremos dependências fixas. Mesmo se especificarmos versões exatas em install_requires , as dependências transitivas não são bloqueadas e a instalação pode realmente baixar uma versão diferente (mais recente) de uma dependência transitiva e isso pode interromper sua implantação.

(Declarar manualmente as versões exatas de dependências transitivas não é uma opção - muito complicado.)

Neste caso de uso, devemos depender de um arquivo de bloqueio estilo requirements.txt (que especifica versões exatas mesmo para dependências transitivas). No entanto, não parece que o pipenv permite excluir os requisitos de desenvolvimento em pipenv lock -r (por exemplo pipenv lock --no-dev -r ), para que possamos criar tal requirements.txt (que pode então ser ler em install_requires )?

Vou citar o artigo de Donald Stufft:

Um aplicativo normalmente tem um conjunto de dependências, muitas vezes até mesmo um conjunto muito complexo de dependências, com o qual foi testado. Sendo uma instância específica que foi implantada, ela normalmente não tem um nome nem nenhum outro metadados relacionados ao empacotamento. Isso se reflete nas habilidades de um arquivo de requisitos de pip.

Em outras palavras: o aplicativo não é o pacote. O aplicativo é o ambiente, com um conjunto de dependências concretas instaladas. As dependências de um aplicativo devem ser representadas por requirements.txt (ou Pipfile / Pipfile.lock ), não por um único pacote install_requires .

Pessoalmente, eu diria que o conjunto completo de dependências fixadas (incluindo a transitiva) deve estar em um requirements.txt para o aplicativo, não no setup.py do pacote. Isso descreve a ideia de que a implantação de um aplicativo não é feita com pip install myapp==1.0.0 , mas sim com pip install -r requirements.txt (ou pipenv install com Pipfile.lock ), onde o requirements.txt inclui myapp==1.0.0 , bem como todas as outras dependências e dependências transitivas, fixadas.
Pode parecer que estou indo um pouco longe, mas trabalhei em um contexto em que o "app" implantado é orientado por um conjunto de pacotes. Não há um único pacote que represente o aplicativo em si, então essa noção de que "o pacote não é o aplicativo" foi jogada na minha cara bem cedo 😄 .

Tenho a forte sensação de que Pipenv/Pipfile/Pipfile.lock segue essa ideia.
Seria por isso que parece haver uma lacuna para ir de Pipfile.lock para setup.py 's install_requires : realmente não deveria ser feito dessa maneira, em qualquer caso.

@maintainers Gostaria de sua opinião aqui para saber se é realmente assim que você vê tudo isso. Tenho pregado uma visão de como devemos tratar as dependências, mas também não quero falar em seu lugar.

@vphilippon Acho que existem diferentes pontos de vista e terminologia. Mas, em última análise, queremos uma lista de dependências fixadas para instalar. Portanto, um requirements.txt com versões fixadas (ou um pacote com tais dependências declaradas, realmente não importa). A questão é, como realmente criar esse arquivo?

Com pip-compile (de pip-tools ), posso compilar tal requirements.txt de requirements.in e conterá apenas as dependências não-dev que meu aplicativo precisa. Não tenho certeza se estou interpretando sua resposta corretamente - você realmente quer dizer que devemos manter as dependências fixadas requirements.txt manualmente (também duplicando um pouco o que já está em setup.py ), também para dependências transitivas? Isso não pode ser a solução...

Se houvesse pipenv lock --no-dev -r , acho que isso resolveria esse problema.

@tuukkamustonen Desculpe a confusão, eu estava realmente apenas abordando a ideia do install_requires vs requirements.txt / Pipfile / Pipfile.lock .

Portanto, um requirements.txt com versões fixadas (ou um pacote com tais dependências declaradas, não importa muito).

Eu acho que a distinção é muito importante, mas como você disse, há pontos de vista diferentes aqui. Vamos concordar em discordar por enquanto. Como nota lateral, seria bom ter um lugar para continuar no assunto sem adicionar ruído a um problema específico. Esse é o tipo de coisa que precisa de mais discussão e compartilhamento na comunidade, IMO.

No entanto, não parece que o pipenv permite excluir os requisitos de desenvolvimento em pipenv lock -r

Mas, em última análise, queremos uma lista de dependências fixadas para instalar. [...] A questão é, como realmente criar tal arquivo? [...] Com pip-compile (de pip-tools), posso compilar esse arquivo requirements.txt de requirements.in e ele conterá apenas as dependências não-dev que meu aplicativo precisa.

Ah, eu pulei essa parte no começo, desculpe. E parece que você está certo: não consigo encontrar uma maneira de dizer pipenv install --not-dev-stuff (eu tinha certeza de que havia um, estranho) e gerar um ambiente não-dev. Qual é o ponto de ter uma seção 2 separada então? Posso estar faltando alguma coisa agora, e isso não está relacionado ao uso com setup.py . Talvez valha a pena discutir em uma nova edição.

EDITAR:
Eu cometi um erro aqui. Eu realmente não encontrei uma maneira de gerar um Pipfile.lock sem pacotes dev, mas , em um novo ambiente, com Pipfile / Pipfile.lock existente, fazendo pipenv install não instala os pacotes dev. Isso não resolve o ponto do @tuukkamustonen , mas errei ao afirmar que não havia como instalar um "ambiente prod", erro meu.

Ufa, isso foi muito para recuperar o atraso.

A menos que eu esteja muito enganado, o código em #209 (comentário) é seguro para ser usado se você estiver construindo uma roda (=binary dist), mas não se você estiver construindo sdist (=source dist).

@tuukkamustonen isso se destina apenas a ser usado em um script autônomo para implantações, não o inclua em seu setup.py. Esta é uma solução semi-hacky de antes de termos pipenv lock -r , muitos meses atrás. Essa abordagem funcionará para o seu caso de uso de dividir packages e dev-packages .

Estou pessoalmente usando (3) (veja #209 (comentário)) até que o Pipfile se torne mais um padrão comum, ponto em que nenhum dos meus projetos depende diretamente do código do Pipenv, já que o Pipenv parece claramente ser um ferramenta para gerenciar um virtualenv baseado em um Pipfile, e não necessariamente uma biblioteca Pipfile em si.

@elgertam , parece que suas opiniões podem ter sido influenciadas desde este comentário, mas eu observaria que provavelmente não é uma boa ideia agrupar pipenv com seu projeto. Não há nada que proíba isso explicitamente, mas fazemos muitos patches de caminho que são propensos a causar problemas quando usados ​​assim. Acho que vou encerrar isso com um aviso de "use por sua conta e risco".

mantenedores Eu gostaria de sua opinião aqui para saber se é de fato como você vê tudo isso. Tenho pregado uma visão de como devemos tratar as dependências, mas também não quero falar em seu lugar.

Acho que você está bem alinhado com a nossa visão para a duração do projeto. Obrigado por compilar tudo isso e articular tão bem @vphilippon!

Parece que as outras partes relevantes desta discussão foram movidas para #942, então acho que estamos bem aqui. Por favor, ping-me se eu não abordar nada.

Segui com uma proposta concreta em https://github.com/pypa/pipfile/issues/98 que acredito nos dar algo acionável e pragmático que poderia melhorar o DX para manter bibliotecas Python.

Pensamentos?

import json, jmespath

install_requires = []
with open('Pipfile.lock') as f:
    context = json.loads(f.read())
    install_requires.extend(map(
        lambda n, v : n + v,
        jmespath.search('default | keys(@)', context),
        jmespath.search('default.*.version', context),
    ))

setup(
    name='foobar',
    packages=find_packages(),
    setup_requires=['jmespath'],
    install_requires=install_requires,
)

@cornfeedhobo meu entendimento é que setup_requires não funciona bem com pip. Você poderia elaborar um pouco sobre como você sugeriria usar esta amostra?

A amostra não funcionará a menos que você instale o jmespath primeiro porque setup.py é avaliado como código Python normal. O argumento setup_requires na verdade não alcança nada: se o programa chegar tão longe, o jmespath é garantido para ser instalado.

Eu mencionei isso em outro problema, mas não consigo localizá-lo (há tantas discussões duplicadas em todo o rastreador de problemas que é impossível encontrar mais nada), então vou dizer novamente: Por favor, não coloque nada não construído- em dentro do setup.py, a menos que você forneça o fallback adequado ou tenha um motivo perfeito. Um pacote contendo o setup.py acima nem funcionará com o Pipenv com jmespath instalado no virtualenv; O Pipenv invoca setup.py egg_info em um ambiente limpo e falhará ao executar a importação do jmespath. Esta é uma má prática. Por favor, evite.

@epot eu não sabia disso

@uranusjr Obrigado pela resposta bem pensada com detalhes. Estou apenas explorando toda essa questão, então posso voltar para mais constrangimento. Também estou rastreando pypa/pipfile#98

E se não exigirmos jmespath ?

import json


install_requires = []
tests_require = []

with open('Pipfile.lock') as fd:
    lock_data = json.load(fd)
    install_requires = [
        package_name + package_data['version']
        for package_name, package_data in lock_data['default'].items()
    ]
    tests_require = [
        package_name + package_data['version']
        for package_name, package_data in lock_data['develop'].items()
    ]

@mschwager Você não deseja fixar a versão ou os usuários terão dificuldades. #1921 é um exemplo de uma biblioteca que usa == acaba quebrando a compilação de um usuário.

Minhas desculpas, mas qual é a diferença entre usar setup.py para usá-lo como um pacote ou requirements.txt / Pipfile para gerenciar as dependências desse pacote? As bibliotecas necessárias TÊM que ser idênticas entre setup.py e requirements.txt / Pipfile certo? Portanto, não há razão para não integrar Pipfile . setup.py já analisa requirements.txt . Por que não deveria ser capaz de analisar Pipfile ?

Seria ótimo se livrar de requirements.txt e usar apenas Pipfile

Não, não há razão para eles serem idênticos. Essa é uma suposição bastante radical, e muitos na comunidade pediriam a diferença.

Há de fato, no entanto, razões pelas quais eles podem ser idênticos. O Pipenv não exclui isso. Está fora do escopo e não é suportado por este projeto. Você pode construir totalmente uma biblioteca para dar suporte a isso e aproveitar o PEP 518 , que é implementado no pip 10.0, para fornecer suporte em tempo de compilação.

Como você disse, não há razão para não permitir que setup.py analise o Pipfile. Estou ansioso para você fazer isso acontecer :)

Entenda que algumas pessoas gostam das bibliotecas abstratas do setup.py, mas isso não é obrigatório? Quero dizer, golang sofre apenas por ter requisitos concretos, mas ainda ser capaz de substituir uma lib necessária por seu próprio fork apenas porque corresponde ao nome? Compreensível que a interação setup.py não esteja no escopo.

No entanto, seria interessante ver qual é o roteiro de longo prazo do pipenv. Seria ótimo vê-lo se tornar a ferramenta em python. por exemplo, de alguma forma substitui setup.py ou gera um setup.py apropriado para o usuário, de qualquer forma pipenv sendo de fato gerenciador de pacotes é incrível. Gostaria de saber se existe a possibilidade de estender o escopo para incluir setup.py?

Se pipenv for como npm etc., então seu package.json permite instalação remota, não há razão para pipenv não poder interagir ou substituir setup.py, tornando-o no escopo. Estou fazendo sentido ou parece que estou tomando pílulas malucas?

Obrigado por pensar que é um must-have. Com você considerando isso tão crucial, acredito que seremos capazes de executar um sistema de compilação baseado em Pipfile em pouco tempo.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

FooBarQuaxx picture FooBarQuaxx  ·  3Comentários

xi picture xi  ·  3Comentários

ipmb picture ipmb  ·  3Comentários

bgjelstrup picture bgjelstrup  ·  3Comentários

jerzyk picture jerzyk  ·  3Comentários