[Checkins] SVN: zope.app.container/trunk/ - Added an
``IBTreeContainer`` interface that allows an argument to the
Fred L. Drake, Jr.
fdrake at gmail.com
Tue Apr 15 22:10:56 EDT 2008
Log message for revision 85414:
- Added an ``IBTreeContainer`` interface that allows an argument to the
``items``, ``keys``, and ``values`` methods with the same semantics as for
a BTree object. The extended interface is implemented by the
``BTreeContainer`` class.
Changed:
U zope.app.container/trunk/CHANGES.txt
U zope.app.container/trunk/src/zope/app/container/btree.py
U zope.app.container/trunk/src/zope/app/container/interfaces.py
U zope.app.container/trunk/src/zope/app/container/tests/test_btree.py
-=-
Modified: zope.app.container/trunk/CHANGES.txt
===================================================================
--- zope.app.container/trunk/CHANGES.txt 2008-04-16 01:30:16 UTC (rev 85413)
+++ zope.app.container/trunk/CHANGES.txt 2008-04-16 02:10:55 UTC (rev 85414)
@@ -2,6 +2,14 @@
CHANGES
=======
+3.6.0 (unreleased)
+------------------
+
+- Added an ``IBTreeContainer`` interface that allows an argument to the
+ ``items``, ``keys``, and ``values`` methods with the same semantics as for
+ a BTree object. The extended interface is implemented by the
+ ``BTreeContainer`` class.
+
3.5.3 (2007-11-09)
------------------
Modified: zope.app.container/trunk/src/zope/app/container/btree.py
===================================================================
--- zope.app.container/trunk/src/zope/app/container/btree.py 2008-04-16 01:30:16 UTC (rev 85413)
+++ zope.app.container/trunk/src/zope/app/container/btree.py 2008-04-16 02:10:55 UTC (rev 85414)
@@ -26,12 +26,15 @@
from BTrees.OOBTree import OOBTree
from BTrees.Length import Length
+from zope.app.container.interfaces import IBTreeContainer
from zope.app.container.sample import SampleContainer
from zope.cachedescriptors.property import Lazy
+from zope.interface import implements
+
class BTreeContainer(SampleContainer, Persistent):
- # implements(what my base classes implement)
+ implements(IBTreeContainer)
# TODO: It appears that BTreeContainer uses SampleContainer only to
# get the implementation of __setitem__(). All the other methods
@@ -99,3 +102,21 @@
l.change(-1)
has_key = __contains__
+
+ def items(self, key=None):
+ if key is None:
+ return super(BTreeContainer, self).items()
+ else:
+ return self._SampleContainer__data.items(key)
+
+ def keys(self, key=None):
+ if key is None:
+ return super(BTreeContainer, self).keys()
+ else:
+ return self._SampleContainer__data.keys(key)
+
+ def values(self, key=None):
+ if key is None:
+ return super(BTreeContainer, self).values()
+ else:
+ return self._SampleContainer__data.values(key)
Modified: zope.app.container/trunk/src/zope/app/container/interfaces.py
===================================================================
--- zope.app.container/trunk/src/zope/app/container/interfaces.py 2008-04-16 01:30:16 UTC (rev 85413)
+++ zope.app.container/trunk/src/zope/app/container/interfaces.py 2008-04-16 02:10:55 UTC (rev 85414)
@@ -137,6 +137,46 @@
"""Readable and writable content container."""
+class IBTreeContainer(IContainer):
+ """Container that supports BTree semantics for some methods."""
+
+ def items(key=None):
+ """Return an iterator over the key-value pairs in the container.
+
+ If ``None`` is passed as `key`, this method behaves as if no argument
+ were passed; exactly as required for ``IContainer.items()``.
+
+ If `key` is in the container, the first item provided by the iterator
+ will correspond to that key. Otherwise, the first item will be for
+ the key that would come next if `key` were in the container.
+
+ """
+
+ def keys(key=None):
+ """Return an iterator over the keys in the container.
+
+ If ``None`` is passed as `key`, this method behaves as if no argument
+ were passed; exactly as required for ``IContainer.keys()``.
+
+ If `key` is in the container, the first key provided by the iterator
+ will be that key. Otherwise, the first key will be the one that would
+ come next if `key` were in the container.
+
+ """
+
+ def values(key=None):
+ """Return an iterator over the values in the container.
+
+ If ``None`` is passed as `key`, this method behaves as if no argument
+ were passed; exactly as required for ``IContainer.values()``.
+
+ If `key` is in the container, the first value provided by the iterator
+ will correspond to that key. Otherwise, the first value will be for
+ the key that would come next if `key` were in the container.
+
+ """
+
+
class IOrderedContainer(IContainer):
"""Containers whose contents are maintained in order."""
Modified: zope.app.container/trunk/src/zope/app/container/tests/test_btree.py
===================================================================
--- zope.app.container/trunk/src/zope/app/container/tests/test_btree.py 2008-04-16 01:30:16 UTC (rev 85413)
+++ zope.app.container/trunk/src/zope/app/container/tests/test_btree.py 2008-04-16 02:10:55 UTC (rev 85414)
@@ -16,18 +16,22 @@
$Id$
"""
from unittest import TestCase, main, makeSuite, TestSuite
+from zope.interface.verify import verifyObject
from zope.testing.doctestunit import DocTestSuite
from zope.app.testing import placelesssetup
from test_icontainer import TestSampleContainer
from zope.app.container.btree import BTreeContainer
+from zope.app.container.interfaces import IBTreeContainer
+
class TestBTreeContainer(TestSampleContainer, TestCase):
def makeTestObject(self):
return BTreeContainer()
-class TestBTreeLength(TestCase):
+class TestBTreeSpecials(TestCase):
+
def testStoredLength(self):
# This is lazy for backward compatibility. If the len is not
# stored already we set it to the length of the underlying
@@ -40,11 +44,118 @@
self.assertEqual(len(bc), 1)
self.assertEqual(bc.__dict__['_BTreeContainer__len'](), 1)
+ # The tests which follow test the additional signatures and declarations
+ # for the BTreeContainer that allow it to provide the IBTreeContainer
+ # interface.
+ def testBTreeContainerInterface(self):
+ bc = BTreeContainer()
+ self.assert_(verifyObject(IBTreeContainer, bc))
+ self.checkIterable(bc.items())
+ self.checkIterable(bc.keys())
+ self.checkIterable(bc.values())
+
+ def testEmptyItemsWithArg(self):
+ bc = BTreeContainer()
+ self.assertEqual(list(bc.items(None)), list(bc.items()))
+ self.assertEqual(list(bc.items("")), [])
+ self.assertEqual(list(bc.items("not-there")), [])
+ self.checkIterable(bc.items(None))
+ self.checkIterable(bc.items(""))
+ self.checkIterable(bc.items("not-there"))
+
+ def testEmptyKeysWithArg(self):
+ bc = BTreeContainer()
+ self.assertEqual(list(bc.keys(None)), list(bc.keys()))
+ self.assertEqual(list(bc.keys("")), [])
+ self.assertEqual(list(bc.keys("not-there")), [])
+ self.checkIterable(bc.keys(None))
+ self.checkIterable(bc.keys(""))
+ self.checkIterable(bc.keys("not-there"))
+
+ def testEmptyValuesWithArg(self):
+ bc = BTreeContainer()
+ self.assertEqual(list(bc.values(None)), list(bc.values()))
+ self.assertEqual(list(bc.values("")), [])
+ self.assertEqual(list(bc.values("not-there")), [])
+ self.checkIterable(bc.values(None))
+ self.checkIterable(bc.values(""))
+ self.checkIterable(bc.values("not-there"))
+
+ def testNonemptyItemsWithArg(self):
+ bc = BTreeContainer()
+ bc["0"] = 1
+ bc["1"] = 2
+ bc["2"] = 3
+ self.assertEqual(list(bc.items(None)), list(bc.items()))
+ self.assertEqual(list(bc.items("")), [("0", 1), ("1", 2), ("2", 3)])
+ self.assertEqual(list(bc.items("3")), [])
+ self.assertEqual(list(bc.items("2.")), [])
+ self.assertEqual(list(bc.items("2")), [("2", 3)])
+ self.assertEqual(list(bc.items("1.")), [("2", 3)])
+ self.assertEqual(list(bc.items("1")), [("1", 2), ("2", 3)])
+ self.assertEqual(list(bc.items("0.")), [("1", 2), ("2", 3)])
+ self.assertEqual(list(bc.items("0")), [("0", 1), ("1", 2), ("2", 3)])
+ self.checkIterable(bc.items(None))
+ self.checkIterable(bc.items(""))
+ self.checkIterable(bc.items("0."))
+ self.checkIterable(bc.items("3"))
+
+ def testNonemptyKeysWithArg(self):
+ bc = BTreeContainer()
+ bc["0"] = 1
+ bc["1"] = 2
+ bc["2"] = 3
+ self.assertEqual(list(bc.keys(None)), list(bc.keys()))
+ self.assertEqual(list(bc.keys("")), ["0", "1", "2"])
+ self.assertEqual(list(bc.keys("3")), [])
+ self.assertEqual(list(bc.keys("2.")), [])
+ self.assertEqual(list(bc.keys("2")), ["2"])
+ self.assertEqual(list(bc.keys("1.")), ["2"])
+ self.assertEqual(list(bc.keys("1")), ["1", "2"])
+ self.assertEqual(list(bc.keys("0.")), ["1", "2"])
+ self.assertEqual(list(bc.keys("0")), ["0", "1", "2"])
+ self.checkIterable(bc.keys(None))
+ self.checkIterable(bc.keys(""))
+ self.checkIterable(bc.keys("0."))
+ self.checkIterable(bc.keys("3"))
+
+ def testNonemptyValueWithArg(self):
+ bc = BTreeContainer()
+ bc["0"] = 1
+ bc["1"] = 2
+ bc["2"] = 3
+ self.assertEqual(list(bc.values(None)), list(bc.values()))
+ self.assertEqual(list(bc.values("")), [1, 2, 3])
+ self.assertEqual(list(bc.values("3")), [])
+ self.assertEqual(list(bc.values("2.")), [])
+ self.assertEqual(list(bc.values("2")), [3])
+ self.assertEqual(list(bc.values("1.")), [3])
+ self.assertEqual(list(bc.values("1")), [2, 3])
+ self.assertEqual(list(bc.values("0.")), [2, 3])
+ self.assertEqual(list(bc.values("0")), [1, 2, 3])
+ self.checkIterable(bc.values(None))
+ self.checkIterable(bc.values(""))
+ self.checkIterable(bc.values("0."))
+ self.checkIterable(bc.values("3"))
+
+ def checkIterable(self, iterable):
+ it = iter(iterable)
+ self.assert_(callable(it.next))
+ self.assert_(callable(it.__iter__))
+ self.assert_(iter(it) is it)
+ # Exhaust the iterator:
+ first_time = list(it)
+ self.assertRaises(StopIteration, it.next)
+ # Subsequent iterations will return the same values:
+ self.assertEqual(list(iterable), first_time)
+ self.assertEqual(list(iterable), first_time)
+
+
def test_suite():
return TestSuite((
makeSuite(TestBTreeContainer),
- makeSuite(TestBTreeLength),
+ makeSuite(TestBTreeSpecials),
DocTestSuite('zope.app.container.btree',
setUp=placelesssetup.setUp,
tearDown=placelesssetup.tearDown),
More information about the Checkins
mailing list