Python et pip, liste toutes les versions d'un package disponibles?

445

Étant donné le nom d'un package Python qui peut être installé avec pip , existe-t-il un moyen de trouver une liste de toutes les versions possibles de celui-ci que pip pourrait installer? En ce moment, c'est un essai et une erreur.

J'essaie d'installer une version pour une bibliothèque tierce, mais la dernière version est trop nouvelle, des modifications incompatibles ont été apportées. J'aimerais donc avoir en quelque sorte une liste de toutes les versions connues de pip, afin de pouvoir les tester.

Rory
la source
1
La réponse acceptée n'est pas équivalente à l'autre avec le script car ils ne génèrent pas la même sortie.
oligofren
17
Veuillez mettre à jour la réponse sélectionnée. Le jaune est cassé et inutile. La réponse avec pip install pylibmc==est parfaite.
Jonathan
Veuillez mettre à jour la réponse acceptée comme le suggère @Jonathan. Je ne dirais pas que c'est parfait car cela ne fonctionnera pas sur les versions antérieures de pip (v7 ou v8), mais c'est génial sinon.
Antony Hatchkins
1
@Rory, veuillez mettre à jour la réponse acceptée, le jaune est mort. La réponse de Chris Montanaro est la meilleure méthode actuellement OMI.
Ryan Fisher
1
@Rory Veuillez modifier la réponse acceptée au profit des futurs visiteurs de cette question populaire. Le projet Yolk n'est plus maintenu et ne fonctionne tout simplement pas comme le prétend cette réponse.
wim

Réponses:

167

(mise à jour: en mars 2020, de nombreuses personnes ont signalé que le jaune, installé via pip install yolk3k, ne renvoyait que la dernière version. La réponse de Chris semble avoir le plus de votes positifs et a fonctionné pour moi)

Le script de pastebin fonctionne. Cependant, ce n'est pas très pratique si vous travaillez avec plusieurs environnements / hôtes car vous devrez le copier / créer à chaque fois.

Une meilleure solution globale serait d'utiliser yolk3k , qui est disponible pour l'installation avec pip. Par exemple, pour voir quelles versions de Django sont disponibles:

$ pip install yolk3k
$ yolk -V django
Django 1.3
Django 1.2.5
Django 1.2.4
Django 1.2.3
Django 1.2.2
Django 1.2.1
Django 1.2
Django 1.1.4
Django 1.1.3
Django 1.1.2
Django 1.0.4

yolk3kest une fourche de l'original yolkqui a cessé son développement en 2012 . Bien qu'il yolkne soit plus maintenu (comme indiqué dans les commentaires ci-dessous), il yolk3ksemble être et prend en charge Python 3.

Remarque: je ne suis pas impliqué dans le développement de yolk3k. Si quelque chose ne semble pas fonctionner comme il se doit, laisser un commentaire ici ne devrait pas faire beaucoup de différence. Utilisez plutôt le traqueur de problèmes yolk3k et envisagez de soumettre un correctif, si possible.

m000
la source
4
La réponse ci-dessous (en utilisant le script de pastebin) est plus lourde, mais fonctionne au moins dans mon cas (recherche de versions de scipy). jaune ne montre que la dernière version disponible, l'autre script montre toutes les versions datant de 0.8.0.
oligofren
31
La plupart du temps, il ne renverra que la dernière version
PawelRoman
17
Fir python3 utilise simplement pip install yolk3k. La commande yolk sera disponible.
Pierre Criulanscy
9
Comme le jaune, la plupart du temps, le jaune 3 ne renvoie que la dernière version.
diabloneo
4
le jaune est cassé / n'est plus entretenu. supprimez cette réponse.
wim
840

Pour pip> = 9,0 utiliser

$ pip install pylibmc==
Collecting pylibmc==
  Could not find a version that satisfies the requirement pylibmc== (from 
  versions: 0.2, 0.3, 0.4, 0.5.1, 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.5, 0.6.1, 0.6, 
  0.7.1, 0.7.2, 0.7.3, 0.7.4, 0.7, 0.8.1, 0.8.2, 0.8, 0.9.1, 0.9.2, 0.9, 
  1.0-alpha, 1.0-beta, 1.0, 1.1.1, 1.1, 1.2.0, 1.2.1, 1.2.2, 1.2.3, 1.3.0)
