Source

jsonwidget-python / csvedit

Full commit
#!/usr/bin/python

import csv
import optparse
import os
import sys

import jsonwidget.termedit
import jsonwidget.schema
import jsonwidget.jsonnode



class CsvPinotFile(jsonwidget.termedit.JsonPinotFile):
    '''Glue to between PinotFile and underlying JSON object'''

    #jsonfile=None, schemafile=None
    def __init__(self, csvfile=None):
        if csvfile is None or os.access(csvfile, os.R_OK):
            # file exists, and we can read it (or we're just passing "None")
            self._load_csv(csvfile)
        elif os.access(jsonfile, os.F_OK):
            # file exists, but can't read it
            sys.stderr.write("Cannot access file \"%s\" (check permissions)\n" %
                             csvfile)
            sys.exit(os.EX_NOINPUT)
        else:
            # must be a new file
            sys.stderr.write("csvfile requires a filename\n")
            sys.exit(os.EX_NOINPUT)

    def _load_csv(self, filename):
        csvfile = open(filename)
        self._dialect = csv.Sniffer().sniff(csvfile.read(2048))
        self._dialect.escapechar = '\\'
        csvfile.seek(0)
        
        csvreader = csv.DictReader(csvfile, dialect=self._dialect)
        csvdata = [row for row in csvreader]
        csvschemaobj = jsonwidget.schema.generate_schema_from_data(csvdata)
        csvschemaobj.set_title(filename)
        csvschemaobj.get_child(0).set_title("Row")
        csvschemaobj.get_child(0).set_key_order(csvreader.fieldnames)
        # saving fieldnames ensures we don't scramble the column order
        self._fieldnames = csvreader.fieldnames
        self.json = jsonwidget.jsonnode.JsonNode(data=csvdata, 
                                                 schemanode=csvschemaobj)
        self.set_filename(filename)

    def save_to_file(self):
        fd = open(self.get_filename(), 'w+')
        csvwriter = csv.DictWriter(fd, fieldnames=self._fieldnames, 
                                   dialect=self._dialect)
        # write the header - see http://bugs.python.org/issue1537721
        csvwriter.writerow(dict(zip(self._fieldnames, self._fieldnames)))
        # write everything else
        csvwriter.writerows(self.json.get_data())
        self.json.set_saved()

    def get_filename(self):
        return self._filename

    def set_filename(self, name):
        self._filename = name

    def get_filename_text(self):
        return self._filename

    def get_schema_display_text(self):
        return ""


if __name__ == "__main__":
    '''urwid-based .csv/.tsv file editor'''
    usage = "usage: %prog [options] file"
    parser = optparse.OptionParser(usage)
    (options, args) = parser.parse_args()

    if len(args) > 1:
        parser.error("Too many arguments.")
    if len(args) == 1:
        csvfile = args[0]
    else:
        parser.error("Must supply file name")

    fileobj = CsvPinotFile(csvfile)

    form = jsonwidget.termedit.JsonFileEditor(fileobj=fileobj, 
                            program_name="csvedit")
    form.run()