Added a little script for editing our csv files as yaml. veekun-promotions/2010112601
authorEevee <git@veekun.com>
Fri, 26 Nov 2010 07:04:38 +0000 (23:04 -0800)
committerEevee <git@veekun.com>
Fri, 26 Nov 2010 07:04:38 +0000 (23:04 -0800)
bin/edit-csv-as-yaml [new file with mode: 0755]

diff --git a/bin/edit-csv-as-yaml b/bin/edit-csv-as-yaml
new file mode 100755 (executable)
index 0000000..ea1aa81
--- /dev/null
@@ -0,0 +1,98 @@
+#!/usr/bin/env python
+"""Quick, dirty script that will convert a csv file to yaml, spawn an editor
+for you to fiddle with it, then convert back to csv and replace the original
+file.
+
+Run me as: $0 some_file.csv
+
+The editor used is $EDITOR, of course.
+
+This script is not guaranteed to be even remotely reliable, so consider only
+using it on files in source control.
+"""
+
+import codecs
+import csv
+import os
+import subprocess
+import sys
+import tempfile
+
+try:
+    import yaml
+except ImportError:
+    sys.stderr.write("Please install PyYAML.\n")
+    sys.exit(13)
+
+infilename, = sys.argv[1:]
+
+data = []
+with open(infilename) as infile:
+    reader = csv.reader(infile, lineterminator='\n')
+    column_names = [unicode(column) for column in next(reader)]
+
+    # Read data...
+    for row in reader:
+        datum = dict()
+        for col, value in zip(column_names, row):
+            datum[col] = value.decode('utf-8')
+
+        data.append(datum)
+
+
+# Monkeypatch yaml to use > syntax for multiline text; easier to edit
+from yaml.emitter import Emitter
+orig_choose_scalar_style = Emitter.choose_scalar_style
+def new_choose_scalar_style(self):
+    if self.analysis is None:
+        self.analysis = self.analyze_scalar(self.event.value)
+    if self.analysis.multiline:
+        return '>'
+    return orig_choose_scalar_style(self)
+Emitter.choose_scalar_style = new_choose_scalar_style
+
+# Write to a tempfile
+with tempfile.NamedTemporaryFile(suffix='.yml') as tmp:
+    yaml.safe_dump(data, tmp,
+        default_flow_style=False,
+        allow_unicode=True,
+        indent=4,
+    )
+    del data  # reclaim rams!
+
+    error_line = ''  # used on errors
+    while True:
+        args = [os.environ['EDITOR'], tmp.name]
+        if 'vim' in os.environ['EDITOR']:
+            # vim has an arg for jumping to a line:
+            args.append("+{0}".format(error_line))
+
+        # Run the user's editor and wait for it to close
+        subprocess.Popen(args).wait()
+        tmp.seek(0)
+
+        try:
+            new_data = yaml.safe_load(tmp)
+            break
+        except yaml.YAMLError as e:
+            if hasattr(e, 'problem_mark'):
+                error_line = e.problem_mark.line + 1
+            else:
+                error_line = ''
+
+            print
+            print "Oh my god what have you done:"
+            print
+            print str(e)
+            print
+            print "Press Enter to try again, or I guess ctrl-c to bail."
+            raw_input()
+
+with open(infilename, 'wb') as outfile:
+    writer = csv.writer(outfile, lineterminator='\n')
+    writer.writerow([ column.encode('utf8') for column in column_names ])
+
+    for datum in new_data:
+        writer.writerow([
+            datum[column].encode('utf8') for column in column_names
+        ])