Commit 95426303 authored by Tres Seaver's avatar Tres Seaver

Switch to using non-backward-compatible pickles

- Allow protocol 3 under Python 3.

- Do not stori bytes as strings under Python 3.

Fixes issue #4.
parent 58b05544
......@@ -5,6 +5,9 @@
Unreleased
==========
- Switch to using non-backward-compatible pickles (protocol 3, without
storing bytes as strings) under Python 3.
- Fixed: A ``UnicodeDecodeError`` could happen for non-ASCII OIDs
when using bushy blob layout.
......
......@@ -25,10 +25,7 @@ except ImportError:
class Pickler(zodbpickle.pickle.Pickler):
def __init__(self, f, protocol=None):
if protocol:
# we want to be backwards-compatible with Python 2
assert 0 <= protocol < 3
super(Pickler, self).__init__(f, protocol, bytes_as_strings=True)
super(Pickler, self).__init__(f, protocol)
class Unpickler(zodbpickle.pickle.Unpickler):
def __init__(self, f):
......@@ -45,16 +42,10 @@ except ImportError:
return self.find_global(modulename, name)
def dump(o, f, protocol=None):
if protocol:
# we want to be backwards-compatible with Python 2
assert 0 <= protocol < 3
return zodbpickle.pickle.dump(o, f, protocol, bytes_as_strings=True)
return zodbpickle.pickle.dump(o, f, protocol)
def dumps(o, protocol=None):
if protocol:
# we want to be backwards-compatible with Python 2
assert 0 <= protocol < 3
return zodbpickle.pickle.dumps(o, protocol, bytes_as_strings=True)
return zodbpickle.pickle.dumps(o, protocol)
def loads(s):
return zodbpickle.pickle.loads(s, encoding='ASCII', errors='bytes')
......
......@@ -38,7 +38,7 @@ def make_pickle(ob):
return sio.getvalue()
def test_factory(conn, module_name, name):
def _factory(conn, module_name, name):
return globals()[name]
class SerializerTestCase(unittest.TestCase):
......@@ -60,7 +60,7 @@ class SerializerTestCase(unittest.TestCase):
(ClassWithNewargs, (1,)))
def test_getClassName(self):
r = serialize.ObjectReader(factory=test_factory)
r = serialize.ObjectReader(factory=_factory)
eq = self.assertEqual
eq(r.getClassName(self.old_style_with_newargs),
__name__ + ".ClassWithNewargs")
......@@ -82,7 +82,7 @@ class SerializerTestCase(unittest.TestCase):
__import__(module)
return getattr(sys.modules[module], name)
r = TestObjectReader(factory=test_factory)
r = TestObjectReader(factory=_factory)
g = r.getGhost(self.old_style_with_newargs)
self.assertTrue(isinstance(g, ClassWithNewargs))
self.assertEqual(g, 1)
......@@ -119,9 +119,76 @@ class SerializerTestCase(unittest.TestCase):
self.assertTrue(not serialize.myhasattr(NewStyle(), "rat"))
class SerializerFunctestCase(unittest.TestCase):
def setUp(self):
import tempfile
self._tempdir = tempfile.mkdtemp(suffix='serializerfunc')
def tearDown(self):
import shutil
shutil.rmtree(self._tempdir)
def test_funky_datetime_serialization(self):
import os
import subprocess
fqn = os.path.join(self._tempdir, 'Data.fs')
prep_args = [sys.executable, '-c',
'from ZODB.tests.testSerialize import _functest_prep; '
'_functest_prep("%s")' % fqn]
subprocess.check_call(prep_args)
load_args = [sys.executable, '-c',
'from ZODB.tests.testSerialize import _functest_load; '
'_functest_load("%s")' % fqn]
subprocess.call(load_args)
def _working_failing_datetimes():
import datetime
WORKING = datetime.datetime(5375, 12, 31, 23, 59, 59)
# Any date after 5375 A.D. appears to trigger this bug.
FAILING = datetime.datetime(5376, 12, 31, 23, 59, 59)
return WORKING, FAILING
def _functest_prep(fqn):
# Prepare the database with a BTree which won't deserialize
# if the bug is present.
# run in separate process)
import transaction
from BTrees.OOBTree import OOBTree
from ZODB import DB
WORKING, FAILING = _working_failing_datetimes()
db = DB(fqn)
conn = db.open()
try:
root = conn.root()
tree = root['tree'] = OOBTree()
tree[WORKING] = 'working'
tree[FAILING] = 'failing'
transaction.commit()
finally: # Windoze
conn.close()
db.close()
def _functest_load(fqn):
# Open the database and attempt to deserialize the tree
# (run in separate process)
from ZODB import DB
WORKING, FAILING = _working_failing_datetimes()
db = DB(fqn)
conn = db.open()
try:
root = conn.root()
tree = root['tree']
assert tree[WORKING] == 'working'
assert tree[FAILING] == 'failing'
finally: # Windoze
conn.close()
db.close()
def test_suite():
suite = unittest.makeSuite(SerializerTestCase)
suite.addTest(
return unittest.TestSuite((
unittest.makeSuite(SerializerTestCase),
unittest.makeSuite(SerializerFunctestCase),
doctest.DocTestSuite("ZODB.serialize",
checker=ZODB.tests.util.checker))
return suite
checker=ZODB.tests.util.checker),
))
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