diff options
Diffstat (limited to 'Lib/csv/csv.py')
-rw-r--r-- | Lib/csv/csv.py | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/Lib/csv/csv.py b/Lib/csv/csv.py new file mode 100644 index 0000000000..a3ea4e20a6 --- /dev/null +++ b/Lib/csv/csv.py @@ -0,0 +1,138 @@ +from _csv import Error, __version__, writer, reader, register_dialect, \ + unregister_dialect, get_dialect, list_dialects, \ + QUOTE_MINIMAL, QUOTE_ALL, QUOTE_NONNUMERIC, QUOTE_NONE, \ + __doc__ + +__all__ = [ "QUOTE_MINIMAL", "QUOTE_ALL", "QUOTE_NONNUMERIC", "QUOTE_NONE", + "Error", "Dialect", "excel", "excel_tab", "reader", "writer", + "register_dialect", "get_dialect", "list_dialects", + "unregister_dialect", "__version__", "DictReader", "DictWriter" ] + +class Dialect: + _name = "" + _valid = False + # placeholders + delimiter = None + quotechar = None + escapechar = None + doublequote = None + skipinitialspace = None + lineterminator = None + quoting = None + + def __init__(self): + if self.__class__ != Dialect: + self._valid = True + errors = self._validate() + if errors != []: + raise Error, "Dialect did not validate: %s" % ", ".join(errors) + + def _validate(self): + errors = [] + if not self._valid: + errors.append("can't directly instantiate Dialect class") + + if self.delimiter is None: + errors.append("delimiter character not set") + elif (not isinstance(self.delimiter, str) or + len(self.delimiter) > 1): + errors.append("delimiter must be one-character string") + + if self.quotechar is None: + if self.quoting != QUOTE_NONE: + errors.append("quotechar not set") + elif (not isinstance(self.quotechar, str) or + len(self.quotechar) > 1): + errors.append("quotechar must be one-character string") + + if self.lineterminator is None: + errors.append("lineterminator not set") + elif not isinstance(self.lineterminator, str): + errors.append("lineterminator must be a string") + + if self.doublequote not in (True, False): + errors.append("doublequote parameter must be True or False") + + if self.skipinitialspace not in (True, False): + errors.append("skipinitialspace parameter must be True or False") + + if self.quoting is None: + errors.append("quoting parameter not set") + + if self.quoting is QUOTE_NONE: + if (not isinstance(self.escapechar, (unicode, str)) or + len(self.escapechar) > 1): + errors.append("escapechar must be a one-character string or unicode object") + + return errors + +class excel(Dialect): + delimiter = ',' + quotechar = '"' + doublequote = True + skipinitialspace = False + lineterminator = '\r\n' + quoting = QUOTE_MINIMAL +register_dialect("excel", excel) + +class excel_tab(excel): + delimiter = '\t' +register_dialect("excel-tab", excel_tab) + + +class DictReader: + def __init__(self, f, fieldnames, restkey=None, restval=None, + dialect="excel", *args): + self.fieldnames = fieldnames # list of keys for the dict + self.restkey = restkey # key to catch long rows + self.restval = restval # default value for short rows + self.reader = reader(f, dialect, *args) + + def __iter__(self): + return self + + def next(self): + row = self.reader.next() + # unlike the basic reader, we prefer not to return blanks, + # because we will typically wind up with a dict full of None + # values + while row == []: + row = self.reader.next() + d = dict(zip(self.fieldnames, row)) + lf = len(self.fieldnames) + lr = len(row) + if lf < lr: + d[self.restkey] = row[lf:] + elif lf > lr: + for key in self.fieldnames[lr:]: + d[key] = self.restval + return d + + +class DictWriter: + def __init__(self, f, fieldnames, restval="", extrasaction="raise", + dialect="excel", *args): + self.fieldnames = fieldnames # list of keys for the dict + self.restval = restval # for writing short dicts + if extrasaction.lower() not in ("raise", "ignore"): + raise ValueError, \ + ("extrasaction (%s) must be 'raise' or 'ignore'" % + extrasaction) + self.extrasaction = extrasaction + self.writer = writer(f, dialect, *args) + + def _dict_to_list(self, rowdict): + if self.extrasaction == "raise": + for k in rowdict.keys(): + if k not in self.fieldnames: + raise ValueError, "dict contains fields not in fieldnames" + return [rowdict.get(key, self.restval) for key in self.fieldnames] + + def writerow(self, rowdict): + return self.writer.writerow(self._dict_to_list(rowdict)) + + def writerows(self, rowdicts): + rows = [] + for rowdict in rowdicts: + rows.append(self._dict_to_list(rowdict)) + return self.writer.writerows(rows) |