Herramientas de configuración de Python: ¿Cómo puedo incluir un repositorio privado en install_requires?

83

Estoy creando un setup.pyarchivo para un proyecto que depende de repositorios privados de GitHub. Las partes relevantes del archivo se ven así:

from setuptools import setup
setup(name='my_project',
    ...,
    install_requires=[
        'public_package',
        'other_public_package',
        'private_repo_1',
        'private_repo_2',
    ],
    dependency_links=[
        'https://github.com/my_account/private_repo_1/master/tarball/',
        'https://github.com/my_account/private_repo_2/master/tarball/',
    ],
    ...,
)

Estoy usando en setuptoolslugar de distutilsporque este último no admite los argumentos install_requiresy dependency_linkssegún esta respuesta.

El archivo de configuración anterior no puede acceder a los repositorios privados con un error 404, lo cual es de esperar, ya que GitHub devuelve un 404 a solicitudes no autorizadas de un repositorio privado. Sin embargo, no puedo averiguar cómo setuptoolsautenticarme.

Aquí hay algunas cosas que he probado:

  1. Utilizar git+ssh://en lugar de https://en dependency_linkscomo lo haría si se instala con el repositorio pip. Esto falla porque setuptools no reconoce este protocolo ("tipo de URL desconocido: git + ssh"), aunque la documentación de distribución dice que debería hacerlo. Ídem git+httpsy git+http.

  2. https://<username>:<password>@github.com/...- sigue obteniendo un 404. (Este método tampoco funciona con curlo wgetdesde la línea de comandos, aunque curl -u <username> <repo_url> -O <output_file_name>funciona).

  3. Actualización de setuptools (0.9.7) y virtualenv (1.10) a las últimas versiones. También intenté instalar distribuir, aunque esta descripción general dice que se fusionó nuevamente con setuptools. De cualquier manera, sin dados.

Actualmente, acabo de setup.pyimprimir una advertencia de que los repositorios privados deben descargarse por separado. Obviamente, esto es menos que ideal. Siento que hay algo obvio que me estoy perdiendo, pero no puedo pensar qué podría ser. :)

Pregunta duplicada sin respuestas aquí .

Eric P
fuente
Acepta una solución.
wieczorek1990

Respuestas:

64

Estaba tratando de que esto funcionara para instalar con pip, pero lo anterior no me funcionaba. De [1] entendí PEP508que se debería usar el estándar, de [2] obtuve un ejemplo que realmente funciona (al menos en mi caso).

Tenga en cuenta; esto es con pip 20.0.2elPython 3.7.4

setup(
    name='<package>',
...
    install_requires=[
        '<normal_dependency>',
         # Private repository
        '<dependency_name> @ git+ssh://[email protected]/<user>/<repo_name>@<branch>',
         # Public repository
        '<dependency_name> @ git+https://github.com/<user>/<repo_name>@<branch>',
    ],
)

Después de especificar mi paquete de esta manera, la instalación funciona bien (también con -econfiguraciones y sin la necesidad de especificar --process-dependency-links).

Referencias [1] https://github.com/pypa/pip/issues/4187 [2] https://github.com/pypa/pip/issues/5566

Tom Hemmes
fuente
La #egg=...parte parece innecesaria ahora.
Huazuo Gao
1
¡Gracias! Tiene toda la razón, ambos #eggy branchson opcionales (ver editar) y también funciona para git+https.
Tom Hemmes
1
Si usa ssh://y se encuentra con, Could not resolve hostnamecambie :a /en su URL de clonación. Tuve este error con gitlab.
delijati
11
Eso parece no funcionar más ya que setuptools parece buscar un paquete en PyPi con el nombre de dependencia:, Reading https://pypi.org/simple/some-fake-name/y luego Couldn't find index page for 'some_fake_name' (maybe misspelled?). Al final, el último error que se muestra eserror: Could not find suitable distribution for Requirement.parse('some_fake_name@ git+ssh://[email protected]/cglacet/quadtree.git')
cglacet
1
Enfatice que <dependency_name> no es lo mismo que <repo_name> Y puede reemplazar 'ssh: // git @' con 'https: //' si es un repositorio público
Phil P
41

Esto es lo que funcionó para mí:

  install_requires=[
      'private_package_name==1.1',
  ],
  dependency_links=[
      'git+ssh://[email protected]/username/private_repo.git#egg=private_package_name-1.1',
  ]

Tenga en cuenta que debe tener el número de versión en el nombre del huevo, de lo contrario, dirá que no puede encontrar el paquete.

vadimg
fuente
3
Hola vadimg: ¿Qué versión de setuptools / distribuir estás usando? Obtengo "Tipo de URL desconocido: git + ssh" usando distribuir 0.7.3 (la última versión).
Eric P
2
Esto no funcionó para mí 3 años después ... Conseguido: No se pudo encontrar una versión que satisfaga el requisito
jsmedmar
7
A partir del 28 de octubre de 2016, este enfoque parece no funcionar
máximo
1
Con los pip modernos, debe incluir una opción, algo comopip install --process-dependency-links ...
Ash Berlin-Taylor
2
--process-dpendency-linksestá en desuso, vea mi respuesta usando la especificación de URL PEP508
Tom Hemmes
10