No matching distribution found for pylibmc==

- toutes les versions disponibles seront imprimées sans réellement télécharger ou installer de packages supplémentaires.

Pour pip <9.0 utilisation

pip install pylibmc==blork

blorkpeut être n'importe quelle chaîne qui n'est pas un numéro de version valide .

Chris Montanaro
la source
25
Je trouve étrange que l'erreur de pip crache toutes les versions mais ils n'ont aucun argument pour obtenir explicitement lesdites données
Chris Montanaro
2
Une autre belle propriété de cette solution est qu'elle fonctionne avec tous les indicateurs normaux pour limiter les sources d'installation. Par exemple pip install --only-binary :all: pylibmc, répertoriera toutes les versions de pylibmc disponibles sous forme de packages binaires.
pavon
3
pip install pylibmc==9999999 | tr ', ' "\n" | sort -n
Vikas
18
Cela doit être marqué comme la bonne réponse car il ne nécessite aucun autre package à installer.
Yves Dorfsman
5
C'est un peu ridicule que cela semble être la seule façon de le faire en pip. J'espère qu'il y a au moins un problème ouvert à ce sujet sur leur traqueur de bogues?
pmos
69

Mise à jour: depuis
septembre 2017, cette méthode ne fonctionne plus: a --no-installété supprimée dans le pip 7

Utilisez pip install -v, vous pouvez voir toutes les versions disponibles

root@node7:~# pip install web.py -v
Downloading/unpacking web.py
  Using version 0.37 (newest of versions: 0.37, 0.36, 0.35, 0.34, 0.33, 0.33, 0.32, 0.31, 0.22, 0.2)
  Downloading web.py-0.37.tar.gz (90Kb): 90Kb downloaded
  Running setup.py egg_info for package web.py
    running egg_info
    creating pip-egg-info/web.py.egg-info

Pour ne pas installer de package, utilisez l'une des solutions suivantes:

root@node7:~# pip install --no-deps --no-install flask -v                                                                                                      
Downloading/unpacking flask
  Using version 0.10.1 (newest of versions: 0.10.1, 0.10, 0.9, 0.8.1, 0.8, 0.7.2, 0.7.1, 0.7, 0.6.1, 0.6, 0.5.2, 0.5.1, 0.5, 0.4, 0.3.1, 0.3, 0.2, 0.1)
  Downloading Flask-0.10.1.tar.gz (544Kb): 544Kb downloaded

ou

root@node7:~# cd $(mktemp -d)
root@node7:/tmp/tmp.c6H99cWD0g# pip install flask -d . -v
Downloading/unpacking flask
  Using version 0.10.1 (newest of versions: 0.10.1, 0.10, 0.9, 0.8.1, 0.8, 0.7.2, 0.7.1, 0.7, 0.6.1, 0.6, 0.5.2, 0.5.1, 0.5, 0.4, 0.3.1, 0.3, 0.2, 0.1)
  Downloading Flask-0.10.1.tar.gz (544Kb): 4.1Kb downloaded

Testé avec pip 1.0

root@node7:~# pip --version
pip 1.0 from /usr/lib/python2.7/dist-packages (python 2.7)
HVNSweeting
la source
9
pip 1.5.4donne DEPRECATION: --no-install, --no-download, --build, and --no-clean are deprecated. See https://github.com/pypa/pip/issues/906.et n'affiche pas les versions disponibles pour les packages déjà installés.
int_ua
2
pour afficher toutes les versions, il en a juste besoin -v. Le reste de ma réponse est pour éviter l'effet d'ajout (installation / téléchargement). Pour le paquet installé, ajoutez simplement --upgrade. Anw, vous pouvez créer un virtualenv séparé pour tout simplifier.
HVNSweeting
2
pip 9.0.1 aboie:no such option: --no-install
fat_of_nitpickers
"la plus récente des versions:" de -v exclut certaines versions.
mmacvicar
56

Vous n'avez pas besoin d'un package tiers pour obtenir ces informations. pypi fournit des flux JSON simples pour tous les packages sous

