Commit 1a525601 authored by Tres Seaver's avatar Tres Seaver

Py3k compat:

- Bytes everywhere for OID / serials.

- Different obejct comparison semantics.

- Replace class advice 'implments' w/ 'implementer' decorator.

- Flatten 'items()' / 'keys()' iterators for testing.
parent a83f388b
......@@ -22,6 +22,11 @@ if sys.version_info[0] > 2: #pragma NO COVER
def _u(s):
return s
def _b(s):
if isinstance(s, str):
return s.encode('unicode_escape')
return s
def _native(s):
if isinstance(s, bytes):
return s.decode('unicode_escape')
......@@ -43,5 +48,7 @@ else: #pragma NO COVER
return s.encode('unicode_escape')
return s
_b = _native
PYTHON3 = False
PYTHON2 = True
......@@ -30,6 +30,8 @@ except ImportError: #pragma NO COVER
STICKY = 2
OID_TYPE = SERIAL_TYPE = bytes
class IPersistent(Interface):
"""Python persistent interface
......
......@@ -20,6 +20,8 @@ from persistent.interfaces import CHANGED
from persistent.interfaces import GHOST
from persistent.interfaces import IPickleCache
from persistent.interfaces import STICKY
from persistent.interfaces import OID_TYPE
from persistent.interfaces import SERIAL_TYPE
class RingNode(object):
# 32 byte fixed size wrapper.
......@@ -61,8 +63,8 @@ class PickleCache(object):
def __setitem__(self, oid, value):
""" See IPickleCache.
"""
if not isinstance(oid, str): # XXX bytes
raise ValueError('OID must be string: %s' % oid)
if not isinstance(oid, OID_TYPE): # XXX bytes
raise ValueError('OID must be %s: %s' % (OID_TYPE, oid))
# XXX
if oid in self.persistent_classes or oid in self.data:
if self.data[oid] is not value:
......@@ -80,7 +82,7 @@ class PickleCache(object):
def __delitem__(self, oid):
""" See IPickleCache.
"""
if not isinstance(oid, str):
if not isinstance(oid, OID_TYPE):
raise ValueError('OID must be string: %s' % oid)
if oid in self.persistent_classes:
del self.persistent_classes[oid]
......@@ -189,7 +191,7 @@ class PickleCache(object):
def reify(self, to_reify):
""" See IPickleCache.
"""
if isinstance(to_reify, str): #bytes
if isinstance(to_reify, OID_TYPE): #bytes
to_reify = [to_reify]
for oid in to_reify:
value = self[oid]
......
......@@ -20,12 +20,12 @@ from persistent.interfaces import GHOST
from persistent.interfaces import UPTODATE
from persistent.interfaces import CHANGED
from persistent.interfaces import STICKY
from persistent.interfaces import OID_TYPE
from persistent.interfaces import SERIAL_TYPE
from persistent.timestamp import TimeStamp
from persistent.timestamp import _ZERO
from persistent._compat import copy_reg
OID_TYPE = SERIAL_TYPE = bytes
_INITIAL_SERIAL = _ZERO
......
......@@ -14,6 +14,7 @@
# Example objects for pickling.
from persistent import Persistent
from persistent._compat import PYTHON2
def print_dict(d):
......@@ -27,9 +28,14 @@ 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
lhs, rhs = getattr(self, attr, None), getattr(other, attr, None)
if PYTHON2:
c = cmp(lhs, rhs)
if c:
return c
else:
if lhs != rhs:
return 1
return 0
class Simple(Persistent):
......@@ -39,8 +45,13 @@ class Simple(Persistent):
self._v_favorite_color = 'blue'
self._p_foo = 'bar'
def __cmp__(self, other):
return cmpattrs(self, other, '__class__', *(self.__dict__.keys()))
@property
def _attrs(self):
return list(self.__dict__.keys())
def __eq__(self, other):
return cmpattrs(self, other, '__class__', *self._attrs) == 0
class Custom(Simple):
......@@ -71,6 +82,13 @@ class Slotted(Persistent):
self._v_eek = 1
self._p_splat = 2
@property
def _attrs(self):
return list(self.__dict__.keys())
def __eq__(self, other):
return cmpattrs(self, other, '__class__', *self._attrs) == 0
class SubSlotted(Slotted):
......@@ -80,8 +98,9 @@ class SubSlotted(Slotted):
Slotted.__init__(self, s1, s2)
self.s3 = s3
def __cmp__(self, other):
return cmpattrs(self, other, '__class__', 's1', 's2', 's3', 's4')
@property
def _attrs(self):
return ('s1', 's2', 's3', 's4')
class SubSubSlotted(SubSlotted):
......@@ -92,7 +111,6 @@ class SubSubSlotted(SubSlotted):
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()))
@property
def _attrs(self):
return ['s1', 's2', 's3', 's4'] + list(self.__dict__.keys())
......@@ -34,7 +34,8 @@ class PersistenceTest(unittest.TestCase):
self.assertEqual(obj._p_oid, None)
def test_oid_mutable_and_deletable_when_no_jar(self):
OID = '\x01' * 8
from persistent._compat import _b
OID = _b('\x01' * 8)
obj = self._makeOne()
obj._p_oid = OID
self.assertEqual(obj._p_oid, OID)
......@@ -42,7 +43,8 @@ class PersistenceTest(unittest.TestCase):
self.assertEqual(obj._p_oid, None)
def test_oid_immutable_when_in_jar(self):
OID = '\x01' * 8
from persistent._compat import _b
OID = _b('\x01' * 8)
obj = self._makeOne()
jar = self._makeJar()
jar.add(obj)
......@@ -185,9 +187,9 @@ class PersistenceTest(unittest.TestCase):
self.assertEqual(obj._p_state, GHOST)
def test_initial_serial(self):
NOSERIAL = "\000" * 8
from persistent.timestamp import _ZERO
obj = self._makeOne()
self.assertEqual(obj._p_serial, NOSERIAL)
self.assertEqual(obj._p_serial, _ZERO)
def test_setting_serial_w_invalid_types_raises(self):
# Serial must be an 8-digit string
......@@ -203,11 +205,12 @@ class PersistenceTest(unittest.TestCase):
self.assertRaises(ValueError, set, _u("01234567"))
def test_del_serial_returns_to_initial(self):
NOSERIAL = "\000" * 8
from persistent.timestamp import _ZERO
from persistent._compat import _b
obj = self._makeOne()
obj._p_serial = "01234567"
obj._p_serial = _b("01234567")
del obj._p_serial
self.assertEqual(obj._p_serial, NOSERIAL)
self.assertEqual(obj._p_serial, _ZERO)
def test_initial_mtime(self):
obj = self._makeOne()
......
......@@ -181,14 +181,14 @@ class PersistentMappingTests(unittest.TestCase):
except KeyError:
pass
else:
raise TestFailed("1 should not be poppable from u2")
self.fail("1 should not be poppable from u2")
x = u2.pop(1, 7)
eq(x, 7, "u2.pop(1, 7) == 7")
# Test popitem
items = u2.items()
items = list(u2.items())
key, value = u2.popitem()
self.failUnless((key, value) in items, "key, value in items")
self.failUnless(key not in u2, "key not in u2")
......
......@@ -19,11 +19,11 @@ class _Persistent_Base(object):
return self._getTargetClass()(*args, **kw)
def _makeJar(self):
from zope.interface import implements
from zope.interface import implementer
from persistent.interfaces import IPersistentDataManager
@implementer(IPersistentDataManager)
class _Jar(object):
implements(IPersistentDataManager)
def __init__(self):
self._loaded = []
self._registered = []
......
This diff is collapsed.
......@@ -177,23 +177,30 @@ class PersistentWeakKeyDictionaryTests(unittest.TestCase):
def test___setstate___empty(self):
from persistent.wref import WeakRef
from persistent._compat import _b
jar = _makeJar()
key = jar['key'] = _makeTarget(oid='KEY')
KEY = _b('KEY')
KEY2 = _b('KEY2')
KEY3 = _b('KEY3')
VALUE = _b('VALUE')
VALUE2 = _b('VALUE2')
VALUE3 = _b('VALUE3')
key = jar[KEY] = _makeTarget(oid=KEY)
key._p_jar = jar
kref = WeakRef(key)
value = jar['value'] = _makeTarget(oid='VALUE')
value = jar[VALUE] = _makeTarget(oid=VALUE)
value._p_jar = jar
key2 = _makeTarget(oid='KEY2')
key2 = _makeTarget(oid=KEY2)
key2._p_jar = jar # not findable
kref2 = WeakRef(key2)
del kref2._v_ob # force a miss
value2 = jar['value2'] = _makeTarget(oid='VALUE2')
value2 = jar[VALUE2] = _makeTarget(oid=VALUE2)
value2._p_jar = jar
key3 = jar['KEY3'] = _makeTarget(oid='KEY3') # findable
key3 = jar[KEY3] = _makeTarget(oid=KEY3) # findable
key3._p_jar = jar
kref3 = WeakRef(key3)
del kref3._v_ob # force a miss, but win in the lookup
value3 = jar['value3'] = _makeTarget(oid='VALUE3')
value3 = jar[VALUE3] = _makeTarget(oid=VALUE3)
value3._p_jar = jar
pwkd = self._makeOne(None)
pwkd.__setstate__({'data':
......@@ -308,6 +315,7 @@ class PersistentWeakKeyDictionaryTests(unittest.TestCase):
def _makeTarget(oid='OID', **kw):
from persistent import Persistent
from persistent._compat import _b
class Derived(Persistent):
def __hash__(self):
return hash(self._p_oid)
......@@ -318,7 +326,7 @@ def _makeTarget(oid='OID', **kw):
derived = Derived()
for k, v in kw.items():
setattr(derived, k, v)
derived._p_oid = oid
derived._p_oid = _b(oid)
return derived
def _makeJar():
......
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