No pude encontrar ninguna buena documentación sobre esto, pero encontré la solución principalmente a través de prueba y error. Además, la instalación desde pip & setuptools tiene algunas diferencias sutiles; pero esta forma debería funcionar para ambos.

GitHub no ofrece (actualmente, a agosto de 2016) una manera fácil de obtener el zip / tarball de repositorios privados. Por lo tanto, debe señalar setuptools para decirle a setuptools que está apuntando a un repositorio de git:

from setuptools import setup
import os
# get deploy key from https://help.github.com/articles/git-automation-with-oauth-tokens/
github_token = os.environ['GITHUB_TOKEN']

setup(
    # ...
    install_requires='package',
    dependency_links = [
    'git+https://{github_token}@github.com/user/{package}.git/@{version}#egg={package}-0'
        .format(github_token=github_token, package=package, version=master)
        ] 

Un par de notas aquí:

  • Para repositorios privados, debe autenticarse con GitHub; la forma más sencilla que encontré es crear un token de Oauth, colocarlo en su entorno y luego incluirlo con la URL
  • Debe incluir algún número de versión (aquí está 0) al final del enlace, incluso si no hay ningún paquete en PyPI. Tiene que ser un número real, no una palabra.
  • git+Debe comenzar con para decirle a setuptools que debe clonar el repositorio, en lugar de apuntar a un zip / tarball
  • version puede ser una rama, una etiqueta o un hash de confirmación
  • Necesita suministrar --process-dependency-linkssi se instala desde pip
Maximiliano
fuente
Recibo una etiqueta de no se puede encontrar o un mensaje de rama. A pesar de que el repositorio privado que intento clonar tiene una etiqueta.
trendsetter37
1
Descubrí cuál era el problema. La etiqueta tenía un vprefijo en github. Así que necesitaba usar en v1.1.0lugar de 1.1.0en mi script setup.py.
trendsetter37
4

Encontré una solución (pirata):

#!/usr/bin/env python

from setuptools import setup
import os

os.system('pip install git+https://github-private.corp.com/user/repo.git@master')

setup( name='original-name'
     , ...
     , install_requires=['repo'] )

Entiendo que existen problemas éticos al tener una llamada al sistema en un script de configuración, pero no puedo pensar en otra forma de hacerlo.

cjohnson318
fuente
sí, esta también fue una solución desagradable para nosotros debido a lo siguiente: github.com/pypa/pip/issues/2822
Tommy
Esta es la única forma en que pude hacer que funcione, aunque acepté import pip. Ni la respuesta de @ vadimg ni esta sugerencia en pypa / pip funcionaron.
gens
4
Esto instalará una dependencia incluso si se ejecuta algo no relacionado con la instalación como python setup.py --version.
WhyNotHugo
1

A través de la respuesta de Tom Hemmes, encontré que esto es lo único que funcionó para mí:

    install_requires=[
        '<package> @ https://github.com/<username>/<package>/archive/<branch_name>.zip']
PidgeyBE
fuente
0

El uso de la URL de archivo de github funciona para mí, para repositorios públicos. P.ej

dependency_links = [
  'https://github.com/username/reponame/archive/master.zip#egg=eggname-version',
]
Overclockeado
fuente
¿Cómo encuentras el eggname-version?
cglacet
-1

Editar: esto parece funcionar solo con repositorios públicos de github, ver comentarios.

dependency_links=[
    'https://github.com/my_account/private_repo_1/tarball/master#egg=private_repo_1',
    'https://github.com/my_account/private_repo_2/tarball/master#egg=private_repo_2',
],

La sintaxis anterior parece funcionar para mí con setuptools 1.0. Por el momento, al menos la sintaxis de agregar "# egg = project_name-version" a las dependencias de VCS está documentada en el enlace que proporcionó para distribuir la documentación .

Wor
fuente
Sigo recibiendo el mismo error 404. ¿Los repositorios en su caso son privados? Soy consciente de la sintaxis # egg = pero no sé si afecta la autenticación.
Eric P
Lo siento, por supuesto, fue un proyecto de repositorio público. Probablemente no haya ninguna forma de hacer esto con las herramientas de configuración actuales si https // <nombre de usuario>: <contraseña> @ ... las URL de tarball no funcionan con los repositorios privados de githubs, ya que esta pregunta también parece indicar: tener-problemas-descargar -git-archive-tarballs-from-private-repo
wor
También puede probar la versión de desarrollo de setuptools y / o comprobar el código. El código relevante parece ser: package_index: fetch_distribution (): 534 package_index.py:_download_url():736
wor
-2

Este trabajo para nuestro escenario:

  1. el paquete está en github en un repositorio privado
  2. queremos instalarlo en paquetes de sitio (no en ./src con -e)
  3. poder usar pip install -r requirements.txt
  4. pudiendo usar pip install -e reposdir (o desde github), donde las dependencias solo se especifican en requirements.txt

https://github.com/pypa/pip/issues/3610#issuecomment-356687173

kotrfa
fuente