https://pypi.python.org/pypi/{PKG_NAME}/json

Voici du code Python utilisant uniquement la bibliothèque standard qui obtient toutes les versions.

import json
import urllib2
from distutils.version import StrictVersion

def versions(package_name):
    url = "https://pypi.python.org/pypi/%s/json" % (package_name,)
    data = json.load(urllib2.urlopen(urllib2.Request(url)))
    versions = data["releases"].keys()
    versions.sort(key=StrictVersion)
    return versions

print "\n".join(versions("scikit-image"))

Ce code s'imprime (au 23 février 2015):

0.7.2
0.8.0
0.8.1
0.8.2
0.9.0
0.9.1
0.9.2
0.9.3
0.10.0
0.10.1
eric chiang
la source
2
Le JSON a une bonne quantité d'imbrication. J'avais l'habitude versions = [x for x in data["releases"] if any([y["python_version"] in ['cp26', '2.6'] for y in data["releases"][x]])]de trouver des versions compatibles avec Python 2.6. (Je n'ai vu cp26nulle part, mais certains packages l'avaient cp27donc je suppose que cela pourrait exister dans d'autres packages.)
tripleee
2
Voici un moyen de le faire avec curl, jq et sort (un "one-liner"!): curl -s https://pypi.python.org/pypi/{PKG_NAME}/json | jq -r '.releases | keys[]' | sort -t. -k 1,1n -k 2,2n -k 3,3n
Alan Ivey
1
Cela lève une ValueErrorexception pour certains packages qui suivent des schémas de version pas si stricts. Pour le corriger pour ces packages, consultez cet essentiel .
TrinitronX
obsolète le fera pour vous.
shadi
18

Je suis venu avec un script bash mort-simple. Merci à l' auteur de jq .

#!/bin/bash
set -e

PACKAGE_JSON_URL="https://pypi.org/pypi/${1}/json"

curl -s "$PACKAGE_JSON_URL" | jq  -r '.releases | keys | .[]' | sort -V

Mise à jour: ajoutez le tri par numéro de version.

Timofey Stolbov
la source
Je n'ai pas pu me rendre curlau travail, peut-être à cause d'erreurs de certificat. wget --no-check-certificatefonctionne, mais ne curl -k --insecureproduit même rien. L'avertissement que je reçois wgetditERROR: certificate common name `www.python.org´ doesn´t match requested host name `pypi.python.org´.
tripleee
Le sort -Vne fonctionne pas sur OSX avec la version homebrew dejq
deepelement
16

Vous pouvez utiliser le package yolk3k au lieu de yolk. yolk3k est une fourchette du jaune d'origine et prend en charge à la fois python2 et 3.

https://github.com/myint/yolk

pip install yolk3k
ykyuen
la source
C'était pratique à savoir, car le jaune ne fonctionne pas sous python 3.x
Broken Man
1
yolk3k ne renvoie que la version installée pour moi:yolk -V attest Attest 0.5.3
Antony Hatchkins
2
yolk3k semble ne renvoyer que la dernière version?
mvherweg
16

Après avoir regardé le code de pip pendant un moment, il semble que le code responsable de la localisation des packages se trouve dans la PackageFinderclasse de pip.index. Sa méthode find_requirementrecherche les versions de a InstallRequirement, mais ne renvoie malheureusement que la version la plus récente.

Le code ci-dessous est presque une copie 1: 1 de la fonction d'origine, avec le retour à la ligne 114 modifié pour renvoyer toutes les versions.

Le script attend un nom de package comme premier et seul argument et renvoie toutes les versions.

http://pastebin.com/axzdUQhZ

Je ne peux pas garantir l'exactitude, car je ne connais pas le code de pip.Mais j'espère que cela aide.

Exemple de sortie

python test.py pip
Versions of pip
0.8.2
0.8.1
0.8
0.7.2
0.7.1
0.7
0.6.3
0.6.2
0.6.1
0.6
0.5.1
0.5
0.4
0.3.1
0.3
0.2.1
0.2 dev

Le code:

import posixpath
import pkg_resources
import sys
from pip.download import url_to_path
from pip.exceptions import DistributionNotFound
from pip.index import PackageFinder, Link
from pip.log import logger
from pip.req import InstallRequirement
from pip.util import Inf


