Python e pip, listam todas as versões de um pacote que está disponível?

445

Dado o nome de um pacote Python que pode ser instalado com o pip , existe alguma maneira de descobrir uma lista de todas as versões possíveis dele que o pip poderia instalar? No momento, é tentativa e erro.

Estou tentando instalar uma versão para uma biblioteca de terceiros, mas a versão mais recente é muito nova, foram feitas alterações incompatíveis com versões anteriores. Então, de alguma forma, gostaria de ter uma lista de todas as versões que o pip conhece, para que eu possa testá-las.

Rory
fonte
1
A resposta aceita não é equivalente à outra com o script, pois eles não geram a mesma saída.
Oligofren #
17
Atualize a resposta selecionada. A gema está quebrada e desnecessária. A resposta pip install pylibmc==é perfeita.
Jonathan
Atualize a resposta aceita como sugere @ Jonathan. Eu não diria que é perfeito porque não funcionará em versões anteriores do pip (v7 ou v8), mas é ótimo caso contrário.
Antony Hatchkins
1
@Rory, atualize a resposta aceita, a gema está morta. A resposta de Chris Montanaro é o melhor método atualmente IMO.
Ryan Fisher
1
@Rory Altere a resposta aceita para o benefício de futuros visitantes desta pergunta popular. O projeto Yolk não é mais mantido e simplesmente não funciona conforme a resposta.
wim

Respostas:

167

(atualização: em março de 2020, muitas pessoas relataram que a gema, instalada via pip install yolk3k, retorna apenas a versão mais recente. A resposta de Chris parece ter o maior número de votos positivos e funcionou para mim)

O script em pastebin funciona. No entanto, não é muito conveniente se você estiver trabalhando com vários ambientes / hosts, pois será necessário copiar / criar todas as vezes.

Uma solução geral melhor seria usar o yolk3k , que está disponível para instalação com o pip. Por exemplo, para ver quais versões do Django estão disponíveis:

$ 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

yolk3ké uma bifurcação do original yolkque interrompeu o desenvolvimento em 2012 . Embora yolknão seja mais mantido (como indicado nos comentários abaixo), yolk3kparece ser compatível com o Python 3.

Nota: Não estou envolvido no desenvolvimento do yolk3k. Se algo parece não funcionar como deveria, deixar um comentário aqui não deve fazer muita diferença. Use o rastreador de problemas do yolk3k e considere enviar uma correção, se possível.

m000
fonte
4
A resposta abaixo (usando o script de pastebin) é mais complicada, mas pelo menos funciona no meu caso (procurando por versões do scipy). gema mostra apenas a última versão disponível, o outro script mostra todas as versões que remontam a 0.8.0.
Oligofren #
30
Na maioria das vezes ele só irá retornar versão mais recente
PawelRoman
17
Fir python3 basta usar pip install yolk3k. O comando yolk estará disponível.
Pierre Criulanscy
8
Como a gema, na maioria das vezes, a yolk3k retorna apenas a versão mais recente.
Diabloneo 26/05/2015
4
gema quebrada / não é mais mantida. exclua esta resposta.
wim
834

Para pip> = 9.0 use

$ 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==

- todas as versões disponíveis serão impressas sem realmente baixar ou instalar nenhum pacote adicional.

Para pip <9.0 use

pip install pylibmc==blork

onde blorkpode haver qualquer sequência que não seja um número de versão válido .

Chris Montanaro
fonte
25
Acho estranho que espetos de erro do PIP se esgotar todas as versões, mas eles não têm argumento para explicitamente chegar a tais dados
Chris Montanaro
2
Outra propriedade interessante desta solução é que ela funciona com todos os sinalizadores normais para limitar as fontes de instalação. Por exemplopip install --only-binary :all: pylibmc , listará todas as versões do pylibmc disponíveis como pacotes binários.
Pavon
3
pip install pylibmc==9999999 | tr ', ' "\n" | sort -n
Vikas
18
Isso deve ser marcado como a resposta correta, pois não requer a instalação de nenhum outro pacote.
Yves Dorfsman
5
É um pouco ridículo que essa seja a única maneira de fazer isso no pip. Espero que haja pelo menos um problema em aberto sobre isso no rastreador de bugs?
pmos
69

Atualização: a
partir de setembro de 2017, esse método não funciona mais: --no-installfoi removido no pip 7

Use pip install -v, você pode ver todas as versões disponíveis

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

