Given the name of a Python package that can be installed with pip, is there any way to find out a list of all the possible versions of it that pip could install? Right now it's trial and error.

I'm trying to install a version for a third party library, but the newest version is too new, there were backwards incompatible changes made. So I'd like to somehow have a list of all the versions that pip knows about, so that I can test them.

29

Best Answer


For pip >= 21.2 use:

pip index versions pylibmc

Note that this command is experimental, and might change in the future!

For pip >= 21.1 use:

pip install pylibmc==

For pip >= 20.3 use:

pip install --use-deprecated=legacy-resolver pylibmc==

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

The available versions will be printed without actually downloading or installing any packages.

For pip < 9.0 use:

pip install pylibmc==blork

where blork can be any string that is not a valid version number.

(update: As of March 2020, many people have reported that yolk, installed via pip install yolk3k, only returns latest version. Chris's answer seems to have the most upvotes and worked for me)

The script at pastebin does work. However it's not very convenient if you're working with multiple environments/hosts because you will have to copy/create it every time.

A better all-around solution would be to use yolk3k, which is available to install with pip. E.g. to see what versions of Django are available:

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

yolk3k is a fork of the original yolk which ceased development in 2012. Though yolk is no longer maintained (as indicated in comments below), yolk3k appears to be and supports Python 3.

Note: I am not involved in the development of yolk3k. If something doesn't seem to work as it should, leaving a comment here should not make much difference. Use the yolk3k issue tracker instead and consider submitting a fix, if possible.

You don't need a third party package to get this information. pypi provides simple JSON feeds for all packages under

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

Here's some Python code using only the standard library which gets all versions.

import requestsfrom distutils.version import LooseVersiondef versions(package_name, limit_releases=10):url = f"https://pypi.org/pypi/{package_name}/json"data = requests.get(url).json()versions = list(data["releases"].keys())versions.sort(key=LooseVersion, reverse=True)return versions[:limit_releases]print("\n".join(versions("typeguard")))

That code prints (as of 21/Jul/2023):

4.0.0rc64.0.0rc54.0.0rc44.0.0rc34.0.0rc24.0.0rc14.0.03.0.23.0.13.0.0rc2

Update:
As of Sep 2017 this method no longer works: --no-install was removed in pip 7

Use pip install -v, you can see all versions that available

root@node7:~# pip install web.py -vDownloading/unpacking web.pyUsing 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 downloadedRunning setup.py egg_info for package web.pyrunning egg_infocreating pip-egg-info/web.py.egg-info

To not install any package, use one of following solution:

root@node7:~# pip install --no-deps --no-install flask -v Downloading/unpacking flaskUsing 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

or

root@node7:~# cd $(mktemp -d)root@node7:/tmp/tmp.c6H99cWD0g# pip install flask -d . -vDownloading/unpacking flaskUsing 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

Tested with pip 1.0

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

I came up with dead-simple bash script. Thanks to jq's author.

#!/bin/bashset -ePACKAGE_JSON_URL="https://pypi.org/pypi/${1}/json"curl -L -s "$PACKAGE_JSON_URL" | jq -r '.releases | keys | .[]' | sort -V

Update:

  • Add sorting by version number.
  • Add -L to follow redirects.

You can use this small Python 3 script (using only standard library modules) to grab the list of available versions for a package from PyPI using JSON API and print them in reverse chronological order. Unlike some other Python solutions posted here, this doesn't break on loose versions like django's 2.2rc1 or uwsgi's 2.0.17.1:

#!/usr/bin/env python3import jsonimport sysfrom 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')

Save the script and run it with the package name as an argument, e.g.:

python versions.py django
3.0a12.2.52.2.42.2.32.2.22.2.12.22.2rc1...

After looking at pip's code for a while, it looks like the code responsible for locating packages can be found in the PackageFinder class in pip.index. Its method find_requirement looks up the versions of a InstallRequirement, but unfortunately only returns the most recent version.

The code below is almost a 1:1 copy of the original function, with the return in line 114 changed to return all versions.

The script expects one package name as first and only argument and returns all versions.

http://pastebin.com/axzdUQhZ

I can't guarantee for the correctness, as I'm not familiar with pip's code. But hopefully this helps.

Sample output

python test.py pip
Versions of pip0.8.20.8.10.80.7.20.7.10.70.6.30.6.20.6.10.60.5.10.50.40.3.10.30.2.10.2 dev

The code:

import posixpathimport pkg_resourcesimport sysfrom pip.download import url_to_pathfrom pip.exceptions import DistributionNotFoundfrom pip.index import PackageFinder, Linkfrom pip.log import loggerfrom pip.req import InstallRequirementfrom pip.util import Infclass 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 = Noneif 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 filesall_index_urls = self.index_urls + self.mirror_urlsdef 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 locif url_name is not None:locations = [mkurl_pypi_url(url)for url in all_index_urls] + self.find_linkselse: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)] + locationsfile_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 += 2try:page_versions.extend(self._package_versions(page.links, req.name.lower()))finally:logger.indent -= 2dependency_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_versionsall_versions = found_versions + page_versions + dependency_versionsapplicable_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])))continueapplicable_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 Noneif 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 versionlogger.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 Noneif 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_versionsif __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]

