""" Misc utils for manipulating CSV files. """ import sys, csv, socket, struct from types import * from time import mktime from datetime import date def error(msg,err=1): sys.stderr.write("Error: %s\n" % msg) sys.exit(err) def warn(msg): sys.stderr.write("Warning: %s\n" % msg) def notice(msg): sys.stderr.write("Notice: %s\n" % msg) def month_inc(d,v=1): "increment a date by a month" month = (d.month - 1) + v # decrement by 1 to get month range 0-11 year = d.year + (month/12) month = (month%12) + 1 # add 1 to get month range 1-12 return date(year, month, d.day) def datetotime(date): "convert datetime date to time" return mktime(date.timetuple()) def str2val(string): "convert a csv string to a date, int, float, or string value" try: # yyyy-mm-dd format date y,m,d = map(int,string.split('-')) return date(y,m,d) except: pass try: # dd/mm/yyyy format date d,m,y = map(int,string.split('/')) return date(y,m,d) except: pass try: # int value return int(string) except: pass try: # float value return float(string) except: # string return string def val2str(value): "convert a date, int, float, or string value to a csv string" # Just uses str(), as this has good default behaviour for most values. return str(value) def readcsv(csvfile,converter=stov): """ Reads a csv file with a header, returning the header list, and a list of dict's keyed by the header for each line. The optional converter parameter is a function used to convert field strings into values. """ head=csv.reader(csvfile).next() reader=csv.DictReader(csvfile,head) data=[] for row in reader: for key,val in row.items(): row[key]=converter(val) data.append(row) return head,data def writecsv(csvfile,head,data,header=True,converter=vtos): """ Writes a csv file from a header list and a list of dict's keyed by the header for each line. The optional converter parameter is a function used to convert values for fields into strings. """ if header: csv.writer(csvfile).writerow(head) writer=csv.DictWriter(csvfile,head,extrasaction='ignore') for row in data: r={} for key,val in row.items(): r[key]=converter(val) writer.writerow(r) def indexcsv(data,cols): """ Creates an index for a csv list of dicts, key'ed by the "columns" specified. The cols can be a tuple of headers, or a single header string. """ index={} for row in data: if type(cols) == StringType: key = row[cols] else: key = [] for col in cols: key.append(row[col]) key=tuple(key) index[key]=row return index def sortcsv(data,cols,reverse=False): """ Sorts a csv list of dicts by the "columns" specified. The cols can be a tupple of headers, or a single header string. The sort order can also be reversed. """ index = indexcsv(data,cols) keys = index.keys() keys.sort() if reverse: keys.reverse() ans = [] for key in keys: ans.append(index[key]) return ans def writeTextTable(textfile,fieldnames,records): """ write cvs fieldnames and records to a reStructuredText table""" # calculate column widths widths={} for col in fieldnames: width = max([len(str(row[col])) for row in records]) widths[col] = max(width,len(col)) # generate reStructuredText table seperator and format lines sepline = " ".join(['=' * widths[col] for col in fieldnames]) + '\n' format = " ".join(['%%%ds' % widths[col] for col in fieldnames]) + '\n' # write table header textfile.write(sepline) textfile.write(format % tuple(fieldnames)) textfile.write(sepline) # write table data for record in records: textfile.write(format % tuple([record[v] for v in fieldnames])) textfile.write(sepline) def writeHTMLTable(htmlfile,fieldnames,records): """ write cvs fieldnames and records into a html table """ def writeRow(htmlfile,row,tag="TD"): htmlfile.write("
%s
" % para)