"""Support for CSV files. See README.txt and interfaces.py to learn more. """ import csv import grok from waeup.sirp.csvfile.interfaces import ICSVFile class CSVFile(grok.Adapter): """A CSV file abstraction. """ grok.context(basestring) grok.implements(ICSVFile) required_fields = [] path = None def __init__(self, context): self.path = context self.checkFields() def checkFields(self): headers = self.getHeaderFields() missing = [x for x in self.required_fields if x not in headers] if len(missing): raise TypeError('Missing columns in CSV file: %s' % missing) return def getDictReader(self): return csv.DictReader(open(self.path, 'rb')) def getData(self): reader = self.getDictReader() for row in reader: row = self.processRow(row) yield row def processRow(self, row): return row def getHeaderFields(self): path = self.path reader = self.getDictReader() reader.next() fields = reader.fieldnames return sorted(reader.fieldnames) # The registry for CSV file wrappers... csvwrappers = [CSVFile,] def getScore(path, wrapperclass): """Compute a score for a certain wrapper related to a certain CSV file. """ wrapper = None try: wrapper = wrapperclass(path) except: return -1 required = wrapper.required_fields if required == []: return 0 available_headers = wrapper.getHeaderFields() score = len([x for x in required if x in available_headers]) if score < len(required): return -1 return score def getCSVFile(path): """Get a CSVFile instance for a path. """ best_score = -1 best_wrapper = None for wrapperclass in csvwrappers: score = getScore(path, wrapperclass) if score < best_score or score == -1: continue best_score, best_wrapper = score, wrapperclass if best_wrapper is not None: return best_wrapper(path) return None