Search code examples
pythonpippypi

PyPI API - How to get stable package version


How does pip determine which version is the stable version of a package? For example, the current stable release of Django is 1.7.5 (as of 2-27-15), and that is the version installed by the command pip install django.

But when I go to the PyPI JSON API for Django (https://pypi.python.org/pypi/Django/json), it resolves to the most recent release (including development versions):

"version": "1.8b1",

There is a key in the JSON response that looks like it would indicate stable:

"stable_version": null,

but the value is null on all the packages I tried in the API. There is this line in the JSON response:

"classifiers": [
    "Development Status :: 4 - Beta", 

But that is a complex line to parse on. It would be nice if there was a line like "stable_version": true or false. How can I determine the default pip installed version using the PyPI JSON API?


Solution

  • Version scheme defined in the PEP-440. There is a module packaging, which can handle version parsing and comparison.

    I came up with this function to get latest stable version of a package:

    import requests
    import json
    try:
        from packaging.version import parse
    except ImportError:
        from pip._vendor.packaging.version import parse
    
    
    URL_PATTERN = 'https://pypi.python.org/pypi/{package}/json'
    
    
    def get_version(package, url_pattern=URL_PATTERN):
        """Return version of package on pypi.python.org using json."""
        req = requests.get(url_pattern.format(package=package))
        version = parse('0')
        if req.status_code == requests.codes.ok:
            j = json.loads(req.text.encode(req.encoding))
            releases = j.get('releases', [])
            for release in releases:
                ver = parse(release)
                if not ver.is_prerelease:
                    version = max(version, ver)
        return version
    
    
    if __name__ == '__main__':
        print("Django==%s" % get_version('Django'))
    

    When executed, this produces following results:

    $ python v.py
    Django==2.0