So schreiben Sie setup.py, um ein Git-Repo als Abhängigkeit einzuschließen

98

Ich versuche setup.pyfür mein Paket zu schreiben . Mein Paket muss eine Abhängigkeit von einem anderen Git-Repo angeben.

Das habe ich bisher:

from setuptools import setup, find_packages

setup(
    name='abc',
    packages=find_packages(),
    url='https://github.abc.com/abc/myabc',
    description='This is a description for abc',
    long_description=open('README.md').read(),
    install_requires=[
        "requests==2.7.0",
        "SomePrivateLib>=0.1.0",
        ],
    dependency_links = [
     "git+git://github.abc.com/abc/SomePrivateLib.git#egg=SomePrivateLib",
    ],
    include_package_data=True,
)

Wenn ich renne:

pip install -e https://github.abc.com/abc/myabc.git#egg=analyse

Ich bekomme

Es konnte keine Version gefunden werden, die die Anforderung SomePrivateLib> = 0.1.0 (aus Analyse) (aus Versionen :) erfüllt. Für SomePrivateLib> = 0.1.0 (aus Analyse) wurde keine übereinstimmende Verteilung gefunden.

Was mache ich falsch ?

Ankur Agarwal
quelle
Beachten Sie, dass setup.py und pip völlig unterschiedliche Systeme sind. Ein Problem, das ich hatte, war, dass ich dies für pip zum Laufen bringen konnte, aber nicht für setup.py.
Vieh

Antworten:

51

Den richtigen Weg dazu finden Sie hier .

dependency_links=['http://github.com/user/repo/tarball/master#egg=package-1.0']

Der Schlüssel ist nicht, einen Link zu einem Git-Repository zu geben, sondern einen Link zu einem Tarball. Github erstellt für Sie einen Tarball des Hauptzweigs, wenn Sie /tarball/masterwie oben gezeigt anhängen .

cel
quelle
17
Es sieht so aus, als ob diese Methode per github.com/pypa/pip/issues/3939
muon
3
Diese Methode ist auch für private Repositorys nutzlos, da keine Authentifizierung möglich ist.
Tedivm
3
Ich habe es geschafft, es zum Laufen zu bringen und habe eine weitere Antwort hinzugefügt.
Tedivm
1
Die /tarball/masterMethode funktioniert nicht für Gitlab
Martin Thoma
5
Veraltet. Die richtige Antwort ist die Verwendung von Pep508, beantwortet von @Dick Fox unten
SwimBikeRun
111

Nachdem ich das von @muon in den obigen Kommentaren verknüpfte Pip-Problem 3939 und dann die PEP-508-Spezifikation durchgearbeitet hatte , fand ich Erfolg darin, meine private Repo-Abhängigkeit setup.pymithilfe dieses Spezifikationsmusters in install_requires(nicht mehr dependency_links) zu installieren :

install_requires = [
  'some-pkg @ git+ssh://[email protected]/someorgname/[email protected]#egg=some-pkg',
]

Das @v1.1gibt das auf github erstellte Release-Tag an, das durch einen Zweig, ein Commit oder einen anderen Tag-Typ ersetzt werden kann.

Dick Fox
quelle
Hinweis: Dies funktioniert gut für lokale / private Pakete. Sie können jedoch kein Paket für PyPI freigeben, das diese Syntax in seiner setup.py verwendet
Brian
7
@Brian Könnten Sie bitte einen Link zur offiziellen Erklärung angeben?
Elefant
12
Beachten Sie, git+https://github.comdass Sie dies tun können, wenn Sie SSH nicht verwenden möchten.
Multithr3at3d
2
Was ist der richtige Ansatz für ein --upgrade? Obwohl ich eine Tag-Version spezifiziere, ignoriert ein Upgrade nur neuere Tag-Versionen
Piacenti
1
@Elephant Nicht super offiziell, aber dies sind zumindest Kommentare zum Pip GitHub-Projekt von tatsächlichen Mitgliedern des PyPA: github.com/pypa/pip/issues/4187#issuecomment-415667805 und weitere Erklärungen: github.com/pypa/pip / issue / 4187 # issuecomment-415067034
Dominick Pastore
20

Die folgende Antwort ist für Pip 19+ veraltet


Leider funktioniert die andere Antwort nicht mit privaten Repositorys, was einer der häufigsten Anwendungsfälle dafür ist. Ich habe es schließlich mit einer setup.pyDatei zum Laufen gebracht, die so aussieht:

from setuptools import setup, find_packages

setup(
    name = 'MyProject',
    version = '0.1.0',
    url = '',
    description = '',
    packages = find_packages(),
    install_requires = [
        # Github Private Repository - needs entry in `dependency_links`
        'ExampleRepo'
    ],

    dependency_links=[
        # Make sure to include the `#egg` portion so the `install_requires` recognizes the package
        'git+ssh://[email protected]/example_organization/ExampleRepo.git#egg=ExampleRepo-0.1'
    ]
)

Neuere Versionen von pip machen dies noch einfacher, da "dependency_links" nicht mehr benötigt werden -

from setuptools import setup, find_packages

