files.py

'''\
File Functions.

functions:
    put_file_text       (fname, txt)    -- write string to file (as entire file)
    get_file_text       (fname)         -- returns text (no filtering)

    put_file_lines      (fname, rows)   -- write list of strings to file (adds newline chars; blank lines okay)
    get_file_lines      (fname)         -- returns list (no newline chars; incl. blank lines)

    put_file_tab        (fname, data)   -- write TAB-delimited file from ([hdrs],[row][col]) dataset
    get_file_tab        (fname)         -- read TAB-delimited file (uses get_file_lines)

    put_file_csv        (fname, data)   -- write comma-delimited file from ([hdrs],[row][col]) dataset
    get_file_csv        (fname)         -- read comma-delimited file (uses get_file_lines)

    get_file_script     (fname)         -- (uses get_file_lines)
    get_file_map        (fname)         -- (uses get_file_script)
    get_file_parameters (fname)         -- returns parameter map

Developer@Sonnack.com
June 2013
'''
####################################################################################################
from sys import stdoutstderr
from os import path
from env import plural
####################################################################################################

TAB = '\t'
NL = '\n'
COMMA = ','


##================================================================================================##
def put_file_text (fnametxt):
    '''Write a string to a file. (returns string length)'''
    fp = open(fname'w')
    try:
        fp.write(txt)
        return len(txt)
    except:
        raise
    finally:
        fp.close()

##================================================================================================##
def get_file_text (fname):
    '''Read file into a string.'''
    test_file(fname)
    fp = open(fname'r')
    try:
        return fp.read()
    except:
        raise
    finally:
        fp.close()


##================================================================================================##
def put_file_lines (fnamerows):
    '''Write a list of strings to a file. (returns number of rows)'''
    fp = open(fname'w')
    try:
        for row in rows:
            fp.write(str(row))
            fp.write('\n')
        return len(rows)
    except:
        raise
    finally:
        fp.close()

##================================================================================================##
def get_file_lines (fname):
    '''Read file into an array of strings.'''
    test_file(fname)
    fp = open(fname'r')
    try:
        return [s.rstrip() for s in fp]
    except:
        raise
    finally:
        fp.close()


##================================================================================================##
def put_file_tab (fnamedatasetmaxrows=-1):
    '''Write a ([hdrs],[row][col]) dataset to a TAB file.'''
    hdrs,data = dataset
    n_cols = len(hdrs)
    r_rows = len(data)
    fp = open(fname'w')
    try:
        t = [str(hfor h in hdrs]
        fp.write(TAB.join(t))
        fp.write(NL)
        for rx,row in enumerate(data):
            if (0 <= maxrowsand (maxrows <= rx):
                break
            if len(row) < n_cols:
                raise Exception('Not enough columns in data row!')
            t = [str(colfor col in row]
            fp.write(TAB.join(t))
            fp.write(NL)
    except:
        raise
    finally:
        fp.close()
##================================================================================================##
def put_file_csv (fnamedatasetmaxrows=-1):
    '''Write a ([hdrs],[row][col]) dataset to a CSV file.'''
    hdrs,data = dataset
    n_cols = len(hdrs)
    r_rows = len(data)
    fp = open(fname'w')
    try:
        t = [str(hfor h in hdrs]
        fp.write(COMMA.join(t))
        fp.write(NL)
        for rx,row in enumerate(data):
            if (0 <= maxrowsand (maxrows <= rx):
                break
            if len(row) < n_cols:
                raise Exception('Not enough columns in data row!')
            t = [str(colfor col in row]
            fp.write(COMMA.join(t))
            fp.write(NL)
    except:
        raise
    finally:
        fp.close()

##================================================================================================##
def get_file_tab (fnamemaxrows=-1):
    '''Read file of TAB-delimited data.'''
    hdrs = []
    data = []
    test_file(fname)
    fp = open(fname'r')
    try:
        rx = -1 # skip the header
        for s in fp:
            rx += 1
            if (0 <= maxrowsand (maxrows < rx):
                break
            fields = s.split(TAB)
            # Remove trailing newline...
            fields[len(fields)-1] = fields[len(fields)-1].rstrip()
            if not hdrs:
                hdrs = fields
            else:
                data.append(fields)
        # Return Headers and RowData...
        return (hdrsdata)
    except:
        raise
    finally:
        fp.close()
##================================================================================================##
def get_file_csv (fnamemaxrows=-1):
    '''Read file of (unquoted!) comma-delimited data.'''
    hdrs = []
    data = []
    test_file(fname)
    fp = open(fname'r')
    try:
        rx = -1 # skip the header
        for s in fp:
            rx += 1
            if (0 <= maxrowsand (maxrows < rx):
                break
            fields = s.rstrip().split(COMMA)
            if not hdrs:
                hdrs = fields
            else:
                data.append(fields)
        # Return Headers and RowData...
        return (hdrsdata)
    except:
        raise
    finally:
        fp.close()


##================================================================================================##
def get_file_script (fname):
    '''Read file into an array of strings. Strip comments and blank lines.'''
    ff = lambda s: len(sand not (s.startswith('#'or s.startswith(';'or s.startswith('//'))
    txtlist = get_file_lines(fname)
    return [x for x in txtlist if ff(x)]


##================================================================================================##
def get_file_map (fname):
    '''Read file of TAB-delimited name/value pairs into a map.'''
    txtlist = get_file_script(fname)
    fldmap = {}
    for s in txtlist:
        pair = s.split('\t')
        if len(pair) != 2:
            raise Exception, ('Illegal Map Entry: "%s"' % s)
        fldmap[pair[0]] = pair[1]
    return fldmap


##================================================================================================##
def get_file_parameters (fname):
    '''Read Input Parameters (name = value).'''
    ff = lambda s: len(sand not (s.startswith('#'or s.startswith(';'or s.startswith('//'))
    test_file(fname)
    fp = open(fname'r')
    try:
        data = {}
        lc = 0
        for s in fp:
            lc = lc + 1
            s = s.strip()
            if not ff(s):
                continue
            # Split the field into name and value...
            t = s.partition('=')
            if t[1] != '=':
                raise Exception, ('Illegal Parameter: "%s"' % s)
            n = t[0].strip()
            # Convert vpipe to newline...
            v = t[2].strip().replace('|''\n')
            # Add new name=value pair...
            data[n] = v
            #print >> Log, 'Field: %s = "%s"' % (n, v)
        return data
    except:
        raise
    finally:
        fp.close()


##================================================================================================##
def test_file (fname):
    '''See if a filename exists and is really a file.'''
    if not path.exists(fname):
        raise IOError, ('File not found: "%s"' % fname)
    if not path.isfile(fname):
        raise IOError, ('Name not a file: "%s"' % fname)



####################################################################################################
'''eof'''