+#!/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
+ ])