[Checkins] SVN: zodbupgrade/trunk/src/zodbupgrade/picklefilter.py cleanup, refactoring

Christian Theune ct at gocept.com
Sun Jun 14 07:24:49 EDT 2009


Log message for revision 100943:
  cleanup, refactoring
  

Changed:
  U   zodbupgrade/trunk/src/zodbupgrade/picklefilter.py

-=-
Modified: zodbupgrade/trunk/src/zodbupgrade/picklefilter.py
===================================================================
--- zodbupgrade/trunk/src/zodbupgrade/picklefilter.py	2009-06-14 11:16:28 UTC (rev 100942)
+++ zodbupgrade/trunk/src/zodbupgrade/picklefilter.py	2009-06-14 11:24:49 UTC (rev 100943)
@@ -22,7 +22,6 @@
 import pickletools
 import StringIO
 
-
 # The following functions were created on the basis of the code found in
 # pickle.py. They reflect all opcodes that pickle knows about and how they get
 # written to the output stream under the knowledge how pickletools.genops
@@ -30,8 +29,10 @@
 
 packi = lambda arg:struct.pack('<i', arg)
 reprn = lambda arg:repr(arg)+'\n'
+strn = lambda arg:str(arg)+'\n'
 fact_ref = lambda arg:arg.replace(' ','\n')+'\n'
 arg_len = lambda arg:packi(len(arg))+arg
+unicode_escape = lambda arg:arg.replace('\\', '\\u005c').replace('\n', '\\u000a').encode('raw-unicode-escape')+'\n'
 
 noargs = '().NQR]abdeostu}l\x81\x85\x86\x87\x88\x89210'
 generators = {
@@ -53,8 +54,8 @@
     'g': reprn,
     'q': chr,
     'r': packi,
-    'P': lambda arg:str(arg)+'\n',
-    'V': lambda arg:arg.replace('\\', '\\u005c').replace('\n', '\\u000a').encode('raw-unicode-escape')+'\n',
+    'P': strn,
+    'V': unicode_escape,
     '\x80': chr,
     '\x82': chr,
     '\x83': lambda arg:"%c%c" % (arg&0xff, arg>>8),
@@ -64,42 +65,32 @@
 }
 
 
-def analyze(p):
-    new = ''
-    for op, arg, pos in pickletools.genops(p):
-        new += op.code
-        if op.code in noargs:
-            pass
-        elif op.code in generators:
-            generated = generators[op.code](arg)
-            new += generated
-        else:
-            print "+", op.code, arg, pos
-            raise SystemExit()
-    return new
+def to_pickle_chunk(op, arg):
+    """Transform an operation and its argument into pickle format."""
+    chunk = op.code
+    if op.code in noargs:
+        pass
+    elif op.code in generators:
+        generated = generators[op.code](arg)
+        chunk += generated
+    else:
+        raise ValueError('Unknown opcode: %s')
+    return chunk
 
-total = root._p_jar._db.objectCount()
-storage = root._p_jar._storage
-count = 0
-next = None
-while True:
-    last = next
-    count += 1
-    oid, tid, data, next = storage.record_iternext(next)
-    pickle_data = StringIO.StringIO(data)
-    # ZODB records consist of two concatenated pickles, so the following
-    # needs to be done twice:
-    if not count % 5000:
-        print '%s objects (%s%%)' % (count, float(count)/total*100.0)
-        print ZODB.utils.oid_repr(oid), ZODB.utils.oid_repr(tid)
-    new = ''
-    for i in range(2):
-        new += analyze(pickle_data)
-    if new != data:
-        print repr(last)
-        print repr(new)
-        print "="*80
-        print repr(data)
-        raise SystemExit()
-    if next is None:
-        break
+
+def filter(f, pickle_data):
+    """Apply filter function to each opcode of a pickle, return new pickle.
+
+    Calls function for each opcode with the arguments (code, arg) as created
+    by the pickletools.genops function. 
+
+    The filter function is expected to return a new (code, arg) tuple or None
+    which causes the old (code, arg) tuple to be placed into the stream again.
+
+    """
+    new = StringIO.StringIO()
+    for op, arg, pos in pickletools.genops(p):
+        result = f(op, arg)
+        op, arg = result if result is not None else op, arg
+        new.write(to_pickle_chunk(op, arg))
+    return new.getvalue()



More information about the Checkins mailing list