[Zodb-checkins] CVS: Zope/lib/python/persistent/tests -
__init__.py:1.2 testPersistent.py:1.2 test_pickle.py:1.2
Jim Fulton
cvs-admin at zope.org
Fri Nov 28 11:45:28 EST 2003
Update of /cvs-repository/Zope/lib/python/persistent/tests
In directory cvs.zope.org:/tmp/cvs-serv3783/lib/python/persistent/tests
Added Files:
__init__.py testPersistent.py test_pickle.py
Log Message:
Merged Jeremy and Tim's changes from the zodb33-devel-branch.
=== Zope/lib/python/persistent/tests/__init__.py 1.1 => 1.2 ===
--- /dev/null Fri Nov 28 11:45:28 2003
+++ Zope/lib/python/persistent/tests/__init__.py Fri Nov 28 11:44:56 2003
@@ -0,0 +1 @@
+# package
=== Zope/lib/python/persistent/tests/testPersistent.py 1.1 => 1.2 ===
--- /dev/null Fri Nov 28 11:45:28 2003
+++ Zope/lib/python/persistent/tests/testPersistent.py Fri Nov 28 11:44:56 2003
@@ -0,0 +1,224 @@
+#############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+import pickle
+import time
+import unittest
+
+from persistent import Persistent
+from persistent.cPickleCache import PickleCache
+from persistent.TimeStamp import TimeStamp
+from ZODB.utils import p64
+
+class Jar(object):
+ """Testing stub for _p_jar attribute."""
+
+ def __init__(self):
+ self.cache = PickleCache(self)
+ self.oid = 1
+ self.registered = {}
+
+ def add(self, obj):
+ obj._p_oid = p64(self.oid)
+ self.oid += 1
+ obj._p_jar = self
+ self.cache[obj._p_oid] = obj
+
+ def close(self):
+ pass
+
+ # the following methods must be implemented to be a jar
+
+ def setklassstate(self):
+ # I don't know what this method does, but the pickle cache
+ # constructor calls it.
+ pass
+
+ def register(self, obj):
+ self.registered[obj] = 1
+
+ def setstate(self, obj):
+ # Trivial setstate() implementation that just re-initializes
+ # the object. This isn't what setstate() is supposed to do,
+ # but it suffices for the tests.
+ obj.__class__.__init__(obj)
+
+class P(Persistent):
+ pass
+
+class H1(Persistent):
+
+ def __init__(self):
+ self.n = 0
+
+ def __getattr__(self, attr):
+ self.n += 1
+ return self.n
+
+class H2(Persistent):
+
+ def __init__(self):
+ self.n = 0
+
+ def __getattribute__(self, attr):
+ supergetattr = super(H2, self).__getattribute__
+ try:
+ return supergetattr(attr)
+ except AttributeError:
+ n = supergetattr("n")
+ self.n = n + 1
+ return n + 1
+
+class PersistenceTest(unittest.TestCase):
+
+ def setUp(self):
+ self.jar = Jar()
+
+ def tearDown(self):
+ self.jar.close()
+
+ def testOidAndJarAttrs(self):
+ obj = P()
+ self.assertEqual(obj._p_oid, None)
+ obj._p_oid = 12
+ self.assertEqual(obj._p_oid, 12)
+ del obj._p_oid
+
+ self.jar.add(obj)
+
+ # Can't change oid of cache object.
+ def deloid():
+ del obj._p_oid
+ self.assertRaises(ValueError, deloid)
+ def setoid():
+ obj._p_oid = 12
+ self.assertRaises(ValueError, setoid)
+
+ def deloid():
+ del obj._p_jar
+ self.assertRaises(ValueError, deloid)
+ def setoid():
+ obj._p_jar = 12
+ self.assertRaises(ValueError, setoid)
+
+ def testChanged(self):
+ obj = P()
+ self.jar.add(obj)
+
+ # The value returned for _p_changed can be one of:
+ # 0 -- it is not changed
+ # 1 -- it is changed
+ # None -- it is a ghost
+
+ obj.x = 1
+ self.assertEqual(obj._p_changed, 1)
+ self.assert_(obj in self.jar.registered)
+
+ obj._p_changed = 0
+ self.assertEqual(obj._p_changed, 0)
+ self.jar.registered.clear()
+
+ obj._p_changed = 1
+ self.assertEqual(obj._p_changed, 1)
+ self.assert_(obj in self.jar.registered)
+
+ # setting obj._p_changed to None ghostifies if the
+ # object is in the up-to-date state, but not otherwise.
+ obj._p_changed = None
+ self.assertEqual(obj._p_changed, 1)
+ obj._p_changed = 0
+ # Now it's a ghost.
+ obj._p_changed = None
+ self.assertEqual(obj._p_changed, None)
+
+ obj = P()
+ self.jar.add(obj)
+ obj._p_changed = 1
+ # You can transition directly from modified to ghost if
+ # you delete the _p_changed attribute.
+ del obj._p_changed
+ self.assertEqual(obj._p_changed, None)
+
+ def testSerial(self):
+ noserial = "\000" * 8
+ obj = P()
+ self.assertEqual(obj._p_serial, noserial)
+
+ def set(val):
+ obj._p_serial = val
+ self.assertRaises(ValueError, set, 1)
+ self.assertRaises(ValueError, set, "0123")
+ self.assertRaises(ValueError, set, "012345678")
+ self.assertRaises(ValueError, set, u"01234567")
+
+ obj._p_serial = "01234567"
+ del obj._p_serial
+ self.assertEqual(obj._p_serial, noserial)
+
+ def testMTime(self):
+ obj = P()
+ self.assertEqual(obj._p_mtime, None)
+
+ t = int(time.time())
+ ts = TimeStamp(*time.gmtime(t)[:6])
+ obj._p_serial = repr(ts)
+ self.assertEqual(obj._p_mtime, t)
+ self.assert_(isinstance(obj._p_mtime, float))
+
+ def testPicklable(self):
+ obj = P()
+ obj.attr = "test"
+ s = pickle.dumps(obj)
+ obj2 = pickle.loads(s)
+ self.assertEqual(obj.attr, obj2.attr)
+
+ def testGetattr(self):
+ obj = H1()
+ self.assertEqual(obj.larry, 1)
+ self.assertEqual(obj.curly, 2)
+ self.assertEqual(obj.moe, 3)
+
+ self.jar.add(obj)
+ obj._p_deactivate()
+
+ # The simple Jar used for testing re-initializes the object.
+ self.assertEqual(obj.larry, 1)
+ # The getattr hook modified the object, so it should now be
+ # in the changed state.
+ self.assertEqual(obj._p_changed, 1)
+ self.assertEqual(obj.curly, 2)
+ self.assertEqual(obj.moe, 3)
+
+ def testGetattribute(self):
+ obj = H2()
+ self.assertEqual(obj.larry, 1)
+ self.assertEqual(obj.curly, 2)
+ self.assertEqual(obj.moe, 3)
+
+ self.jar.add(obj)
+ obj._p_deactivate()
+
+ # The simple Jar used for testing re-initializes the object.
+ self.assertEqual(obj.larry, 1)
+ # The getattr hook modified the object, so it should now be
+ # in the changed state.
+ self.assertEqual(obj._p_changed, 1)
+ self.assertEqual(obj.curly, 2)
+ self.assertEqual(obj.moe, 3)
+
+ # XXX Need to decide how __setattr__ and __delattr__ should work,
+ # then write tests.
+
+
+def test_suite():
+ return unittest.makeSuite(PersistenceTest)
=== Zope/lib/python/persistent/tests/test_pickle.py 1.1 => 1.2 ===
--- /dev/null Fri Nov 28 11:45:28 2003
+++ Zope/lib/python/persistent/tests/test_pickle.py Fri Nov 28 11:44:56 2003
@@ -0,0 +1,294 @@
+##############################################################################
+#
+# Copyright (c) 2003 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.0 (ZPL). A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""Basic pickling tests
+
+$Id$
+"""
+
+from persistent import Persistent
+import pickle
+
+
+def print_dict(d):
+ d = d.items()
+ d.sort()
+ print '{%s}' % (', '.join(
+ [('%r: %r' % (k, v)) for (k, v) in d]
+ ))
+
+def cmpattrs(self, other, *attrs):
+ for attr in attrs:
+ if attr[:3] in ('_v_', '_p_'):
+ continue
+ c = cmp(getattr(self, attr, None), getattr(other, attr, None))
+ if c:
+ return c
+ return 0
+
+class Simple(Persistent):
+ def __init__(self, name, **kw):
+ self.__name__ = name
+ self.__dict__.update(kw)
+ self._v_favorite_color = 'blue'
+ self._p_foo = 'bar'
+
+ def __cmp__(self, other):
+ return cmpattrs(self, other, '__class__', *(self.__dict__.keys()))
+
+def test_basic_pickling():
+ """
+ >>> x = Simple('x', aaa=1, bbb='foo')
+
+ >>> x.__getnewargs__()
+ ()
+
+ >>> print_dict(x.__getstate__())
+ {'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
+
+ >>> f, (c,), state = x.__reduce__()
+ >>> f.__name__
+ '__newobj__'
+ >>> f.__module__
+ 'copy_reg'
+ >>> c.__name__
+ 'Simple'
+
+ >>> print_dict(state)
+ {'__name__': 'x', 'aaa': 1, 'bbb': 'foo'}
+
+ >>> pickle.loads(pickle.dumps(x)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 0)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 1)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 2)) == x
+ 1
+
+ >>> x.__setstate__({'z': 1})
+ >>> x.__dict__
+ {'z': 1}
+
+ """
+
+class Custom(Simple):
+
+ def __new__(cls, x, y):
+ r = Persistent.__new__(cls)
+ r.x, r.y = x, y
+ return r
+
+ def __init__(self, x, y):
+ self.a = 42
+
+ def __getnewargs__(self):
+ return self.x, self.y
+
+ def __getstate__(self):
+ return self.a
+
+ def __setstate__(self, a):
+ self.a = a
+
+
+def test_pickling_w_overrides():
+ """
+ >>> x = Custom('x', 'y')
+ >>> x.a = 99
+
+ >>> (f, (c, ax, ay), a) = x.__reduce__()
+ >>> f.__name__
+ '__newobj__'
+ >>> f.__module__
+ 'copy_reg'
+ >>> c.__name__
+ 'Custom'
+ >>> ax, ay, a
+ ('x', 'y', 99)
+
+ >>> pickle.loads(pickle.dumps(x)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 0)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 1)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 2)) == x
+ 1
+
+ """
+
+class Slotted(Persistent):
+ __slots__ = 's1', 's2', '_p_splat', '_v_eek'
+ def __init__(self, s1, s2):
+ self.s1, self.s2 = s1, s2
+ self._v_eek = 1
+ self._p_splat = 2
+
+class SubSlotted(Slotted):
+ __slots__ = 's3', 's4'
+ def __init__(self, s1, s2, s3):
+ Slotted.__init__(self, s1, s2)
+ self.s3 = s3
+
+
+ def __cmp__(self, other):
+ return cmpattrs(self, other, '__class__', 's1', 's2', 's3', 's4')
+
+
+def test_pickling_w_slots_only():
+ """
+ >>> x = SubSlotted('x', 'y', 'z')
+
+ >>> x.__getnewargs__()
+ ()
+
+ >>> d, s = x.__getstate__()
+ >>> d
+ >>> print_dict(s)
+ {'s1': 'x', 's2': 'y', 's3': 'z'}
+
+ >>> pickle.loads(pickle.dumps(x)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 0)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 1)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 2)) == x
+ 1
+
+ >>> x.s4 = 'spam'
+
+ >>> d, s = x.__getstate__()
+ >>> d
+ >>> print_dict(s)
+ {'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
+
+ >>> pickle.loads(pickle.dumps(x)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 0)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 1)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 2)) == x
+ 1
+
+ """
+
+class SubSubSlotted(SubSlotted):
+
+ def __init__(self, s1, s2, s3, **kw):
+ SubSlotted.__init__(self, s1, s2, s3)
+ self.__dict__.update(kw)
+ self._v_favorite_color = 'blue'
+ self._p_foo = 'bar'
+
+ def __cmp__(self, other):
+ return cmpattrs(self, other,
+ '__class__', 's1', 's2', 's3', 's4',
+ *(self.__dict__.keys()))
+
+def test_pickling_w_slots():
+ """
+ >>> x = SubSubSlotted('x', 'y', 'z', aaa=1, bbb='foo')
+
+ >>> x.__getnewargs__()
+ ()
+
+ >>> d, s = x.__getstate__()
+ >>> print_dict(d)
+ {'aaa': 1, 'bbb': 'foo'}
+ >>> print_dict(s)
+ {'s1': 'x', 's2': 'y', 's3': 'z'}
+
+ >>> pickle.loads(pickle.dumps(x)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 0)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 1)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 2)) == x
+ 1
+
+ >>> x.s4 = 'spam'
+
+ >>> d, s = x.__getstate__()
+ >>> print_dict(d)
+ {'aaa': 1, 'bbb': 'foo'}
+ >>> print_dict(s)
+ {'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
+
+ >>> pickle.loads(pickle.dumps(x)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 0)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 1)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 2)) == x
+ 1
+
+ """
+
+def test_pickling_w_slots_w_empty_dict():
+ """
+ >>> x = SubSubSlotted('x', 'y', 'z')
+
+ >>> x.__getnewargs__()
+ ()
+
+ >>> d, s = x.__getstate__()
+ >>> print_dict(d)
+ {}
+ >>> print_dict(s)
+ {'s1': 'x', 's2': 'y', 's3': 'z'}
+
+ >>> pickle.loads(pickle.dumps(x)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 0)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 1)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 2)) == x
+ 1
+
+ >>> x.s4 = 'spam'
+
+ >>> d, s = x.__getstate__()
+ >>> print_dict(d)
+ {}
+ >>> print_dict(s)
+ {'s1': 'x', 's2': 'y', 's3': 'z', 's4': 'spam'}
+
+ >>> pickle.loads(pickle.dumps(x)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 0)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 1)) == x
+ 1
+ >>> pickle.loads(pickle.dumps(x, 2)) == x
+ 1
+
+ """
+
+from doctest import DocTestSuite
+import unittest
+
+def test_suite():
+ return unittest.TestSuite((
+ DocTestSuite(),
+ ))
+
+if __name__ == '__main__': unittest.main()
+
+
+
More information about the Zodb-checkins
mailing list