import sys, string

# Ensure we have warn() and Warning
try:
    from warnings import warn
except ImportError:
    # We don't have the warning framework, so make our own
    def warn( message, category, stack_level ):
        # It would be better to use introspection to find out the name of the
        # calling program.  This is left as an excercise for the reader.  :-)
        sys.stderr.write( "WARNING: " + message + '\n' )
    class Warning(RuntimeError):
        pass

# Ensure we have version_info
try:
    from sys import version_info
except ImportError:
    _s = string.split( sys.version )[0]
    version_info = tuple( map(int, string.split(_s, '.') ) )
    del _s

class VersionWarning(Warning):
    pass
    
class VersionError(RuntimeError):
    pass
    
def _makeVersionString( vtup ):
    s = []
    for i in range(3):
        try:
            s.append( `vtup[i]` )
        except IndexError:
            s.append( '0' )
    return string.join(s, '.')
    
def versionChk(good_low, good_hi=None, below='error', \
               above='warn', name='this software'):
    """Checks to make sure that the version of Python that the program 
    is running on is between good_low and good_hi, where good_low and good_hi
    are tuples of up to 3 elements specifying (major, minor, point) release
    numbers.  The keyword arguments 'below' and 'above' are strings equal to 
    one of 'error' or 'warn'.  These arguments specify whether to print a 
    warning or raise an exception if the current version of python is outside 
    of the specified range.  Defaults are: below = 'error', above = 'warn'.
    The keyword argument 'name' can be used to identify the software package
    that is triggering the error to the user.
    
    Examples:
        To specify Python version 2.1 or later, raising an exception otherwise:
            versionChk( (2,1) )
        To specify Python version between 2.1 and 2.2, raising an exception
        otherwise and telling the user that file 'inquisition.py' is to blame:
            versionChk( (2,1), (2,2), above='error', name='inquisition.py' )
        To specify Python version between 2.2.1 and 3.0.0 release with 
        warnings for previous versions and errors for later versions:
            versionChk( (2,2,1), (3,), below='warn', above='error' )
    """
    
    currVer = version_info[0:3]
    good_low = good_low[0:3]
    if good_hi: 
        good_hi = good_hi[0:3]
        assert good_low <= good_hi, 'Low version must be <= high version!'
    
    if currVer < good_low:
        action = below
    else:
        if good_hi and currVer > good_hi:
            action = above
        else:
            return  # Everything is just fine
            
    if below == 'error': 
        bMsg = 'required '
    else: bMsg = 'recommended '
    if above == 'error': 
        aMsg = 'allowed '
    else: aMsg = 'recommended '
    
    msgTmp = 'The %s %s version of Python for %s is %s\n'
    msg = '\n' + msgTmp % ('minimum', bMsg, name, 
                           _makeVersionString( good_low ))
    if good_hi:
        msg = msg + msgTmp % ('maximum', aMsg, name, 
                              _makeVersionString( good_hi ))
        
    msg = msg + 'You are using Python version '
    msg = msg + _makeVersionString( currVer ) + '.\n'
        
    if action == 'warn':
        warn( msg, VersionWarning, 2 )
    else:
        raise VersionError, msg