You could the yolk3k package instead of yolk. yolk3k is a fork from the original yolk and it supports both python2 and 3.

https://github.com/myint/yolk

pip install yolk3k

You can try to install package version that does to exist. Then pip will list available versions

pip install hell==99999ERROR: Could not find a version that satisfies the requirement hell==99999(from versions: 0.1.0, 0.2.0, 0.2.1, 0.2.2, 0.2.3, 0.2.4, 0.3.0,0.3.1, 0.3.2, 0.3.3, 0.3.4, 0.4.0, 0.4.1)ERROR: No matching distribution found for hell==99999

My project luddite has this feature.

Example usage:

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

It lists all versions of a package available, by querying the JSON API of https://pypi.org/

This works for me on OSX:

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

It returns the list one per line:

1.1.0rc11.1.0rc21.1.01.2.0rc11.2.0rc21.2.0rc31.2.0rc41.2.01.3.0rc11.3.0rc21.3.0rc31.3.01.3.11.3.21.3.31.4.0rc11.4.0rc21.4.0rc31.4.01.4.11.4.21.5.0rc11.5.0rc21.5.0rc31.5.01.5.11.5.21.6.0rc11.6.01.6.11.6.21.7.0rc11.7.0rc21.7.01.7.11.8.0rc11.8.0rc21.8.01.8.11.9.0rc11.9.0rc21.9.0rc31.9.0rc41.9.01.10.0rc11.10.0rc21.10.0

Or to get the latest version available:

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

Keep in mind gsort has to be installed (on OSX) to parse the versions. You can install it with brew install coreutils

Update:

Maybe the solution is not needed anymore, check comments to this answer.

Original Answer

With pip versions above 20.03 you can use the old solver in order to get back all the available versions:

$ pip install --use-deprecated=legacy-resolver pylibmc==ERROR: Could not find a version that satisfies the requirement pylibmc== (from versions: 0.2, 0.3, 0.4, 0.5, 0.5.1, 0.5.2, 0.5.3, 0.5.4, 0.5.5, 0.6, 0.6.1,0.7, 0.7.1, 0.7.2, 0.7.3, 0.7.4, 0.8, 0.8.1, 0.8.2, 0.9, 0.9.1, 0.9.2, 1.0a0, 1.0b0, 1.0, 1.1, 1.1.1, 1.2.0, 1.2.1, 1.2.2, 1.2.3, 1.3.0, 1.4.0, 1.4.1, 1.4.2, 1.4.3, 1.5.0, 1.5.1, 1.5.2, 1.5.100.dev0, 1.6.0, 1.6.1)ERROR: No matching distribution found for pylibmc==

The pypi-version package does an excellent job:

$ pip3 install pip-versions$ pip-versions latest rsyncy0.0.4$ pip-versions list rsyncy0.0.10.0.20.0.30.0.4

