veekun_pokedex/bin/edit-csv-as-yaml

99 lines
2.7 KiB
Text
Raw Normal View History

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