setup(
    name = 'MyProject',
    version = '0.1.0',
    url = '',
    description = '',
    packages = find_packages(),
    install_requires = [
        # Github Private Repository
        'ExampleRepo @ git+ssh://[email protected]/example_organization/ExampleRepo.git#egg=ExampleRepo-0.1'
    ]
)
tedivm
quelle
1
Könnten Sie bitte -0.1näher erläutern, wofür Ihr Ansatz steht? Nehmen Sie die Versionsnummer aus einer Git-Version oder aus der setup.pyBeschreibung?
Peteris
2
Wenn Sie in der Datei setup.py einen bestimmten Zweig oder ein bestimmtes Tag verwenden möchten, formatieren Sie die Dinge etwas anders.
Tedivm
"Leider funktioniert die andere Antwort nicht mit privaten Repositories." Dies ist nicht mehr wahr. Fox ' Antwort funktioniert mit privatem Repo, ohne dass dependency_linksdies erforderlich ist (was veraltet ist )
Keto,
Danke @Keto! Ich weiß nicht, warum deine Bearbeitung abgelehnt wurde, aber die Mods, aber ich habe diese Ablehnung überschrieben, um der Antwort den Verfallshinweis hinzuzufügen.
Tedivm
3

Eine allgemeinere Antwort, um die Informationen aus der Datei Requeriments.txt zu erhalten, die ich mache:

from setuptools import setup, find_packages
from os import path

loc = path.abspath(path.dirname(__file__))

with open(loc + '/requirements.txt') as f:
    requirements = f.read().splitlines()

required = []
dependency_links = []
# do not add to required lines pointing to git repositories
EGG_MARK = '#egg='
for line in requirements:
    if line.startswith('-e git:') or line.startswith('-e git+') or \
            line.startswith('git:') or line.startswith('git+'):
        if EGG_MARK in line:
            package_name = line[line.find(EGG_MARK) + len(EGG_MARK):]
            required.append(package_name)
            dependency_links.append(line)
        else:
            print('Dependency to a git repository should have the format:')
            print('git+ssh://[email protected]/xxxxx/xxxxxx#egg=package_name')
    else:
        required.append(line)

setup(
    name='myproject',  # Required
    version='0.0.1',  # Required
    description='Description here....',  # Required
    packages=find_packages(),  # Required
    install_requires=required,
    dependency_links=dependency_links,
) 
Gonzalo Odiard
quelle
1

Wenn Sie Ihre Pakete rekursiv installierbar machen möchten (YourCurrentPackage enthält Ihre SomePrivateLib), z. B. wenn Sie YourCurrentPackage in eine andere einbinden möchten (wie OuterPackage -> YourCurrentPackage -> SomePrivateLib), benötigen Sie beide:

install_requires=[
    ...,
    "SomePrivateLib @ git+ssh://github.abc.com/abc/[email protected]#egg=SomePrivateLib"
],
dependency_links = [
    "git+ssh://github.abc.com/abc/[email protected]#egg=SomePrivateLib"
]

Und stellen Sie sicher, dass Sie ein Tag mit Ihrer Versionsnummer erstellt haben.

Auch wenn Ihr Git-Projekt privat ist und Sie es im Container installieren möchten, z. B. Docker oder GitLab Runner, benötigen Sie autorisierten Zugriff auf Ihr Repo. Bitte denken Sie daran, git + https mit Zugriffstoken zu verwenden (wie bei GitLab: https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html ):

import os
from setuptools import setup

TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')

setup(
    ....

    install_requires=[
            ...,
            f"SomePrivateLib @ git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/[email protected]#egg=SomePrivateLib"
    ],
    dependency_links = [
            f"git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/[email protected]#egg=SomePrivateLib"
    ]
)
Darencorp
quelle
0

Ich war erfolgreich mit diesen 3 Optionen in Gitlab. Ich benutze Version 11 von Gitlab.

Option 1 - kein Token angegeben. Die Shell fragt nach Benutzername / Passwort.

from setuptools import setup

TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')

setup(
    install_requires=[
        "SomePrivateLib @ git+https://gitlab.server.com/abc/[email protected]#egg=SomePrivateLib"
    ]
)

Option 2 - Benutzerzugriffstoken angegeben. Token generiert über gitlab> Konto oben rechts> Einstellungen> Zugriffstoken. Erstellen Sie ein Token mit read_repository-Rechten.

Beispiel:

import os
from setuptools import setup

TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')

setup(
    install_requires=[
        f"SomePrivateLib @ git+https://gitlab-ci-token:{TOKEN_VALUE}@gitlab.server.com/abc/[email protected]#egg=SomePrivateLib"
    ]
)

Option 3 - Token auf Repository-Ebene angegeben. Token, das generiert wird, indem Sie zu Repository> Einstellungen> Repository> Token bereitstellen gehen. Erstellen Sie von hier aus ein Token mit den Rechten read_repository.

Beispiel:

import os
from setuptools import setup

TOKEN_USER = os.getenv('EXPORTED_TOKEN_USER')
TOKEN_VALUE = os.getenv('EXPORTED_VAR_WITH_TOKEN')

setup(
    install_requires=[
        f"SomePrivateLib @ git+https://{TOKEN_USER}:{TOKEN_VALUE}@gitlab.server.com/abc/[email protected]#egg=SomePrivateLib"
    ]
)

In allen drei Fällen konnte ich einfach Folgendes tun: "SomePrivateLib @ git + https: //gitlab.server.com/abc/SomePrivateLib.git" ohne die Markierung #egg am Ende.

ErikW
quelle