class MyPackageFinder(PackageFinder):

    def find_requirement(self, req, upgrade):
        url_name = req.url_name
        # Only check main index if index URL is given:
        main_index_url = None
        if self.index_urls:
            # Check that we have the url_name correctly spelled:
            main_index_url = Link(posixpath.join(self.index_urls[0], url_name))
            # This will also cache the page, so it's okay that we get it again later:
            page = self._get_page(main_index_url, req)
            if page is None:
                url_name = self._find_url_name(Link(self.index_urls[0]), url_name, req) or req.url_name

        # Combine index URLs with mirror URLs here to allow
        # adding more index URLs from requirements files
        all_index_urls = self.index_urls + self.mirror_urls

        def mkurl_pypi_url(url):
            loc = posixpath.join(url, url_name)
            # For maximum compatibility with easy_install, ensure the path
            # ends in a trailing slash.  Although this isn't in the spec
            # (and PyPI can handle it without the slash) some other index
            # implementations might break if they relied on easy_install's behavior.
            if not loc.endswith('/'):
                loc = loc + '/'
            return loc
        if url_name is not None:
            locations = [
                mkurl_pypi_url(url)
                for url in all_index_urls] + self.find_links
        else:
            locations = list(self.find_links)
        locations.extend(self.dependency_links)
        for version in req.absolute_versions:
            if url_name is not None and main_index_url is not None:
                locations = [
                    posixpath.join(main_index_url.url, version)] + locations

        file_locations, url_locations = self._sort_locations(locations)

        locations = [Link(url) for url in url_locations]
        logger.debug('URLs to search for versions for %s:' % req)
        for location in locations:
            logger.debug('* %s' % location)
        found_versions = []
        found_versions.extend(
            self._package_versions(
                [Link(url, '-f') for url in self.find_links], req.name.lower()))
        page_versions = []
        for page in self._get_pages(locations, req):
            logger.debug('Analyzing links from page %s' % page.url)
            logger.indent += 2
            try:
                page_versions.extend(self._package_versions(page.links, req.name.lower()))
            finally:
                logger.indent -= 2
        dependency_versions = list(self._package_versions(
            [Link(url) for url in self.dependency_links], req.name.lower()))
        if dependency_versions:
            logger.info('dependency_links found: %s' % ', '.join([link.url for parsed, link, version in dependency_versions]))
        file_versions = list(self._package_versions(
                [Link(url) for url in file_locations], req.name.lower()))
        if not found_versions and not page_versions and not dependency_versions and not file_versions:
            logger.fatal('Could not find any downloads that satisfy the requirement %s' % req)
            raise DistributionNotFound('No distributions at all found for %s' % req)
        if req.satisfied_by is not None:
            found_versions.append((req.satisfied_by.parsed_version, Inf, req.satisfied_by.version))
        if file_versions:
            file_versions.sort(reverse=True)
            logger.info('Local files found: %s' % ', '.join([url_to_path(link.url) for parsed, link, version in file_versions]))
            found_versions = file_versions + found_versions
        all_versions = found_versions + page_versions + dependency_versions
        applicable_versions = []
        for (parsed_version, link, version) in all_versions:
            if version not in req.req:
                logger.info("Ignoring link %s, version %s doesn't match %s"
                            % (link, version, ','.join([''.join(s) for s in req.req.specs])))
                continue
            applicable_versions.append((link, version))
        applicable_versions = sorted(applicable_versions, key=lambda v: pkg_resources.parse_version(v[1]), reverse=True)
        existing_applicable = bool([link for link, version in applicable_versions if link is Inf])
        if not upgrade and existing_applicable:
            if applicable_versions[0][1] is Inf:
                logger.info('Existing installed version (%s) is most up-to-date and satisfies requirement'
                            % req.satisfied_by.version)
            else:
                logger.info('Existing installed version (%s) satisfies requirement (most up-to-date version is %s)'
                            % (req.satisfied_by.version, applicable_versions[0][1]))
            return None
        if not applicable_versions:
            logger.fatal('Could not find a version that satisfies the requirement %s (from versions: %s)'
                         % (req, ', '.join([version for parsed_version, link, version in found_versions])))
            raise DistributionNotFound('No distributions matching the version for %s' % req)
        if applicable_versions[0][0] is Inf:
            # We have an existing version, and its the best version
            logger.info('Installed version (%s) is most up-to-date (past versions: %s)'
                        % (req.satisfied_by.version, ', '.join([version for link, version in applicable_versions[1:]]) or 'none'))
            return None
        if len(applicable_versions) > 1:
            logger.info('Using version %s (newest of versions: %s)' %
                        (applicable_versions[0][1], ', '.join([version for link, version in applicable_versions])))
        return applicable_versions