Para não instalar nenhum pacote, use uma das seguintes soluções:

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

Testado com pip 1.0

root@node7:~# pip --version
pip 1.0 from /usr/lib/python2.7/dist-packages (python 2.7)
HVNSweeting
fonte
9
pip 1.5.4fornece DEPRECATION: --no-install, --no-download, --build, and --no-clean are deprecated. See https://github.com/pypa/pip/issues/906.e não mostra as versões disponíveis para pacotes que já estão instalados.
int_ua 24/03/2015
2
para mostrar todas as versões, só precisa -v. O restante da minha resposta é para evitar efeitos adicionais (instalação / download). Para o pkg instalado, basta adicionar --upgrade. De qualquer forma, você pode criar um virtualenv separado para simplificar tudo.
HVNSweeting
2
pip 9.0.1 barks:no such option: --no-install
tired_of_nitpickers
"mais recente das versões:" de -v exclui algumas versões.
mmacvicar
55

Você não precisa de um pacote de terceiros para obter essas informações. O pypi fornece feeds JSON simples para todos os pacotes sob

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

Aqui está um código Python usando apenas a biblioteca padrão que obtém todas as versões.

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"))

Esse código é impresso (em 23 de fevereiro de 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
fonte
2
O JSON tem uma quantidade razoável de aninhamento. Eu costumava versions = [x for x in data["releases"] if any([y["python_version"] in ['cp26', '2.6'] for y in data["releases"][x]])]encontrar versões compatíveis com o Python 2.6. (Eu não vi em cp26lugar algum, mas alguns pacotes o fizeram cp27, especulo que isso possa existir em outros pacotes.) #
Tripleee
2
Aqui está uma maneira de fazer isso com curl, jq e sort (um "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
Isso gera uma ValueErrorexceção para alguns pacotes que seguem esquemas de versão não tão rigorosos. Para corrigi-lo para esses pacotes, consulte esta lista .
TrinitronX
desatualizado fará isso por você.
shadi
18

Eu vim com um script simples e simples. Graças ao autor 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

Atualização: adicione a classificação pelo número da versão.

Timofey Stolbov
fonte
Não consegui curltrabalhar, possivelmente por causa de erros de certificado. wget --no-check-certificatefunciona, mas até curl -k --insecurenão produz nada. O aviso que recebo wgetdizERROR: certificate common name `www.python.org´ doesn´t match requested host name `pypi.python.org´.
tripleee 18/03/16
A sort -Vnão funciona em OSX com a versão de homebrew dejq
deepelement
16

Você pode usar o pacote yolk3k em vez de yolk. yolk3k é uma bifurcação da gema original e suporta python2 e 3.

https://github.com/myint/yolk

pip install yolk3k
ykyuen
fonte
Este foi útil para saber, já que a gema não funciona sob 3.x python
quebrado Man
1
yolk3k retorna apenas a versão instalada para mim:yolk -V attest Attest 0.5.3
Antony Hatchkins
2
yolk3k parece retornar apenas a versão mais recente?
Mvherweg # 6/18
16

Depois de olhar para o código do pip por um tempo, parece que o código responsável por localizar pacotes podem ser encontrados na PackageFinderclasse pip.index. Seu método find_requirementprocura as versões de umInstallRequirement , mas infelizmente retorna apenas a versão mais recente.

O código abaixo é quase uma cópia 1: 1 da função original, com o retorno na linha 114 alterado para retornar todas as versões.

O script espera um nome de pacote como primeiro e único argumento e retorna todas as versões.

http://pastebin.com/axzdUQhZ

Não posso garantir a correção, pois não estou familiarizado com o código do pip.Mas espero que isso ajude.

Saída de amostra

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

O código:

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
fonte
Isso funcionou muito melhor do que a resposta acima. skiny $ yolk -V scipy scipy 0.12.0 skinny $ python test.py scipy Versões 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 12/04
1
Esse uso é explicitamente desencorajado nos documentos : " você não deve usar as APIs internas do pip dessa maneira "
wim
9

Você pode usar esse pequeno script Python 3 (usando apenas módulos de biblioteca padrão) para pegar a lista de versões disponíveis para um pacote do PyPI usando a API JSON e imprimi-las em ordem cronológica inversa. Ao contrário de outras soluções Python postadas aqui, isso não ocorre em versões soltas como django's 2.2rc1ou uwsgi' s 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')

Salve o script e execute-o com o nome do pacote como argumento, por exemplo:

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
fonte
7

Isso funciona para mim no OSX:

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

Retorna a lista uma por linha:

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, para obter a versão mais recente disponível:

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

Lembre-se de gsortque deve ser instalado (no OSX) para analisar as versões. Você pode instalá-lo combrew install coreutils

Avó
fonte
Eita, por que você postou esta resposta? A resposta de @Chris Montaro funciona e é elegante. Isto introduz apenas desnecessariamente complicação
Brian Leach
@BrianLeach SMH ... é a mesma abordagem filtrada para uso em um script ...
avó
1
Funciona em cygwin / bash para mim, para a segunda solução use sort, não gsort no cygwin.
WebComer 26/09/18
Aqui python rendimentos indiscutivelmente um código mais legível do que festa ... ver @eric resposta de chiang (espero :) acima ...
mirekphd
4

Meu projeto luddite tem esse recurso.

Exemplo de uso:

>>> 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')

Ele lista todas as versões de um pacote disponível, consultando a API json de https://pypi.org/

wim
fonte
Seria mais instrutivo se você nos o seu pacote está fazendo dizer, caso contrário, você está apenas promover o seu software :)
user228395
@ user228395 Eu pensei que era óbvio o suficiente, mas listava todas as versões de um pacote disponível, que era exatamente o que o título da pergunta pergunta. Editado - melhor?
Wim
Seu funcionamento, é claro. Então, ele está basicamente envolvendo a solução apresentada por @Timofey Stolbov?
user228395
1
@ user228395 Eu não chamaria isso de "quebra automática", já que essa resposta usa bash, curl e jq - enquanto o luddite usa apenas a biblioteca padrão do Python (urllib). Mas a solução de Stolbov usa o mesmo ponto final no pypi.org . Posso perguntar qual é o motivo do seu voto negativo?
Wim
1
Se você seguiu o link para a página de detalhes do projeto, poderá ver que o principal recurso do projeto é verificar requirements.txtarquivos em busca de pacotes desatualizados. É mais do que algumas linhas de código. Para verificar um requirements.txtarquivo, você precisa da funcionalidade para listar todas as versões do pacote. Esta parte é dissociada intencionalmente e faz parte da API pública do luddite. E é fonte Apache License 2.0, acho que não é justo chamar isso de pacote de software "caixa preta".
Wim
2

Eu não tive qualquer sorte com yolk, yolk3kou pip install -vmas então acabei usando isso (adaptado para Python 3 de resposta 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
fonte
1
StrictVersionnão vai funcionar para muitos pacotes ( django, uwsgi, psycopg2para citar alguns). Você pode usar a parse_version()partir de setuptools(veja minha resposta para um exemplo).
21916 Eugene Yarmash
1

A solução alternativa é usar as APIs do Warehouse:

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

Por exemplo, para o Flask:

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

irá imprimir:

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
fonte
0

bashScript simples que depende apenas de pythonsi mesmo (suponho que, no contexto da pergunta, ele deva ser instalado) e um dos curlou wget. Ele pressupõe que você tenha o setuptoolspacote instalado para classificar versões (quase sempre instalado). Não depende de dependências externas, como:

  • jq que pode não estar presente;
  • grepe awkisso pode se comportar de maneira diferente no Linux e no 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)))"

Versão um pouco mais longa com comentários.

Coloque o nome do pacote em uma variável:

PACKAGE=requests

Obter versões (usando 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)))")

Obter versões (usando 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)))")

Imprimir versões ordenadas:

echo $VERSIONS
Andrey Semakin
fonte
-1

Minha opinião é uma combinação de algumas respostas postadas, com algumas modificações para torná-las mais fáceis de usar em um ambiente python em execução.

A idéia é fornecer um comando totalmente novo (modelado após o comando de instalação) que fornece uma instância do localizador de pacotes a ser usado. A vantagem é que ele trabalha com, e usa, quaisquer índices que o pip suporte e leia seus arquivos de configuração do pip local, para que você obtenha os resultados corretos como faria com uma instalação normal do pip.

Eu tentei torná-lo compatível com o pip v 9.xe 10.x .. mas tentei apenas no 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())

Saída de exemplo

./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
fonte
esse uso é explicitamente desencorajado nos documentos : " você não deve usar as APIs internas do pip dessa maneira "
wim