Skip to content

Instantly share code, notes, and snippets.

@kaikuehne
Last active April 14, 2018 21:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save kaikuehne/5dfcd2de219a091962e4957c7e9b20e7 to your computer and use it in GitHub Desktop.
Save kaikuehne/5dfcd2de219a091962e4957c7e9b20e7 to your computer and use it in GitHub Desktop.
This script accepts a package name and version and prints the next package version that is newer than the one provided
#!/usr/bin/env python3
"""
Note: This will only work with python 3. You also need to install "packaging":
pip install packaging
"""
from typing import Iterable, Optional, Union
import json
import urllib.request
from packaging.version import Version, InvalidVersion
from pip._internal.operations.freeze import freeze
def main():
print('This tool is useful if you like to gradually update packages,\ninstead of upgrading to the newest available version.')
print('You might want to run this program repeatedly after upgrading. :-)')
print()
print('Package'.ljust(25), 'Installed'.ljust(25), 'Next version'.ljust(25))
print('=' * 75)
# TODO:
# Is the freeze-format always <pkg>==<version>
# even when a package is installed using range syntax?
for old in freeze():
if '==' not in old:
continue
old_package, old_version = old.split('==')
nxt_version = ''
try:
nxt_version = next_version(old_package, old_version)
except InvalidVersion as exp:
continue
if nxt_version:
print(old_package.ljust(25), old_version.ljust(25), str(nxt_version).ljust(25))
def versions(package_name) -> Iterable[Version]:
url = 'https://pypi.python.org/pypi/%s/json' % (package_name,)
request = urllib.request.Request(url)
data = json.load(urllib.request.urlopen(request))
versions = [str(r) for r in data["releases"]]
return sorted([Version(v) for v in versions])
def next_version(pkg: str, version: Union[str, Version]) -> Optional[Version]:
if isinstance(version, str):
version = Version(version)
for candidate in versions(pkg):
if candidate > version:
return candidate
if __name__ == '__main__':
main()
@kaikuehne
Copy link
Author

kaikuehne commented Apr 14, 2018

The output looks like this:

Package                   Installed                 Next version
===========================================================================
asgiref                   2.0.1                     2.1.0
autobahn                  17.10.1                   18.3.1
celery                    4.1.0                     4.2.0rc1
channels                  1.1.8                     2.0.0
daphne                    1.4.2                     2.0.0
Django                    1.11.9                    1.11.10
django-extensions         1.9.9                     2.0.0
django-polymorphic        1.3                       2.0
django-solo               1.1.2                     1.1.3
djangorestframework       3.7.7                     3.8.0
factory-boy               2.9.2                     2.10.0
Faker                     0.8.9                     0.8.10

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment