Adding Jack Jansen's version checking utility.

This commit is contained in:
Guido van Rossum 1997-12-23 18:43:55 +00:00
parent 7f96291ee2
commit 5291037c70
4 changed files with 212 additions and 0 deletions

41
Tools/versioncheck/README Normal file
View File

@ -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.
<jack@cwi.nl>

View File

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

View File

@ -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()

View File

@ -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()