if __name__ == '__main__':
    req = InstallRequirement.from_line(sys.argv[1], None)
    finder = MyPackageFinder([], ['http://pypi.python.org/simple/'])
    versions = finder.find_requirement(req, False)
    print 'Versions of %s' % sys.argv[1]
    for v in versions:
        print v[1]
Reiner Gerecke
la source
Cela a fonctionné beaucoup mieux que la réponse ci-dessus. skinny $ yolk -V scipy scipy 0.12.0 skinny $ python test.py scipy Versions de scipy 0.12.0 0.12.0 0.11.0 0.11.0 0.10.1 0.10.1 0.10.0 0.10.0 0.9.0 0.9.0 0.8.0
oligofren
1
Cette utilisation est explicitement déconseillée dans les documents : " vous ne devez pas utiliser les API internes de pip de cette manière "
wim
9

Vous pouvez utiliser ce petit script Python 3 (en utilisant uniquement des modules de bibliothèque standard) pour récupérer la liste des versions disponibles pour un package de PyPI à l'aide de l' API JSON et les imprimer dans l'ordre chronologique inverse. Contrairement à certaines autres solutions Python publiées ici, cela ne casse pas sur les versions lâches comme django' 2.2rc1ou uwsgi' 2.0.17.1:

#!/usr/bin/env python3

import json
import sys
from urllib import request    
from pkg_resources import parse_version    

def versions(pkg_name):
    url = f'https://pypi.python.org/pypi/{pkg_name}/json'
    releases = json.loads(request.urlopen(url).read())['releases']
    return sorted(releases, key=parse_version, reverse=True)    

if __name__ == '__main__':
    print(*versions(sys.argv[1]), sep='\n')

Enregistrez le script et exécutez-le avec le nom du package comme argument, par exemple:

python versions.py django
3.0a1
2.2.5
2.2.4
2.2.3
2.2.2
2.2.1
2.2
2.2rc1
...
Eugene Yarmash
la source
7

Cela fonctionne pour moi sur OSX:

pip install docker-compose== 2>&1 \
| grep -oE '(\(.*\))' \
| awk -F:\  '{print$NF}' \
| sed -E 's/( |\))//g' \
| tr ',' '\n'

Il renvoie la liste une par ligne:

1.1.0rc1
1.1.0rc2
1.1.0
1.2.0rc1
1.2.0rc2
1.2.0rc3
1.2.0rc4
1.2.0
1.3.0rc1
1.3.0rc2
1.3.0rc3
1.3.0
1.3.1
1.3.2
1.3.3
1.4.0rc1
1.4.0rc2
1.4.0rc3
1.4.0
1.4.1
1.4.2
1.5.0rc1
1.5.0rc2
1.5.0rc3
1.5.0
1.5.1
1.5.2
1.6.0rc1
1.6.0
1.6.1
1.6.2
1.7.0rc1
1.7.0rc2
1.7.0
1.7.1
1.8.0rc1
1.8.0rc2
1.8.0
1.8.1
1.9.0rc1
1.9.0rc2
1.9.0rc3
1.9.0rc4
1.9.0
1.10.0rc1
1.10.0rc2
1.10.0

Ou pour obtenir la dernière version disponible:

pip install docker-compose== 2>&1 \
| grep -oE '(\(.*\))' \
| awk -F:\  '{print$NF}' \
| sed -E 's/( |\))//g' \
| tr ',' '\n' \
| gsort -r -V \
| head -1
1.10.0rc2

Gardez à l'esprit gsortqu'il faut installer (sur OSX) pour analyser les versions. Vous pouvez l'installer avecbrew install coreutils