And this even works behind a Nexus (sonatype) proxy!

I usually run pip install packagename==somerandomstring. This returns error saying Could not find a version that satisfies the requirement packagename==somerandomstring and along with that error, pip will also list available versions on the server.

e.g.

$ pip install flask==aksjflashdCollecting flask==aksjflashdCould not find a version that satisfies the requirement flask==aksjflashd (from versions: 0.1, 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, 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.12.5, 1.0, 1.0.1, 1.0.2, 1.0.3, 1.0.4, 1.1.0, 1.1.1, 1.1.2)No matching distribution found for flask==aksjflashd$

You have to be extremely unlucky if the random string like 'aksjflashd' turns out to be actual package version!

Of course, you can use this trick with pip download too.

https://pypi.python.org/pypi/Django/ - works for packages whose maintainers choose to show all packageshttps://pypi.python.org/simple/pip/ - should do the trick anyhow (lists all links)

Alternative solution is to use the Warehouse APIs:

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

For instance for Flask:

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

will print:

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

Here's my answer that sorts the list inside jq (for those who use systems where sort -V is not avalable) :

$ pythonPackage=certifi$ curl -Ls https://pypi.org/pypi/$pythonPackage/json | jq -r '.releases | keys_unsorted | sort_by( split(".") | map(tonumber) )'............. "2019.3.9","2019.6.16","2019.9.11","2019.11.28","2020.4.5","2020.4.5.1","2020.4.5.2","2020.6.20","2020.11.8"]

And to fetch the last version number of the package :

$ curl -Ls https://pypi.org/pypi/$pythonPackage/json | jq -r '.releases | keys_unsorted | sort_by( split(".") | map(tonumber) )[-1]'2020.11.8

or a bit faster :

$ curl -Ls https://pypi.org/pypi/$pythonPackage/json | jq -r '.releases | keys_unsorted | max_by( split(".") | map(tonumber) )'2020.11.8

Or even more simple :) :

$ curl -Ls https://pypi.org/pypi/$pythonPackage/json | jq -r .info.version2020.11.8

Simple bash script that relies only on python itself (I assume that in the context of the question it should be installed) and one of curl or wget. It has an assumption that you have setuptools package installed to sort versions (almost always installed). It doesn't rely on external dependencies such as:

  • jq which may not be present;
  • grep and awk that may behave differently on Linux and 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)))"

A little bit longer version with comments.

Put the package name into a variable:

PACKAGE=requests

Get versions (using 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)))")

Get versions (using 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)))")

Print sorted versions:

echo $VERSIONS

I didn't have any luck with yolk, yolk3k or pip install -v but so I ended up using this (adapted to Python 3 from eric chiang's answer):

import jsonimport requestsfrom distutils.version import StrictVersiondef 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.119.1.019.0.018.017.50.17.40.17.3...

Works with recent pip versions, no extra tools necessary:

pip install pylibmc== -v 2>/dev/null | awk '/Found link/ {print $NF}' | uniq

To find all available (even incompatible) versions as well, use the -vv flag with pip >= 21.x.

pip install sklearn== --dry-run -vv

Incompatible versions will be listed in the log like this:

Skipping link: none of the wheel's tags (cp27-cp27m-win32) are compatible

This is Py3.9+ version of Limmy+EricChiang 's solution.

import jsonimport urllib.requestfrom distutils.version import StrictVersion# print PyPI versions of packagedef versions(package_name):url = "https://pypi.org/pypi/%s/json" % (package_name,)data = json.load(urllib.request.urlopen(url))versions = list(data["releases"])sortfunc = lambda x: StrictVersion(x.replace('rc', 'b').translate(str.maketrans('cdefghijklmn', 'bbbbbbbbbbbb')))versions.sort(key=sortfunc)return versions

As of what I understood from this and this, the releases key will be dropped in a near future so solutions using GET "https://pypi.python.org/pypi/{package_name}/json" will not work anymore.

The easiest way to get the latest dependency version nowadays, using just curl and jq:

