Commit d882d96d authored by Christophe Combelles's avatar Christophe Combelles

- Fixed bug #175388 : the setitem's size modification is now done in setitemf:

    setting an existing item does not change the size,
    and the event subscribers should see the new size instead of the old size.
- Reimplemented the BTreeContainer so that it directly accesses the btree
  methods (removed the #TODO)
parent fe1a94fd
...@@ -11,7 +11,11 @@ CHANGES ...@@ -11,7 +11,11 @@ CHANGES
- prevent the namechooser from failing on '+', '@' and '/' - prevent the namechooser from failing on '+', '@' and '/'
- added tests in the namechooser - added tests in the namechooser
- be sure the name chooser returns unicode - be sure the name chooser returns unicode
- fixed #175388 : the setitem's size modification is now done in setitemf:
setting an existing item does not change the size,
and the event subscribers should see the new size instead of the old size.
- Reimplemented the BTreeContainer so that it directly accesses the btree
methods (removed an old #TODO)
3.6.0 (2008-05-06) 3.6.0 (2008-05-06)
------------------ ------------------
......
...@@ -27,23 +27,17 @@ from BTrees.OOBTree import OOBTree ...@@ -27,23 +27,17 @@ from BTrees.OOBTree import OOBTree
from BTrees.Length import Length from BTrees.Length import Length
from zope.app.container.interfaces import IBTreeContainer from zope.app.container.interfaces import IBTreeContainer
from zope.app.container.sample import SampleContainer from zope.app.container.contained import Contained, setitem, uncontained
from zope.cachedescriptors.property import Lazy from zope.cachedescriptors.property import Lazy
from zope.interface import implements from zope.interface import implements
class BTreeContainer(SampleContainer, Persistent): class BTreeContainer(Contained, Persistent):
implements(IBTreeContainer) implements(IBTreeContainer)
# TODO: It appears that BTreeContainer uses SampleContainer only to
# get the implementation of __setitem__(). All the other methods
# provided by that base class are just slower replacements for
# operations on the BTree itself. It would probably be clearer to
# just delegate those methods directly to the btree.
def __init__(self): def __init__(self):
super(BTreeContainer, self).__init__() self.__data = self._newContainerData()
self.__len = Length() self.__len = Length()
def _newContainerData(self): def _newContainerData(self):
...@@ -53,15 +47,13 @@ class BTreeContainer(SampleContainer, Persistent): ...@@ -53,15 +47,13 @@ class BTreeContainer(SampleContainer, Persistent):
The value returned is a mapping object that also has get, The value returned is a mapping object that also has get,
has_key, keys, items, and values methods. has_key, keys, items, and values methods.
The default implementation uses an OOBTree.
""" """
return OOBTree() return OOBTree()
def __contains__(self, key): def __contains__(self, key):
'''See interface IReadContainer '''See interface IReadContainer
Reimplement this method, since has_key() returns the key if available,
while we expect True or False.
>>> c = BTreeContainer() >>> c = BTreeContainer()
>>> "a" in c >>> "a" in c
False False
...@@ -71,51 +63,54 @@ class BTreeContainer(SampleContainer, Persistent): ...@@ -71,51 +63,54 @@ class BTreeContainer(SampleContainer, Persistent):
>>> "A" in c >>> "A" in c
False False
''' '''
return key in self._SampleContainer__data return key in self.__data
@Lazy @Lazy
def _BTreeContainer__len(self): def _BTreeContainer__len(self):
import logging
log = logging.getLogger('zope.app.container.btree')
l = Length() l = Length()
ol = super(BTreeContainer, self).__len__() ol = len(self.__data)
if ol > 0: if ol > 0:
l.change(ol) l.change(ol)
self._p_changed = True self._p_changed = True
log.info("Storing length of %r" % self)
return l return l
def __len__(self): def __len__(self):
return self.__len() return self.__len()
def __setitem__(self, key, value): def _setitemf(self, key, value):
# make sure our lazy property gets set # make sure our lazy property gets set
l = self.__len l = self.__len
super(BTreeContainer, self).__setitem__(key, value) self.__data[key] = value
l.change(1) l.change(1)
def __iter__(self):
return iter(self.__data)
def __getitem__(self, key):
'''See interface `IReadContainer`'''
return self.__data[key]
def get(self, key, default=None):
'''See interface `IReadContainer`'''
return self.__data.get(key, default)
def __setitem__(self, key, value):
setitem(self, self._setitemf, key, value)
def __delitem__(self, key): def __delitem__(self, key):
# make sure our lazy property gets set # make sure our lazy property gets set
l = self.__len l = self.__len
super(BTreeContainer, self).__delitem__(key) uncontained(self.__data[key], self, key)
del self.__data[key]
l.change(-1) l.change(-1)
has_key = __contains__ has_key = __contains__
def items(self, key=None): def items(self, key=None):
if key is None: return self.__data.items(key)
return super(BTreeContainer, self).items()
else:
return self._SampleContainer__data.items(key)
def keys(self, key=None): def keys(self, key=None):
if key is None: return self.__data.keys(key)
return super(BTreeContainer, self).keys()
else:
return self._SampleContainer__data.keys(key)
def values(self, key=None): def values(self, key=None):
if key is None: return self.__data.values(key)
return super(BTreeContainer, self).values()
else:
return self._SampleContainer__data.values(key)
...@@ -139,6 +139,18 @@ class TestBTreeSpecials(TestCase): ...@@ -139,6 +139,18 @@ class TestBTreeSpecials(TestCase):
self.checkIterable(bc.values("0.")) self.checkIterable(bc.values("0."))
self.checkIterable(bc.values("3")) self.checkIterable(bc.values("3"))
def testCorrectLengthWhenAddingExistingItem(self):
"""
for bug #175388
"""
bc = BTreeContainer()
bc[u'x'] = object()
self.assertEqual(len(bc), 1)
bc[u'x'] = bc[u'x']
self.assertEqual(len(bc), 1)
self.assertEqual(list(bc), [u'x'])
def checkIterable(self, iterable): def checkIterable(self, iterable):
it = iter(iterable) it = iter(iterable)
self.assert_(callable(it.next)) self.assert_(callable(it.next))
......
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