web-dev-qa-db-ja.com

Pythonとpipは、利用可能なパッケージのすべてのバージョンを一覧表示しますか?

pip および virtualenv を使用してインストールできるPython(2.X)パッケージの名前を考えると、 pipがインストールできる可能性のあるすべてのバージョンのリストを見つけてください。今それは試行錯誤です。

私はサード・パーティーのライブラリー用のバージョンをインストールしようとしていますが、最新バージョンは新しすぎ、後方互換性のない変更が行われました。だから私はどういうわけか私がそれらをテストすることができるようにpipが知っているすべてのバージョンのリストを持ちたいです。

337
Rory

Pastebinのスクリプトは機能します。ただし、毎回コピー/作成する必要があるため、複数の環境/ホストで作業している場合はあまり便利ではありません。

より良い万能の解決策は、 yolk を使うことです。これはpipでインストールすることができます。例えば。 Djangoのどのバージョンが利用可能かを見るために:

$ 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

ちょっとした注意:卵黄は配布に依存します。これは悪いことではありませんが、何らかの理由で(廃止予定の)python setuptoolsを使い続ける必要がある場合には問題になるかもしれません。

注:私は卵黄の発達には関与していません。 何かがうまく動かないようであれば、ここにコメントを残しても大した違いはないはずです。代わりに 卵黄イシュートラッカー を使ってください可能であれば、修正の提出を検討してください。

153
m000

pip> = 9.0の場合

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

- 追加のパッケージを実際にダウンロードまたはインストールすることなく、利用可能なすべてのバージョンが印刷されます。

pip <9.0の場合

pip install pylibmc==blork

blorkには、インストール候補になる可能性が低い任意の文字列を指定できます。

613
Chris Montanaro

更新:
2017年9月現在、このメソッドは機能しません。--no-installはpip 7で削除されました

pip install -vを使うと、利用可能なすべてのバージョンを見ることができます

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

パッケージをインストールしないようにするには、次のいずれかの方法を使用します。

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

または

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

ピップ1.0でテスト済み

root@node7:~# pip --version
pip 1.0 from /usr/lib/python2.7/dist-packages (python 2.7)
70
HVNSweeting

この情報を入手するためにサードパーティのパッケージは必要ありません。 pypiは以下のすべてのパッケージに簡単なJSONフィードを提供します。

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

これは、すべてのバージョンを取得する標準ライブラリのみを使用したPythonコードです。

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

そのコードは(2015年2月23日現在)印刷されます。

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
47
eric chiang

あなたはyolkの代わりにyolk3kパッケージを使うことができます。 yolk3kは元の卵黄からのフォークであり、python2と3の両方をサポートします。

https://github.com/myint/yolk

pip install yolk3k
18
ykyuen

私はデッドシンプルなbashスクリプトを思い付きました。 jq の作者に感謝します。

#!/bin/bash
set -e

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

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

更新:バージョン番号によるソートを追加しました。

15
Timofey Stolbov

しばらくの間pipのコードを見た後、パッケージを見つけることに責任があるコードがpip.indexPackageFinderクラスにあるように見えます。そのメソッドfind_requirementInstallRequirementのバージョンを調べますが、残念ながら最新のバージョンしか返しません。

以下のコードは、元の関数のほぼ1:1のコピーです。114行目の戻り値は、すべてのバージョンを返すように変更されています。

このスクリプトは、最初の唯一の引数として1つのパッケージ名を想定し、すべてのバージョンを返します。

http://Pastebin.com/axzdUQhZ

私はpipのコードに慣れていないので、正当性を保証することはできません。しかし、うまくいけばこれは助けになります。

出力例

$ 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

コード:

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 __== '__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]
15
Reiner Gerecke

私はこれが一種のばかげたことであることを知っていますが、あなたはこのようなことを試すことができます:

pip install Django==x

これはエラーになりますが、このパッケージで利用可能なすべてのバージョンを一覧表示します。

注意1:Djangoを必要なパッケージに置き換えてください。

注2:私は、xと呼ばれるそのようなバージョンがないと願っています(xが実際のバージョン番号である場合は別の文字列を使用してください)。

注3:==の前後にスペースはありません。

10
ian0411

https://pypi.python.org/pypi/Django/ - メンテナがすべてのパッケージを表示することを選択しているパッケージで動作します https://pypi.python.org/simple/pip/ - とにかくトリックをする必要があります(すべてのリンクを一覧表示)

8
m0she

この小さなPython 3スクリプトを使って、 JSON API を使ってPyPIからパッケージの利用可能なバージョンのリストを取得し、それらを年代順の逆順に出力することができます。ここに掲載されている他のPythonソリューションとは異なり、これはDjango2.2rc1uwsgi2.0.17.1のようなゆるいバージョンではうまくいきません。

#!/usr/bin/env python

import sys    
import requests
from pkg_resources import parse_version    

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

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

スクリプトを保存し、パッケージ名を引数として使用して実行します。

python versions.py Django
2.2
2.2rc1
2.2b1
2.2a1
2.1.8
2.1.7
...
3
Eugene Yarmash

私はyolkyolk3kpip install -vに何の運もありませんでしたが、私はこれを使いました(eric chiangの答えからPython 3に適応させた):

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
...
2
Andrew Magee

Pip 7.1.0はインストールから--no-installオプションを削除しました。追加パッケージなしでパッケージの全バージョンを取得する方法を見つけました。

$ pip install --no-deps Django==x.x.x
Collecting Django==x.x.x.
Could not find a version that satisfies the requirement Django==x.x.x. (from versions: 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.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.8a1, 1.8b1, 1.8b2, 1.8rc1, 1.8, 1.8.1, 1.8.2)
No matching distribution found for Django==x.x.x.
2
samsong8610

これは私にとってOSX上で動作します。

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

1行に1つずつリストを返します。

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

あるいは最新版を入手するには:

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

バージョンを解析するにはgsortを(OSXに)インストールする必要があることに注意してください。 brew install coreutilsでインストールできます

2
grandma

私はこれを実行しました:

pip show packagename

例えば。:

> pip3 show setuptools
---
Metadata-Version: 2.0
Name: setuptools
Version: 18.4
Summary: Easily download, build, install, upgrade, and uninstall Python packages
Home-page: https://bitbucket.org/pypa/setuptools
Author: Python Packaging Authority
Author-email: [email protected]
License: PSF or ZPL
Location: /usr/local/lib/python3.4/site-packages
Requires: 
0
Peter Ehrlich

私の考えでは、いくつかの投稿された回答を組み合わせて、それらを実行中のpython環境から使いやすくするためのいくつかの修正を加えています。

アイデアは、使用するパッケージFinderのインスタンスを提供する、まったく新しいコマンド(installコマンドをモデルにしたもの)を提供することです。利点は、pipがサポートしているローカルのpip設定ファイルを読み、それを使用するということです。そのため、通常のpipインストールと同じ結果が得られます。

私はそれをpip v 9.xと10.xの両方と互換性があるようにすることを試みましたが、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 __== '__main__':
    sys.exit(main())

出力例

$ ./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
0
Kaos

これが現在のPythonのpipベースの方法で、従来のPyPiパッケージAPIを検索しています。

from pip import index
import requests
Finder = index.PackageFinder(
    [],
    ['https://pypi.python.org/simple'],
    session=requests.Session()
)
results = Finder.find_all_candidates("package_name")
versions = [p.version for p in results]
0
benjaoming

別の解決策はWarehouse APIを使用することです。

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

例えばFlaskの場合:

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

印刷されます:

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'])
0
Charlie