Commit abbe1a2a authored by Tres Seaver's avatar Tres Seaver

Match semantics required by the 'using.rst' doctests snippets.

Those snippets now pass with both the Python and the C versions of Persistent.
parent 122d7098
......@@ -77,13 +77,16 @@ def parseTimestamp(octets):
class Persistent(object):
""" Pure Python implmentation of Persistent base class
"""
__slots__ = ('__jar', '__oid', '__serial', '__flags')
__slots__ = ('__jar', '__oid', '__serial', '__flags', '__size')
implements(IPersistent)
def __new__(cls):
inst = super(Persistent, cls).__new__(cls)
inst.__jar = inst.__oid = inst.__serial = None
inst.__jar = None
inst.__oid = None
inst.__serial = None
inst.__flags = None
inst.__size = 0
return inst
# _p_jar: see IPersistent.
......@@ -143,9 +146,11 @@ class Persistent(object):
# _p_changed: see IPersistent.
def _get_changed(self):
if self.__jar is None:
return False
if self.__flags is None: # ghost
return None
return self.__flags & _CHANGED
return bool(self.__flags & _CHANGED)
def _set_changed(self, value):
if self.__flags is None:
......@@ -173,13 +178,11 @@ class Persistent(object):
# _p_state
def _get_state(self):
if self.__jar is None:
return UPTODATE
if self.__flags is None:
if self.__jar is None:
return UPTODATE
return GHOST
if self.__flags & _CHANGED:
if self.__jar is None:
return UPTODATE
result = CHANGED
else:
result = UPTODATE
......@@ -191,10 +194,13 @@ class Persistent(object):
# _p_estimated_size: XXX don't want to reserve the space?
def _get_estimated_size(self):
return 0
return self.__size * 64
def _set_estimated_size(self, value):
pass
value = int(value)
if value < 0:
raise ValueError('_p_estimated_size must not be negative')
self.__size = _estimated_size_in_24_bits(value)
_p_estimated_size = property(_get_estimated_size, _set_estimated_size)
......@@ -245,19 +251,22 @@ class Persistent(object):
def __setattr__(self, name, value):
special_name = (name.startswith('_Persistent__') or
name.startswith('_p_'))
volatile = name.startswith('_v_')
if not special_name:
if _OGA(self, '_Persistent__flags') is None:
_OGA(self, '_p_activate')()
_OGA(self, '_p_accessed')()
if not volatile:
_OGA(self, '_p_accessed')()
_OSA(self, name, value)
if not special_name:
if (_OGA(self, '_Persistent__jar') is not None and
_OGA(self, '_Persistent__oid') is not None and
not special_name and
not volatile):
before = _OGA(self, '_Persistent__flags')
after = before | _CHANGED
if before != after:
_OSA(self, '_Persistent__flags', after)
if (_OGA(self, '_Persistent__jar') is not None and
_OGA(self, '_Persistent__oid') is not None):
_OGA(self, '_p_register')()
_OGA(self, '_p_register')()
def __delattr__(self, name):
special_name = (name.startswith('_Persistent__') or
......@@ -320,12 +329,13 @@ class Persistent(object):
def _p_invalidate(self):
""" See IPersistent.
"""
if self.__flags is not None and self.__flags & _STICKY:
raise ValueError('Sticky')
self.__flags = None
idict = getattr(self, '__dict__', None)
if idict is not None:
idict.clear()
if self.__jar is not None:
if self.__flags is not None and self.__flags & _STICKY:
raise ValueError('Sticky')
self.__flags = None
idict = getattr(self, '__dict__', None)
if idict is not None:
idict.clear()
def _p_getattr(self, name):
""" See IPersistent.
......@@ -379,3 +389,8 @@ class Persistent(object):
# the cache on the persistent object.
if self.__jar is not None and self.__oid is not None:
self.__jar._cache.mru(self.__oid)
def _estimated_size_in_24_bits(value):
if value > 1073741696:
return 16777215
return (value//64) + 1
......@@ -73,7 +73,7 @@ class PersistentTests(unittest.TestCase):
self.assertEqual(inst._p_jar, None)
self.assertEqual(inst._p_oid, None)
self.assertEqual(inst._p_serial, _INITIAL_SERIAL)
self.assertEqual(inst._p_changed, None)
self.assertEqual(inst._p_changed, False)
self.assertEqual(inst._p_sticky, False)
self.assertEqual(inst._p_status, 'unsaved')
......@@ -188,13 +188,24 @@ class PersistentTests(unittest.TestCase):
del(inst._p_serial)
self.assertEqual(inst._p_serial, _INITIAL_SERIAL)
def test_query_p_changed(self):
def test_query_p_changed_unsaved(self):
inst = self._makeOne()
self.assertEqual(inst._p_changed, False)
def test_query_p_changed_ghost(self):
inst, jar, OID = self._makeOneWithJar()
self.assertEqual(inst._p_changed, None)
def test_query_p_changed_saved(self):
inst, jar, OID = self._makeOneWithJar()
inst._p_activate()
self.assertEqual(inst._p_changed, False)
def test_query_p_changed_changed(self):
inst, jar, OID = self._makeOneWithJar()
inst._p_activate()
inst._p_changed = True
self.assertEqual(inst._p_changed, True)
inst._p_changed = False
self.assertEqual(inst._p_changed, False)
def test_assign_p_changed_none_from_unsaved(self):
inst = self._makeOne()
......@@ -305,6 +316,15 @@ class PersistentTests(unittest.TestCase):
del inst._p_changed
self.assertEqual(inst._p_status, 'unsaved')
def test_delete_p_changed_from_unsaved_w_dict(self):
class Derived(self._getTargetClass()):
pass
inst = Derived()
inst.foo = 'bar'
del inst._p_changed
self.assertEqual(inst._p_status, 'unsaved')
self.assertEqual(inst.foo, 'bar')
def test_delete_p_changed_from_ghost(self):
inst, jar, OID = self._makeOneWithJar()
del inst._p_changed
......@@ -409,10 +429,6 @@ class PersistentTests(unittest.TestCase):
inst._p_serial = ts.raw()
self.assertEqual(inst._p_mtime, ts.timeTime())
def test__p_state_new(self):
inst = self._makeOne()
self.assertEqual(inst._p_state, 0)
def test__p_state_unsaved(self):
inst = self._makeOne()
inst._p_changed = True
......@@ -446,15 +462,20 @@ class PersistentTests(unittest.TestCase):
inst._p_sticky = True
self.assertEqual(inst._p_state, 2)
def test_query_p_estimated_size(self):
def test_query_p_estimated_size_new(self):
inst = self._makeOne()
self.assertEqual(inst._p_estimated_size, 0)
def test_assign_p_estimated_size_negative(self):
inst = self._makeOne()
def _test():
inst._p_estimated_size = -1
self.assertRaises(ValueError, _test)
def test_assign_p_estimated_size(self):
# XXX at the moment, we don't store this value.
inst = self._makeOne()
inst._p_estimated_size = 123
self.assertEqual(inst._p_estimated_size, 0)
self.assertEqual(inst._p_estimated_size, 128)
def test___getattribute___p__names(self):
NAMES = ['_p_jar',
......@@ -529,12 +550,22 @@ class PersistentTests(unittest.TestCase):
setattr(inst, name, value)
self.assertEqual(jar._cache._mru, [])
def test___setattr___v__name(self):
class Derived(self._getTargetClass()):
pass
inst, jar, OID = self._makeOneWithJar(Derived)
jar._cache._mru = []
inst._v_foo = 'bar'
self.assertEqual(inst._p_status, 'saved')
self.assertEqual(jar._cache._mru, [])
def test___setattr__normal_name_from_unsaved(self):
class Derived(self._getTargetClass()):
normal = 'before'
inst = Derived()
setattr(inst, 'normal', 'after')
self.assertEqual(getattr(inst, 'normal', None), 'after')
self.assertEqual(inst._p_status, 'unsaved')
def test___setattr__normal_name_from_ghost(self):
class Derived(self._getTargetClass()):
......@@ -545,6 +576,7 @@ class PersistentTests(unittest.TestCase):
self.assertEqual(jar._cache._mru, [OID])
self.assertEqual(jar._registered, [OID])
self.assertEqual(getattr(inst, 'normal', None), 'after')
self.assertEqual(inst._p_status, 'changed')
def test___setattr__normal_name_from_saved(self):
class Derived(self._getTargetClass()):
......@@ -556,6 +588,7 @@ class PersistentTests(unittest.TestCase):
self.assertEqual(jar._cache._mru, [OID])
self.assertEqual(jar._registered, [OID])
self.assertEqual(getattr(inst, 'normal', None), 'after')
self.assertEqual(inst._p_status, 'changed')
def test___setattr__normal_name_from_changed(self):
class Derived(self._getTargetClass()):
......@@ -568,6 +601,7 @@ class PersistentTests(unittest.TestCase):
self.assertEqual(jar._cache._mru, [OID])
self.assertEqual(jar._registered, [])
self.assertEqual(getattr(inst, 'normal', None), 'after')
self.assertEqual(inst._p_status, 'changed')
def test___delattr___p__names(self):
NAMES = ['_p_changed',
......@@ -655,7 +689,7 @@ class PersistentTests(unittest.TestCase):
self.assertEqual(inst._p_jar, None)
self.assertEqual(inst._p_oid, None)
self.assertEqual(inst._p_serial, _INITIAL_SERIAL)
self.assertEqual(inst._p_changed, None)
self.assertEqual(inst._p_changed, False)
self.assertEqual(inst._p_sticky, False)
def test___setstate___nonempty_derived_w_dict(self):
......@@ -805,7 +839,7 @@ class PersistentTests(unittest.TestCase):
inst = Derived()
inst._p_invalidate()
self.assertEqual(inst._p_status, 'unsaved')
self.assertEqual(inst.__dict__, {})
self.assertEqual(inst.__dict__, {'normal': 'after'})
def test__p_invalidate_from_ghost(self):
inst, jar, OID = self._makeOneWithJar()
......
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