curl -sL https://pypi.org/pypi/${PACKAGE}/json | jq -r .info.version

My take is a combination of a couple of posted answers, with some modifications to make them easier to use from within a running python environment.

The idea is to provide a entirely new command (modeled after the install command) that gives you an instance of the package finder to use. The upside is that it works with, and uses, any indexes that pip supports and reads your local pip configuration files, so you get the correct results as you would with a normal pip install.

I've made an attempt at making it compatible with both pip v 9.x and 10.x.. but only tried it on 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 sysimport loggingtry:from pip._internal import cmdoptions, mainfrom pip._internal.commands import commands_dictfrom pip._internal.basecommand import RequirementCommandexcept ImportError:from pip import cmdoptions, mainfrom pip.commands import commands_dictfrom pip.basecommand import RequirementCommandfrom pip._vendor.packaging.version import parse as parse_versionlogger = 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_optscmd_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] = ListPkgVersionsCommandif __name__ == '__main__':sys.exit(main())

Example output

./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.0b2django: 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
pypi-has() { set -o pipefail; curl -sfL https://pypi.org/pypi/$1/json | jq -e --arg v $2 'any( .releases | keys[]; . == $v )'; }

Usage:

$ pypi-has django 4.0x ; echo $?false1$ pypi-has djangos 4.0x ; echo $?22$ pypi-has djangos 4.0 ; echo $?22$ pypi-has django 4.0 ; echo $?true0

Providing a programmatic approach to Chris's answer using pip install <package_name>==

import reimport subprocessfrom packaging.version import VERSION_PATTERN as _VRESION_PATTERNVERSION_PATTERN = re.compile(_VRESION_PATTERN , re.VERBOSE | re.IGNORECASE)def get_available_versions(package_name):process = subprocess.run(['pip', 'install', f'{package_name}=='], stdout=subprocess.DEVNULL, stderr=subprocess.PIPE)versions = []for line in process.stderr.decode('utf-8').splitlines():if 'Could not find a version that satisfies the requirement' in line:for match in VERSION_PATTERN.finditer(line.split('from versions:')[1]):versions.append(match.group(0))return versions

It can be used like

>>> get_available_versions('tensorflow')['2.2.0rc1', '2.2.0rc2', '2.2.0rc3', '2.2.0rc4', '2.2.0', '2.2.1', '2.2.2', '2.2.3', '2.3.0rc0', '2.3.0rc1', '2.3.0rc2', '2.3.0', '2.3.1', '2.3.2', '2.3.3', '2.3.4', '2.4.0rc0', '2.4.0rc1', '2.4.0rc2', '2.4.0rc3', '2.4.0rc4', '2.4.0', '2.4.1', '2.4.2', '2.4.3', '2.4.4', '2.5.0rc0', '2.5.0rc1', '2.5.0rc2', '2.5.0rc3', '2.5.0', '2.5.1', '2.5.2', '2.5.3', '2.6.0rc0', '2.6.0rc1', '2.6.0rc2', '2.6.0', '2.6.1', '2.6.2', '2.6.3', '2.7.0rc0', '2.7.0rc1', '2.7.0', '2.7.1', '2.8.0rc0', '2.8.0rc1', '2.8.0']

and return a list of versions.

Note: it seems to provide compatible releases rather than all releases. To get full list, use json approach from Eric.

To fetch the latest version for a GitLab private package, the below works.

pip index versions package-name --index-url https://<personal_access_token_name>:<personal_access_token>@gitlab.com/api/v4/projects/<project-id>/packages/pypi/simple/ | grep 'LATEST:' | sed -E 's/LATEST:| //g'

You can try to:

Step 1:

$ pip install get_pypi_latest_version

Step 2:

  • Run by python script:
    from get_pypi_latest_version import GetPyPiLatestVersionobtainer = GetPyPiLatestVersion()package_name = 'opencv-python'latest_version = obtainer(package_name)print(latest_version)
  • Run with CLI
    $ get_pypi_latest_version opencv-python# 4.7.0.72