Commit c5d3e66b authored by Tim Peters's avatar Tim Peters

get_pickle_metadata(): This did crazy stuff if the ZODB pickle

started with a pickle GLOBAL opcode.  Curiously, it handled the
case of starting with a MARK GLOBAL opcode *sequence* fine.
parent 40d192d9
......@@ -34,6 +34,15 @@ analyze.py produced spurious "len of unsized object" messages when
finding a data record for an object uncreation or version abort. These
no longer appear.
fsdump.py's get_pickle_metadata() function (which is used by several
tools) was confused about what to do when the ZODB pickle started with
a pickle GLOBAL opcode. It actually loaded the class then, which it
intends never to do, leading to stray messages on stdout when the class
wasn't available, and leading to a strange return value even when it was
available (the repr of the type object was returned as "the module name",
and an empty string was returned as "the class name"). This has been
repaired.
What's new in ZODB3 3.3 beta 2
==============================
......
from cPickle import Unpickler
from cStringIO import StringIO
import md5
import struct
from ZODB.FileStorage import FileIterator
from ZODB.FileStorage.format \
import TRANS_HDR, TRANS_HDR_LEN, DATA_HDR, DATA_HDR_LEN
......@@ -5,23 +10,27 @@ from ZODB.TimeStamp import TimeStamp
from ZODB.utils import u64
from ZODB.tests.StorageTestBase import zodb_unpickle
from cPickle import Unpickler
from cStringIO import StringIO
import md5
import struct
import types
def get_pickle_metadata(data):
# ZODB's data records contain two pickles. The first is the class
# of the object, the second is the object. We're only trying to
# pick apart the first here, to extract the module and class names.
if data.startswith('(c'): # pickle MARK GLOBAL sequence
if data.startswith('(c'): # pickle MARK GLOBAL opcode sequence
global_prefix = 2
elif data.startswith('c'): # pickle GLOBAL opcode
global_prefix = 1
else:
global_prefix = 0
if global_prefix:
# Don't actually unpickle a class, because it will attempt to
# load the class. Just break open the pickle and get the
# module and class from it.
# module and class from it. The module and the class names are
# given by newline-terminated strings following the GLOBAL opcode.
modname, classname, rest = data.split('\n', 2)
modname = modname[2:] # strip leading '(c'
modname = modname[global_prefix:] # strip GLOBAL opcode
return modname, classname
# Else there are a bunch of other possible formats.
f = StringIO(data)
u = Unpickler(f)
try:
......@@ -29,8 +38,8 @@ def get_pickle_metadata(data):
except Exception, err:
print "Error", err
return '', ''
if isinstance(class_info, types.TupleType):
if isinstance(class_info[0], types.TupleType):
if isinstance(class_info, tuple):
if isinstance(class_info[0], tuple):
modname, classname = class_info[0]
else:
modname, classname = class_info
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment