# Miscelaneous functions

import sys
import os
import re

def assertPositive(i, msg):
    if i < 0:
        print 'Error: %s must be positive!' % msg
        sys.exit(1)

def assertGtZero(i, msg):
    if i < 1:
        print 'Error: %s must be greater than zero!' % msg
        sys.exit(1)

def assertExecExists(execPath):
     if not os.access(execPath, os.X_OK):
         print "Error: '%s' not found or is not runnable" % execPath
         sys.exit(1)

def assertFileExists(filePath):
     if not os.access(filePath, os.F_OK):
         print "Error: '%s' not found " % filePath
         sys.exit(1)

def mkdirsOrDie(path):
    try:
        os.makedirs(path)
    except:
        print "Error: Couldn't create directory '%s'" % path
        raise

def chdirOrDie(path):
    try:
        os.chdir(path)
    except:
        print "Error: Couldn't change directory to '%s'" % path
        raise

def sortedListDir(path):
    l = os.listdir(path)
    return natsort(l)

def removeOrDie(path):
    try:
        os.remove(path)
    except:
        print "Error: Couldn't delete file '%s'" % path
        raise

def systemOrWarn(prg, args, acceptedExits=[], tries=1, **redirections):
    cmd = '(%s)' % reduce(lambda s, t: '%s %s' % (s, t), args, prg)

    # handle output redirections
    for (redirType, redirChar) in [('stdin', '<'), ('stdout','>'), ('stderr', '2>')]:
        if redirections.has_key(redirType):
            redirTarget = redirections[redirType]
            if redirTarget == None:
                redirTarget = '/dev/null'

            cmd = '%s %s %s' % (cmd, redirChar, redirTarget)

    # filter out the non-signal part of the result code
    resultAndKiller = os.system(cmd)
    result = resultAndKiller & 65280 # 11111111 00000000
    result = result >> 8
    signal = resultAndKiller & 255   # 00000000 11111111 (see the python doc)
    if signal == 2:
        print "Interrupted '%s'" % cmd
        sys.exit(1)
    elif result in acceptedExits:
        print "Recognised error: %i" % result
    elif result != 0 or signal != 0:
        print "Unknown error executing '%s': %i (sig %i)" % (cmd, result, signal)
        if tries > 1:
          tries = tries - 1
          print ("Trying again (%s tries left)" % tries)
          systemOrWarn(prg, args, acceptedExits, tries, **redirections)
    return result

def systemOrDie(prg, args, acceptedExits=[], tries=1, **redirections):
    result = systemOrWarn(prg, args, acceptedExits, tries, **redirections)
    if result != 0:
      sys.exit(1)

_rollingBarFrames = ['|', '/', '-', '\\']
_currentRollingBarFrame = 0

def which(prgName):
    path = os.environ['PATH']
    for p in path.split(os.pathsep):
        fullName = os.path.join(p, prgName)
        if os.access(fullName, os.X_OK):
            return fullName
    return None

def rollBar():
    """ this doesn't work!
    """
    global _currentRollingBarFrame
    sys.stdout.write('%s\b' % _rollingBarFrames[0])
    _currentRollingBarFrame = (_currentRollingBarFrame + 1) % len(_rollingBarFrames)

# sort 'naturally' (t1 t2 t10, instead of t1 t10 t2)
# by John Mitchell, from python cookbook
def natsort(list_):
    # decorate
    tmp = [ (int(re.search('\d+', i).group(0)), i) for i in list_ ]
    tmp.sort()
    # undecorate
    return [ i[1] for i in tmp ]
