pipでインストールしたパッケージのVersion checkとUpgradeをするscript

パッケージ毎に「pip install --upgrade パッケージ名」とするのが面倒だったので書いてみました。

ちなみにLinuxだと

$ pip freeze | cut -d = -f 1  | xargs pip install -U

という方法もあるみたいですが、これだと最新版使ってても全部インストールし直してしまうのがちょっと…。また、PyPIにあるものが最新版とは限らないようでした。

というわけで書いてみた

一応コードはこんな感じ。
(Python2.5用のはGistで見てください。)

#-*- coding:utf-8 -*-

from pip import get_installed_distributions, call_subprocess
from subprocess import call
import sys

try:
    # Python 2.6, 2.7
    import xmlrpclib
except ImportError:
    # Python 3.x
    raw_input = input
    import xmlrpc.client as xmlrpclib


def check_versions(pypi_ver, installed):
    if installed.has_version():
        print("Checking:  ** {0} **".format(installed.project_name))
        print("IN PyPI:   {0}".format(pypi_ver[0]))
        print("INSTALLED: {0}".format(installed.version))
        if pypi_ver[0] == installed.version:
            print('Using latest version.\n')
        else:
            print("Versions don't match.\n")
            pip_upgrade(installed)
    else:
        print("{0} doesn't have version.\n".format(installed.project_name))

def pip_upgrade(dist):
    qstring1 = 'Do you want to upgrade "{0}"?: (y/n)'
    qstring2 = 'Really? (y/n):'
    upgrade_string = 'pip install --upgrade {0}'
    ans1 = raw_input(qstring1.format(dist.project_name))
    if ans1 == 'y':
        ans2 = raw_input(qstring2)
        if ans2 == 'y':
            try:
                # Windows
                call_subprocess(upgrade_string.format(dist.project_name))
            except OSError:
                # Linux
                call(upgrade_string.format(dist.project_name), shell=True)
            finally:
                print('Done.\n')
        else:
            print("Upgrading Canceled: {0}.\n".format(dist.project_name))
    else:
        print("Upgrading Canceled: {0}.\n".format(dist.project_name))

def main():
    client = xmlrpclib.ServerProxy('http://pypi.python.org/pypi')
    for installed in get_installed_distributions():
        pypi_ver = client.package_releases(installed.project_name)
        if len(pypi_ver) > 0:
            check_versions(pypi_ver, installed)
        else:
            capitalized = installed.project_name.capitalize()
            pypi_ver = client.package_releases(capitalized)
            if pypi_ver:
                check_versions(pypi_ver, installed)
            else:
                print('"{0}" is not found in PyPI\n'.format(
                                            installed.project_name))


if __name__ == '__main__':
    main()

xmlrpclibなんて初めて使ったけど、なかなか便利ですね。