#!/usr/bin/env python # -*- coding: utf-8 -*- # vim: ts=4 # # Copyright (c) 2007 Benjamin Schweizer. All rights reserved. # # Abstract # ~~~~~~~~ # an interactive editor for pickle encoded data structures # # Authors # ~~~~~~~ # Benjamin Schweizer # # Changes # ~~~~~~~ # 2007-06-05, schweizer: reworked indent # 2007-06-04, schweizer: initial release # # Todo # ~~~~~ # - testing, especially indent() # - error handling # import sys import tempfile import subprocess import os import pickle import types def usage(): print """Copyright (c) 2007 Benjamin Schweizer. All rights reserved. pedit - an interactive editor for pickle encoded data structures usage: pedit [--dump] FILENAME --dump simple dump, don't load editor """ def indent(data, level=0, bol=True): """poor man's indent""" def escape(str): """string escape""" newstr = '' for c in str: if ord(c) in range(128): newstr += c else: newstr += '\\x%2x' % ord(c) str = newstr if '\r' in str or '\n' in str: return '"""%s"""' % str else: return '"%s"' % str.replace('"', '\\"') result = '' if bol: result += ' ' * level if type(data) == types.ListType: if not len(data): result += '[]' else: result += '[\n' for e in data: result += indent(e, level+1) result += ' ' * level + ']' elif type(data) == types.DictType: if not len(data): result += '{}' else: result += '{\n' for k in data: v = data[k] result += ' ' * (level+1) + '%s: ' % escape(k) result += indent(v, level+1, bol=False) result += ' ' * level + '}' elif type(data) == types.TupleType: if not len(data): result += '()' else: result += '(\n' for e in data: result += indent(e, level+1) result += ' ' * level + ')' elif type(data) == types.IntType: result += '%d' % data elif type(data) == types.LongType: result += '%dL' % data elif type(data) == types.FloatType: result += '%f' % data elif type(data) == types.BooleanType: result += '%s' % data elif type(data) == types.StringType: result += '%s' % escape(data) elif type(data) == types.UnicodeType: result += 'u%s' % escape(data) else: raise Exception('unhandeled data type, %s' % type(data)) if level: result += ',' result += '\n' return result if __name__ == '__main__': picklefilename = False for e in sys.argv: if e[0] != '-': picklefilename = e if not picklefilename: usage() sys.exit(1) # load pickle data try: fh = open(picklefilename, 'rb') data = pickle.load(fh) fh.close() except IOError, error: if not error.errno == 2: raise # else: file not found data = False # dump if '--dump' in sys.argv: print "%s" % indent(data) sys.exit(0) #else: fire up editor # export pretty printed data fd, tempfilename = tempfile.mkstemp() fh = os.fdopen(fd, "w+b") fh.write('# %s - pedit\n\n' % picklefilename) fh.write(indent(data)) fh.write('\n# eof.') fh.close() # edit tempfile editor = os.environ['EDITOR'] or 'vi' process = subprocess.Popen([editor, tempfilename]) process.communicate() # process.wait() # import tempfile fh = open(tempfilename, "rb") data_new = eval(fh.read()) fh.close() os.unlink(tempfilename) # updata source if data_new != data: fh = open(picklefilename, 'wb') pickle.dump(data_new, fh) fh.close() # else: do nothing # eof.