grand-mère
la source
Jeez, pourquoi avez-vous même posté cette réponse. La réponse de @Chris Montaro fonctionne et est élégante. Cela introduit juste inutilement des complications
Brian Leach
@BrianLeach smh ... c'est la même approche filtrée pour une utilisation dans un script ...
grand
1
Fonctionne dans cygwin / bash pour moi, pour la deuxième solution, utilisez sort, pas gsort dans cygwin.
WebComer
Ici, python donne sans doute un code plus lisible que bash ... voir la réponse de @eric chiang (espérons-le :) ci-dessus ...
mirekphd
4

Mon projet luddite a cette fonctionnalité.

Exemple d'utilisation:

>>> import luddite
>>> luddite.get_versions_pypi("python-dateutil")
('0.1', '0.3', '0.4', '0.5', '1.0', '1.1', '1.2', '1.4', '1.4.1', '1.5', '2.0', '2.1', '2.2', '2.3', '2.4.0', '2.4.1', '2.4.2', '2.5.0', '2.5.1', '2.5.2', '2.5.3', '2.6.0', '2.6.1', '2.7.0', '2.7.1', '2.7.2', '2.7.3', '2.7.4', '2.7.5', '2.8.0')

Il répertorie toutes les versions d'un package disponibles, en interrogeant l'API json de https://pypi.org/

wim
la source
Il serait plus instructif de nous dire ce que fait votre package, sinon vous ne faites que promouvoir votre logiciel :)
user228395
@ user228395 Je pensais que c'était assez évident, mais il répertorie toutes les versions d'un package disponible, ce qui était exactement le sujet de la question. Modifié - mieux?
wim
Son fonctionnement bien sûr. Il s'agit donc essentiellement d'envelopper la solution présentée par @Timofey Stolbov?
user228395
1
@ user228395 Je ne l'appellerais pas "wrapping", car cette réponse utilise bash, curl et jq - alors que luddite utilise uniquement la bibliothèque standard Python (urllib). Mais la solution de Stolbov utilise le même point de terminaison sur pypi.org . Puis-je demander quelle est la raison de votre downvote?
wim
1
Si vous avez suivi le lien vers la page de détails du projet, vous pouvez voir que la principale fonctionnalité du projet consiste à vérifier les requirements.txtfichiers pour les packages obsolètes. C'est plus que quelques lignes de code. Afin de vérifier un requirements.txtfichier, vous avez besoin de la fonctionnalité pour répertorier toutes les versions de package. Cette partie est intentionnellement découplée et fait partie de l'API publique de luddite. Et c'est la source Apache License 2.0, je pense qu'il n'est pas vraiment juste d'appeler cela un progiciel "boîte noire".
wim
2

Je n'ai pas eu de chance avec yolk, yolk3kou , pip install -vmais si je me suis retrouvé à l' aide de ce (adapté à Python 3 de la réponse de eric chiang):

import json
import requests
from distutils.version import StrictVersion

def versions(package_name):
    url = "https://pypi.python.org/pypi/{}/json".format(package_name)
    data = requests.get(url).json()
    return sorted(list(data["releases"].keys()), key=StrictVersion, reverse=True)

>>> print("\n".join(versions("gunicorn")))
19.1.1
19.1.0
19.0.0
18.0
17.5
0.17.4
0.17.3
...
Andrew Magee
la source
1
StrictVersionne fonctionnera pas pour de nombreux paquets ( django, uwsgi, psycopg2pour ne citer que quelques - uns). Vous pouvez utiliser à parse_version()partir de setuptools(voir ma réponse pour un exemple).
Eugene Yarmash
1

La solution alternative consiste à utiliser les API d'entrepôt:

https://warehouse.readthedocs.io/api-reference/json/#release

Par exemple pour Flask:

import requests
r = requests.get("https://pypi.org/pypi/Flask/json")
print(r.json()['releases'].keys())

imprimera:

dict_keys(['0.1', '0.10', '0.10.1', '0.11', '0.11.1', '0.12', '0.12.1', '0.12.2', '0.12.3', '0.12.4', '0.2', '0.3', '0.3.1', '0.4', '0.5', '0.5.1', '0.5.2', '0.6', '0.6.1', '0.7', '0.7.1', '0.7.2', '0.8', '0.8.1', '0.9', '1.0', '1.0.1', '1.0.2'])
Charlie
la source
0

