From 5291037c704a0e092313b70fa09364296e3149fa Mon Sep 17 00:00:00 2001 From: Guido van Rossum Date: Tue, 23 Dec 1997 18:43:55 +0000 Subject: Adding Jack Jansen's version checking utility. --- Tools/versioncheck/README | 41 ++++++++++++++ Tools/versioncheck/_checkversion.py | 16 ++++++ Tools/versioncheck/checkversions.py | 54 +++++++++++++++++++ Tools/versioncheck/pyversioncheck.py | 101 +++++++++++++++++++++++++++++++++++ 4 files changed, 212 insertions(+) create mode 100644 Tools/versioncheck/README create mode 100644 Tools/versioncheck/_checkversion.py create mode 100644 Tools/versioncheck/checkversions.py create mode 100644 Tools/versioncheck/pyversioncheck.py diff --git a/Tools/versioncheck/README b/Tools/versioncheck/README new file mode 100644 index 0000000..a51411b --- /dev/null +++ b/Tools/versioncheck/README @@ -0,0 +1,41 @@ +This is versioncheck 1.0, a first stab at automatic checking of versions of +Python extension packages installed on your system. + +The basic idea is that each package contains a _checkversion.py +somewhere, probably at the root level of the package. In addition, each +package maintainer makes a file available on the net, through ftp or +http, which contains the version number of the most recent distribution +and some readable text explaining the differences with previous +versions, where to download the package, etc. + +The checkversions.py script walks through the installed Python tree (or +through a tree of choice), and runs each _checkversion.py script. These +scripts retrieve the current-version file over the net, compares version +numbers and tells the user about new versions of packages available. + +A boilerplate for the _checkversion.py file can be found here. Replace +package name, version and the URL of the version-check file and put it in +your distribution. In stead of a single URL you can also specify a list +of URLs. Each of these will be checked in order until one is available, +this is handy for distributions that live in multiple places. Put the +primary distribution site (the most up-to-date site) before others. +The script is executed with execfile(), not imported, and the current +directory is the checkversion directory, so be careful with globals, +importing, etc. + +The version-check file consists of an rfc822-style header followed by +plaintext. The only header field checked currently is +'Current-Version:', which should contain te current version and is +matched against the string contained in the _checkversion.py script. +The rest of the file is human-readable text and presented to the user if +there is a version mismatch. It should contain at the very least a URL +of either the current distribution or a webpage describing it. + +Pycheckversion.py is the module that does the actual checking of versions. +It should be fine where it is, it is imported by checkversion before anything +else is done, but if imports fail you may want to move it to somewhere +along sys.path. + + Jack Jansen, CWI, 23-Dec-97. + + diff --git a/Tools/versioncheck/_checkversion.py b/Tools/versioncheck/_checkversion.py new file mode 100644 index 0000000..a103bf9 --- /dev/null +++ b/Tools/versioncheck/_checkversion.py @@ -0,0 +1,16 @@ +"""This file (which is sourced, not imported) checks the version of the +"versioncheck" package. It is also an example of how to format your own +_checkversion.py file""" + +import pyversioncheck + +_PACKAGE="versioncheck" +_VERSION="1.0" +_URL="http://www.cwi.nl/~jack/versioncheck/curversion.txt" + +try: + _myverbose=VERBOSE +except NameError: + _myverbose=1 + +pyversioncheck.versioncheck(_PACKAGE, _URL, _VERSION, verbose=_myverbose) diff --git a/Tools/versioncheck/checkversions.py b/Tools/versioncheck/checkversions.py new file mode 100644 index 0000000..5715da1 --- /dev/null +++ b/Tools/versioncheck/checkversions.py @@ -0,0 +1,54 @@ +"""Checkversions - recursively search a directory (default: sys.prefix) +for _checkversion.py files, and run each of them. This will tell you of +new versions available for any packages you have installed.""" + +import os +import getopt +import sys +import pyversioncheck + +CHECKNAME="_checkversion.py" + +VERBOSE=1 + +USAGE="""Usage: checkversions [-v verboselevel] [dir ...] +Recursively examine a tree (default: sys.prefix) and for each package +with a _checkversion.py file compare the installed version against the current +version. + +Values for verboselevel: +0 - Minimal output, one line per package +1 - Also print descriptions for outdated packages (default) +2 - Print information on each URL checked +3 - Check every URL for packages with multiple locations""" + +def check1dir(dummy, dir, files): + if CHECKNAME in files: + fullname = os.path.join(dir, CHECKNAME) + try: + execfile(fullname) + except: + print '** Exception in', fullname + +def walk1tree(tree): + os.path.walk(tree, check1dir, None) + +def main(): + global VERBOSE + try: + options, arguments = getopt.getopt(sys.argv[1:], 'v:') + except getopt.error: + print USAGE + sys.exit(1) + for o, a in options: + if o == '-v': + VERBOSE = string.atoi(a) + if not arguments: + arguments = [sys.prefix] + for dir in arguments: + walk1tree(dir) + +if __name__ == '__main__': + main() + + diff --git a/Tools/versioncheck/pyversioncheck.py b/Tools/versioncheck/pyversioncheck.py new file mode 100644 index 0000000..074e917 --- /dev/null +++ b/Tools/versioncheck/pyversioncheck.py @@ -0,0 +1,101 @@ +"""pyversioncheck - Module to help with checking versions""" +import Types +import rfc822 +import urllib +import sys +import string + +# Verbose options +VERBOSE_SILENT=0 # Single-line reports per package +VERBOSE_NORMAL=1 # Single-line reports per package, more info if outdated +VERBOSE_EACHFILE=2 # Report on each URL checked +VERBOSE_CHECKALL=3 # Check each URL for each package + +# Test directory +## urllib bug: _TESTDIR="ftp://ftp.cwi.nl/pub/jack/python/versiontestdir/" +_TESTDIR="http://www.cwi.nl/~jack/versiontestdir/" + +def versioncheck(package, url, version, verbose=0): + ok, newversion, fp = checkonly(package, url, version, verbose) + if verbose > VERBOSE_NORMAL: + return ok + if ok < 0: + print '%s: No correctly formatted current version file found'%(package) + elif ok == 1: + print '%s: up-to-date (version %s)'%(package, version) + else: + print '%s: version %s installed, version %s found:' % \ + (package, version, newversion) + if verbose > VERBOSE_SILENT: + while 1: + line = fp.readline() + if not line: break + sys.stdout.write('\t'+line) + return ok + +def checkonly(package, url, version, verbose=0): + if verbose >= VERBOSE_EACHFILE: + print '%s:'%package + if type(url) == Types.StringType: + ok, newversion, fp = _check1version(package, url, version, verbose) + else: + for u in url: + ok, newversion, fp = _check1version(package, u, version, verbose) + if ok >= 0 and verbose < VERBOSE_CHECKALL: + break + return ok, newversion, fp + +def _check1version(package, url, version, verbose=0): + if verbose >= VERBOSE_EACHFILE: + print ' Checking %s'%url + try: + fp = urllib.urlopen(url) + except IOError, arg: + if verbose >= VERBOSE_EACHFILE: + print ' Cannot open:', arg + return -1, None, None + msg = rfc822.Message(fp, seekable=0) + newversion = msg.getheader('current-version') + if not newversion: + if verbose >= VERBOSE_EACHFILE: + print ' No "Current-Version:" header in URL or URL not found' + return -1, None, None + version = string.strip(string.lower(version)) + newversion = string.strip(string.lower(newversion)) + if version == newversion: + if verbose >= VERBOSE_EACHFILE: + print ' Version identical (%s)'%newversion + return 1, version, fp + else: + if verbose >= VERBOSE_EACHFILE: + print ' Versions different (installed: %s, new: %s)'% \ + (version, newversion) + return 0, newversion, fp + + +def _test(): + print '--- TEST VERBOSE=1' + print '--- Testing existing and identical version file' + versioncheck('VersionTestPackage', _TESTDIR+'Version10.txt', '1.0', verbose=1) + print '--- Testing existing package with new version' + versioncheck('VersionTestPackage', _TESTDIR+'Version11.txt', '1.0', verbose=1) + print '--- Testing package with non-existing version file' + versioncheck('VersionTestPackage', _TESTDIR+'nonexistent.txt', '1.0', verbose=1) + print '--- Test package with 2 locations, first non-existing second ok' + versfiles = [_TESTDIR+'nonexistent.txt', _TESTDIR+'Version10.txt'] + versioncheck('VersionTestPackage', versfiles, '1.0', verbose=1) + print '--- TEST VERBOSE=2' + print '--- Testing existing and identical version file' + versioncheck('VersionTestPackage', _TESTDIR+'Version10.txt', '1.0', verbose=2) + print '--- Testing existing package with new version' + versioncheck('VersionTestPackage', _TESTDIR+'Version11.txt', '1.0', verbose=2) + print '--- Testing package with non-existing version file' + versioncheck('VersionTestPackage', _TESTDIR+'nonexistent.txt', '1.0', verbose=2) + print '--- Test package with 2 locations, first non-existing second ok' + versfiles = [_TESTDIR+'nonexistent.txt', _TESTDIR+'Version10.txt'] + versioncheck('VersionTestPackage', versfiles, '1.0', verbose=2) + +if __name__ == '__main__': + _test() + + -- cgit v0.12