Commit f0ac08a6 authored by Jason Madden's avatar Jason Madden

Add a test checking the non-cooperative behaviour of...

Add a test checking the non-cooperative behaviour of Persistent.__getattribute__ in both C and Python.
parent 2467abc9
......@@ -23,7 +23,7 @@ try:
from persistent.cPersistence import UPTODATE
from persistent.cPersistence import CHANGED
from persistent.cPersistence import STICKY
except ImportError: #pragma NO COVER
except ImportError: # pragma: no cover
GHOST = -1
UPTODATE = 0
CHANGED = 1
......@@ -314,10 +314,10 @@ class IPersistent(Interface):
def _p_getattr(name):
"""Test whether the base class must handle the name
The method unghostifies the object, if necessary.
The method records the object access, if necessary.
This method should be called by subclass __getattribute__
implementations before doing anything else. If the method
returns True, then __getattribute__ implementations must delegate
......@@ -471,7 +471,7 @@ class IPickleCache(Interface):
""" Perform an incremental garbage collection sweep.
o Reduce number of non-ghosts to 'cache_size', if possible.
o Ghostify in LRU order.
o Skip dirty or sticky objects.
......@@ -505,7 +505,7 @@ class IPickleCache(Interface):
If the object's '_p_jar' is not None, raise.
If 'oid' is already in the cache, raise.
If 'oid' is already in the cache, raise.
"""
def reify(to_reify):
......@@ -536,7 +536,7 @@ class IPickleCache(Interface):
o Any OID corresponding to a p-class will cause the corresponding
p-class to be removed from the cache.
o For all other OIDs, ghostify the corrsponding object and
o For all other OIDs, ghostify the corrsponding object and
remove it from the ring.
"""
......
......@@ -48,7 +48,7 @@ _SWEEP_NEEDS_GC = not hasattr(sys, 'getrefcount')
# On Jython, we need to explicitly ask it to monitor
# objects if we want a more deterministic GC
if hasattr(gc, 'monitorObject'): #pragma: no cover
if hasattr(gc, 'monitorObject'): # pragma: no cover
_gc_monitor = gc.monitorObject
else:
def _gc_monitor(o):
......@@ -395,8 +395,9 @@ class PickleCache(object):
value = self.data.get(oid)
if value is not None and value._p_state != GHOST:
value._p_invalidate()
if self.ring.delete(value):
self.non_ghost_count -= 1
was_in_ring = self.ring.delete(value)
assert was_in_ring, "Ring corruption: invalidated a non-ghost not in ring"
self.non_ghost_count -= 1
elif oid in self.persistent_classes:
persistent_class = self.persistent_classes[oid]
del self.persistent_classes[oid]
......
......@@ -146,7 +146,7 @@ class _DequeRing(object):
try:
from cffi import FFI
except ImportError: #pragma: no cover
except ImportError: # pragma: no cover
_CFFIRing = None
else:
......
......@@ -692,6 +692,24 @@ class _Persistent_Base(object):
self.assertEqual(getattr(inst, 'normal', None), 'value')
self._checkMRU(jar, [OID])
def test___getattribute___non_cooperative(self):
# Getting attributes is NOT cooperative with the superclass.
# This comes from the C implementation and is maintained
# for backwards compatibility. (For example, Persistent and
# ExtensionClass.Base/Acquisition take special care to mix together.)
class Base(object):
def __getattribute__(self, name):
if name == 'magic':
return 42
return super(Base,self).__getattribute__(name)
self.assertEqual(getattr(Base(), 'magic'), 42)
class Derived(self._getTargetClass(), Base):
pass
self.assertRaises(AttributeError, getattr, Derived(), 'magic')
def test___setattr___p__names(self):
from persistent.timestamp import _makeOctets
SERIAL = _makeOctets('\x01' * 8)
......
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