Facile bashScript qui ne repose que sur pythonlui-même (je suppose que dans le contexte de la question il doit être installé) et l'un curlou wget. Il suppose que vous avez setuptoolsinstallé un package pour trier les versions (presque toujours installé). Il ne repose pas sur des dépendances externes telles que:

  • jq qui peut ne pas être présent;
  • grep et awk qui peuvent se comporter différemment sous Linux et macOS.
curl --silent --location https://pypi.org/pypi/requests/json | python -c "import sys, json, pkg_resources; releases = json.load(sys.stdin)['releases']; print(' '.join(sorted(releases, key=pkg_resources.parse_version)))"

Version un peu plus longue avec commentaires.

Mettez le nom du package dans une variable:

PACKAGE=requests

Obtenir des versions (en utilisant curl ):

VERSIONS=$(curl --silent --location https://pypi.org/pypi/$PACKAGE/json | python -c "import sys, json, pkg_resources; releases = json.load(sys.stdin)['releases']; print(' '.join(sorted(releases, key=pkg_resources.parse_version)))")

Obtenir des versions (en utilisant wget ):

VERSIONS=$(wget -qO- https://pypi.org/pypi/$PACKAGE/json | python -c "import sys, json, pkg_resources; releases = json.load(sys.stdin)['releases']; print(' '.join(sorted(releases, key=pkg_resources.parse_version)))")

Imprimer les versions triées:

echo $VERSIONS
Andrey Semakin
la source
-1

Ma prise est une combinaison de quelques réponses publiées, avec quelques modifications pour les rendre plus faciles à utiliser dans un environnement python en cours d'exécution.

L'idée est de fournir une toute nouvelle commande (modélisée d'après la commande d'installation) qui vous donne une instance de l'outil de recherche de package à utiliser. L'avantage est qu'il fonctionne avec et utilise tous les index que pip prend en charge et lit vos fichiers de configuration de pip locaux, de sorte que vous obtenez les résultats corrects comme vous le feriez avec une installation de pip normale.

J'ai essayé de le rendre compatible avec pip v 9.x et 10.x .. mais je ne l'ai essayé que sur 9.x

https://gist.github.com/kaos/68511bd013fcdebe766c981f50b473d4

#!/usr/bin/env python
# When you want a easy way to get at all (or the latest) version of a certain python package from a PyPi index.

import sys
import logging

try:
    from pip._internal import cmdoptions, main
    from pip._internal.commands import commands_dict
    from pip._internal.basecommand import RequirementCommand
except ImportError:
    from pip import cmdoptions, main
    from pip.commands import commands_dict
    from pip.basecommand import RequirementCommand

from pip._vendor.packaging.version import parse as parse_version

logger = logging.getLogger('pip')

class ListPkgVersionsCommand(RequirementCommand):
    """
    List all available versions for a given package from:

    - PyPI (and other indexes) using requirement specifiers.
    - VCS project urls.
    - Local project directories.
    - Local or remote source archives.

    """
    name = "list-pkg-versions"
    usage = """
      %prog [options] <requirement specifier> [package-index-options] ...
      %prog [options] [-e] <vcs project url> ...
      %prog [options] [-e] <local project path> ...
      %prog [options] <archive url/path> ..."""

    summary = 'List package versions.'

    def __init__(self, *args, **kw):
        super(ListPkgVersionsCommand, self).__init__(*args, **kw)

        cmd_opts = self.cmd_opts

        cmd_opts.add_option(cmdoptions.install_options())
        cmd_opts.add_option(cmdoptions.global_options())
        cmd_opts.add_option(cmdoptions.use_wheel())
        cmd_opts.add_option(cmdoptions.no_use_wheel())
        cmd_opts.add_option(cmdoptions.no_binary())
        cmd_opts.add_option(cmdoptions.only_binary())
        cmd_opts.add_option(cmdoptions.pre())
        cmd_opts.add_option(cmdoptions.require_hashes())

        index_opts = cmdoptions.make_option_group(
            cmdoptions.index_group,
            self.parser,
        )

        self.parser.insert_option_group(0, index_opts)
        self.parser.insert_option_group(0, cmd_opts)

    def run(self, options, args):
        cmdoptions.resolve_wheel_no_use_binary(options)
        cmdoptions.check_install_build_global(options)

        with self._build_session(options) as session:
            finder = self._build_package_finder(options, session)

            # do what you please with the finder object here... ;)
            for pkg in args:
                logger.info(
                    '%s: %s', pkg,
                    ', '.join(
                        sorted(
                            set(str(c.version) for c in finder.find_all_candidates(pkg)),
                            key=parse_version,
                        )
                    )
                )


commands_dict[ListPkgVersionsCommand.name] = ListPkgVersionsCommand

if __name__ == '__main__':
    sys.exit(main())

Exemple de sortie

./list-pkg-versions.py list-pkg-versions pika django
pika: 0.5, 0.5.1, 0.5.2, 0.9.1a0, 0.9.2a0, 0.9.3, 0.9.4, 0.9.5, 0.9.6, 0.9.7, 0.9.8, 0.9.9, 0.9.10, 0.9.11, 0.9.12, 0.9.13, 0.9.14, 0.10.0b1, 0.10.0b2, 0.10.0, 0.11.0b1, 0.11.0, 0.11.1, 0.11.2, 0.12.0b2
django: 1.1.3, 1.1.4, 1.2, 1.2.1, 1.2.2, 1.2.3, 1.2.4, 1.2.5, 1.2.6, 1.2.7, 1.3, 1.3.1, 1.3.2, 1.3.3, 1.3.4, 1.3.5, 1.3.6, 1.3.7, 1.4, 1.4.1, 1.4.2, 1.4.3, 1.4.4, 1.4.5, 1.4.6, 1.4.7, 1.4.8, 1.4.9, 1.4.10, 1.4.11, 1.4.12, 1.4.13, 1.4.14, 1.4.15, 1.4.16, 1.4.17, 1.4.18, 1.4.19, 1.4.20, 1.4.21, 1.4.22, 1.5, 1.5.1, 1.5.2, 1.5.3, 1.5.4, 1.5.5, 1.5.6, 1.5.7, 1.5.8, 1.5.9, 1.5.10, 1.5.11, 1.5.12, 1.6, 1.6.1, 1.6.2, 1.6.3, 1.6.4, 1.6.5, 1.6.6, 1.6.7, 1.6.8, 1.6.9, 1.6.10, 1.6.11, 1.7, 1.7.1, 1.7.2, 1.7.3, 1.7.4, 1.7.5, 1.7.6, 1.7.7, 1.7.8, 1.7.9, 1.7.10, 1.7.11, 1.8a1, 1.8b1, 1.8b2, 1.8rc1, 1.8, 1.8.1, 1.8.2, 1.8.3, 1.8.4, 1.8.5, 1.8.6, 1.8.7, 1.8.8, 1.8.9, 1.8.10, 1.8.11, 1.8.12, 1.8.13, 1.8.14, 1.8.15, 1.8.16, 1.8.17, 1.8.18, 1.8.19, 1.9a1, 1.9b1, 1.9rc1, 1.9rc2, 1.9, 1.9.1, 1.9.2, 1.9.3, 1.9.4, 1.9.5, 1.9.6, 1.9.7, 1.9.8, 1.9.9, 1.9.10, 1.9.11, 1.9.12, 1.9.13, 1.10a1, 1.10b1, 1.10rc1, 1.10, 1.10.1, 1.10.2, 1.10.3, 1.10.4, 1.10.5, 1.10.6, 1.10.7, 1.10.8, 1.11a1, 1.11b1, 1.11rc1, 1.11, 1.11.1, 1.11.2, 1.11.3, 1.11.4, 1.11.5, 1.11.6, 1.11.7, 1.11.8, 1.11.9, 1.11.10, 1.11.11, 1.11.12, 2.0, 2.0.1, 2.0.2, 2.0.3, 2.0.4
Kaos
la source
cette utilisation est explicitement déconseillée dans les documents : " vous ne devez pas utiliser les API internes de pip de cette manière "
wim