2017-02-15 3 views
7

Que pouvons-nous mettre dans un fichier setup.py pour empêcher le pip de collecter et d'essayer d'installer un paquet en utilisant une version Python non supportée?Empêcher l'installation du paquet sur les anciennes versions de Python

Par exemple magicstack est un projet répertorié avec le classificateur Trove:

Programming Language :: Python :: 3 :: Only 

donc je pense le comportement suivant si pip --version est lié à Python 2.7:

$ pip install magicstack 
Collecting magicstack 
    Could not find a version that satisfies the requirement magicstack (from versions:) 
No matching distribution found for magicstack 

Mais le comportement réel est que pip recueille une version, la télécharge, tente de l'installer et échoue. Il existe par exemple d'autres versions de Python3, par exemple curio, qui s'installent correctement - car le setup.py n'utilisait rien de particulier à Python 3 - mais il échouait au moment de l'importation lorsqu'une syntaxe Python 3 seulement était utilisée. Et je suis sûr qu'il y a des paquets qui installent OK, importent OK, et peut-être seulement échouer à l'exécution!

Quelle est la méthode correcte pour spécifier vos versions Python prises en charge d'une manière que pip va respecter? J'ai trouvé une solution de contournement, consistant à télécharger uniquement un fichier de roue, et à refuser de télécharger une distribution .tar.gz, mais je serais intéressé de connaître le correctif approprié.


Edit: Comment ne sait pas pip télécharger la distribution de roue si le Python/os/architecture ne correspond pas à? Utilise-t-il simplement le .whl filename convention ou y a-t-il quelque chose de plus sophistiqué que ce qui se passe dans les coulisses? Pouvons-nous en quelque sorte donner les métadonnées à une distribution source pour faire pip faire la bonne chose avec les téléchargements .tar.gz?

+0

Je ne sais pas s'il s'agit de la réponse _right_ ... mais si 'magicstack' est python3 uniquement parce que' setup.py' échoue sur python2.x, alors il semble que l'une des façons possibles de faire ce travail est de forcer votre 'setup.py' à échouer sur les versions python inappropriées ... – mgilson

+0

Hacky. Si pip est lié à un interpréteur Python non supporté, je ne veux pas que le paquet soit collecté ou téléchargé du tout, encore moins une installation tentée en exécutant 'setup.py'. – wim

+0

Google apparaît certains [précédent] (http://stackoverflow.com/questions/13924931/setup-py-restrict-the-allowable-version-of-the-python-interpreter) [questions] (http: // stackoverflow .com/questions/13385337/distribute-distutils-spécifiez-python-version) avec des réponses disant que votre 'setup.py' vérifie la version de Python. – user2357112

Répondre

3

Il y a une façon correcte de le faire, mais malheureusement pip seulement commencé à le supporter dans la version 9.0.0 (publié 2016-11-02), et ainsi les utilisateurs avec des versions plus anciennes de pip continueront à télécharger des paquets willy-nilly quelle que soit la version de Python pour laquelle ils sont destinés.

Dans votre fichier setup.py, passez setup() un argument python_requires qui répertorie les versions de Python pris en charge de votre paquet en tant que PEP 440version specifier. Par exemple, si votre forfait est pour Python 3+ seulement, écrire:

setup(
    ... 
    python_requires='>=3', 
    ... 
) 

Si votre colis est pour Python 3.3 ans et plus, mais vous n'êtes pas prêt à engager à Python 4 support encore, écrire:

setup(
    ... 
    python_requires='~=3.3', 
    ... 
) 

Si votre colis est pour Python 2.6, 2.7 et toutes les versions de Python 3 à partir de 3,3, écrire:

setup(
    ... 
    python_requires='>=2.6, !=3.0.*, !=3.1.*, !=3.2.*, <4', 
    ... 
) 

Et ainsi de suite. Une fois cela fait, vous devrez mettre à jour votre version de setuptools à au moins 24.2.0 afin que l'argument python_requires soit traité; les versions antérieures l'ignoreront simplement avec un avertissement. Tous les sdists et les roues de votre projet construits après contiennent alors les métadonnées appropriées qui indiquent à PyPI de dire à quelles versions de Python elles sont destinées.

+0

Salut, merci pour la mise à jour. J'ai essayé votre solution, mais cela ne fonctionne pas comme prévu. J'ai mis à jour setuptools à v34.3.2, et téléchargé de nouvelles distributions en utilisant le kwarg 'python_requires'. Avec pip version 9.0.1 sur Python 3.6, le comportement est ** correct ** (pip refuse de télécharger/exécuter la distribution, et imprime les versions python requises/réelles). Cependant, en utilisant pip version 9.0.1 sur Python 2.7, c'est incorrect - la distribution est téléchargée et le 'setup.py' est exécuté. Il semble que les métadonnées pertinentes soient là (puisque cela fonctionne pour pip3) mais elles sont ignorées par pip2. Est-ce que je manque quelque chose? – wim

+0

@wim: Quel spécificateur de version avez-vous utilisé pour 'python_requires'? – jwodder

+0

J'ai utilisé 'python_requires> = '3.6.1'' pour appliquer la restriction sur les métadonnées, puis j'ai testé le pip 9.0.1 en utilisant des environnements virtuels dans 3.6.0 et 2.7.5. – wim

1

La distribution magicstack sur pypi est interrompue. Il échoue car la distribution source ne contient pas de package magicstack même si le setup.py de la distribution source indique qu'il devrait l'être.

Tant que pypi contient une distribution source (par exemple .tar.gz, .zip), pépin téléchargera que si elle ne peut pas trouver une distribution binaire correspondant (par exemple .egg, .whl) pour votre version de python/os/architecture. Vos options sont de télécharger uniquement les distributions binaires vers pypi (de préférence wheels), même si je ne sais même pas si les paquets pypi binaires sont autorisés. L'autre option est de vérifier le sys.version dans votre setup.py pour les versions compatibles et de lever une exception sinon.

+0

Le téléchargement de la distribution binaire uniquement est autorisé, j'ai effectivement mentionné cela dans ma question comme solution de contournement actuelle. Voir [toga-curses] (https://pypi.python.org/pypi/toga-curses/) pour un exemple de paquetage qui sera installé avec pip3 mais qui ne sera même pas vu par pip2. – wim