[Checkins] SVN: zc.dict/trunk/ merging changes to the trunk

Satchidanand Haridas satchit at zope.com
Sun Dec 16 01:30:47 EST 2007


Log message for revision 82295:
  merging changes to the trunk
  
  

Changed:
  A   zc.dict/trunk/CHANGES.txt
  U   zc.dict/trunk/README.txt
  U   zc.dict/trunk/setup.py
  U   zc.dict/trunk/src/zc/dict/__init__.py
  A   zc.dict/trunk/src/zc/dict/ordered.py
  A   zc.dict/trunk/src/zc/dict/ordered.txt
  U   zc.dict/trunk/src/zc/dict/tests.py

-=-
Copied: zc.dict/trunk/CHANGES.txt (from rev 82294, zc.dict/branches/satchit-ordered-dict/CHANGES.txt)
===================================================================
--- zc.dict/trunk/CHANGES.txt	                        (rev 0)
+++ zc.dict/trunk/CHANGES.txt	2007-12-16 06:30:47 UTC (rev 82295)
@@ -0,0 +1,12 @@
+1.2 (unreleased)
+-----------------
+
+
+1.1 (2007-12-16)
+----------------
+
+* Added OrderedDict class that maintains the order in which items are added.
+
+
+1.1b
+----

Modified: zc.dict/trunk/README.txt
===================================================================
--- zc.dict/trunk/README.txt	2007-12-16 06:22:49 UTC (rev 82294)
+++ zc.dict/trunk/README.txt	2007-12-16 06:30:47 UTC (rev 82295)
@@ -1,5 +1,6 @@
-A BTree-based persistent dict-like object that can be used as a base class.
+BTree-based persistent dict-like objects (regular dict and ordered) that can be
+used as base classes.
 
-This is a bit of a heavyweight solution, as every zc.dict.Dict is at
-least 3 persistent objects.  Keep this in mind if you intend to create
-lots and lots of these.
+This is a bit of a heavyweight solution, as every zc.dict.Dict (and
+zc.dict.OrderedDict) is at least 3 persistent objects.  Keep this in mind if you
+intend to create lots and lots of these.

Modified: zc.dict/trunk/setup.py
===================================================================
--- zc.dict/trunk/setup.py	2007-12-16 06:22:49 UTC (rev 82294)
+++ zc.dict/trunk/setup.py	2007-12-16 06:30:47 UTC (rev 82295)
@@ -1,8 +1,11 @@
 from setuptools import setup
 
+long_description = (open("src/zc/dict/dict.txt").read() +
+                    '\n\n' +
+                    open("src/zc/dict/ordered.txt").read())
 setup(
     name="zc.dict",
-    version="1.0b1",
+    version="1.1b1",
     license="ZPL 2.1",
     author="Zope Corporation",
     author_email="zope3-dev at zope.org",
@@ -14,7 +17,7 @@
     install_requires=["setuptools", "zope.interface", "ZODB3"],
     tests_require=["zope.testing"],
     description=open('README.txt').read(),
-    long_description=open("src/zc/dict/dict.txt").read(),
+    long_description=long_description,
     keywords="zope zope3",
     zip_safe=False
     )

Modified: zc.dict/trunk/src/zc/dict/__init__.py
===================================================================
--- zc.dict/trunk/src/zc/dict/__init__.py	2007-12-16 06:22:49 UTC (rev 82294)
+++ zc.dict/trunk/src/zc/dict/__init__.py	2007-12-16 06:30:47 UTC (rev 82295)
@@ -1 +1,2 @@
 from zc.dict.dict import Dict # reexport
+from zc.dict.ordered import OrderedDict

Copied: zc.dict/trunk/src/zc/dict/ordered.py (from rev 82294, zc.dict/branches/satchit-ordered-dict/src/zc/dict/ordered.py)
===================================================================
--- zc.dict/trunk/src/zc/dict/ordered.py	                        (rev 0)
+++ zc.dict/trunk/src/zc/dict/ordered.py	2007-12-16 06:30:47 UTC (rev 82295)
@@ -0,0 +1,130 @@
+##############################################################################
+#
+# Copyright (c) 2007 Zope Corporation and Contributors.
+# All Rights Reserved.
+#
+# This software is subject to the provisions of the Zope Public License,
+# Version 2.1 (ZPL).  A copy of the ZPL should accompany this distribution.
+# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
+# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
+# FOR A PARTICULAR PURPOSE.
+#
+##############################################################################
+"""zc.dict -- A BTree based persistent mapping
+
+$Id: $
+"""
+from BTrees.OOBTree import OOBTree
+from BTrees.Length import Length
+from persistent import Persistent
+from persistent.list import PersistentList
+from types import StringTypes, TupleType, ListType
+
+class OrderedDict(Persistent):
+    """A Ordered BTree-based dict-like persistent object that can be safely
+    inherited from.
+    """
+
+    def __init__(self, dict=None, **kwargs):
+        self._order = PersistentList()
+        self._data = OOBTree()
+        self._len = Length()
+        if dict is not None:
+            self.update(dict)
+        if len(kwargs):
+            self.update(kwargs)
+
+    def keys(self):
+        return self._order[:]
+
+    def __iter__(self):
+        return iter(self.keys())
+
+    def __getitem__(self, key):
+        return self._data[key]
+
+    def values(self):
+        return [self._data[i] for i in self._order]
+
+    def __len__(self):
+        return self._len()
+
+    def items(self):
+        return [(i, self._data[i]) for i in self._order]
+
+    def __contains__(self, key): return self._data.__contains__(key)
+
+    def has_key(self, key): return bool(self._data.has_key(key))
+
+    def __setitem__(self, key, value):
+        delta = 1
+        if key in self._data:
+            delta = 0
+        self._data[key] = value
+        if delta:
+            self._order.append(key)
+            self._len.change(delta)
+
+    def __delitem__(self, key):
+        del self._data[key]
+        self._order.remove(key)
+        self._len.change(-1)
+
+    def updateOrder(self, order):
+        if not isinstance(order, ListType) and \
+            not isinstance(order, TupleType):
+            raise TypeError('order must be a tuple or a list.')
+
+        if len(order) != len(self._order):
+            raise ValueError("Incompatible key set.")
+
+        was_dict = {}
+        will_be_dict = {}
+        new_order = PersistentList()
+
+        for i in range(len(order)):
+            was_dict[self._order[i]] = 1
+            will_be_dict[order[i]] = 1
+            new_order.append(order[i])
+
+        if will_be_dict != was_dict:
+            raise ValueError("Incompatible key set.")
+
+        self._order = new_order
+
+    def update(self, other):
+        for k, v in other.iteritems():
+            self[k] = v
+
+    def clear(self):
+        self._data.clear()
+        self._order = PersistentList()
+        self._len.set(0)
+
+    def copy(self):
+        import copy
+        data = self._data
+        order = self._order
+        try:
+            self._data = OOBTree()
+            self._order = PersistentList()
+            c = copy.copy(self)
+        finally:
+            self._data = data
+            self._order = order
+        c.update(self)
+        return c
+
+    def iteritems(self):
+        return iter(self.items())
+
+    def iterkeys(self):
+        return iter(self.keys())
+
+    def itervalues(self):
+        return iter(self.values())
+
+    def get(self, key, failobj=None):
+        return self._data.get(key, failobj)
+

Copied: zc.dict/trunk/src/zc/dict/ordered.txt (from rev 82294, zc.dict/branches/satchit-ordered-dict/src/zc/dict/ordered.txt)
===================================================================
--- zc.dict/trunk/src/zc/dict/ordered.txt	                        (rev 0)
+++ zc.dict/trunk/src/zc/dict/ordered.txt	2007-12-16 06:30:47 UTC (rev 82295)
@@ -0,0 +1,96 @@
+Ordered Dict: An persistent container that maintains order
+==========================================================
+
+An OrderedDict provides most of the functionality of a Dict, with the
+additional feature that it remembers the order in which items were added.
+It also provides the API to reorder the items.
+
+   >>> from zc.dict import OrderedDict
+   >>> d = OrderedDict()
+   >>> d
+   <zc.dict.ordered.OrderedDict object at ...>
+
+Let us add a couple of items
+
+   >>> d['one'] = 'One'
+   >>> len(d)
+   1
+
+   >>> d['two'] = 'Two'
+   >>> len(d)
+   2
+
+   >>> d.keys()
+   ['one', 'two']
+
+   >>> d.values()
+   ['One', 'Two']
+
+The order can be changed easily
+
+   >>> d.updateOrder(['two', 'one'])
+   >>> d.keys()
+   ['two', 'one']
+
+   >>> d.values()
+   ['Two', 'One']
+
+
+`updateOrder` expects the entire list of keys in the new order
+
+   >>> d.updateOrder(['two'])
+   Traceback (most recent call last):
+   ...
+   ValueError: Incompatible key set.
+
+
+Length is implemented in the same way as a Dict
+
+   >>> d._len
+   <BTrees.Length.Length object at ...>
+   >>> d._len()
+   2
+
+
+OrderedDict also provides API that return iterators of the above methods.
+
+   >>> iter(d)
+   <iterator object at ...>
+   >>> d.iterkeys()
+   <iterator object at ...>
+
+   >>> d.iteritems()
+   <listiterator object at ...>
+
+   >>> d.itervalues()
+   <listiterator object at ...>
+
+
+OrderedDict also provides a copy method
+
+   >>> c = d.copy()
+   >>> c.items() == d.items()
+   True
+
+The `update` method is also provided. If it is provided with an OrderedDict,
+then the new elements are added in the same order as in the argument.
+
+   >>> d2 = OrderedDict()
+   >>> d2['five'] = 'Five'
+   >>> d2['six'] = 'Six'
+   >>> d.update(d2)
+   >>> d.items()
+   [('two', 'Two'), ('one', 'One'), ('five', 'Five'), ('six', 'Six')]
+
+
+But if the argument is a regular Dict, then the order of the newly added
+elements in the resulting OrderedDict object cannot be guaranteed.
+
+clear removes all the keys from the dict:
+
+   >>> d.clear()
+   >>> d.keys()
+   []
+   >>> len(d)
+   0
+

Modified: zc.dict/trunk/src/zc/dict/tests.py
===================================================================
--- zc.dict/trunk/src/zc/dict/tests.py	2007-12-16 06:22:49 UTC (rev 82294)
+++ zc.dict/trunk/src/zc/dict/tests.py	2007-12-16 06:30:47 UTC (rev 82295)
@@ -20,7 +20,7 @@
 
 def test_suite():
     return unittest.TestSuite([
-        doctest.DocFileSuite('dict.txt',
+        doctest.DocFileSuite('dict.txt', 'ordered.txt',
                              optionflags=doctest.INTERPRET_FOOTNOTES
                              |doctest.REPORT_NDIFF|doctest.ELLIPSIS),
         ])



More information about the Checkins mailing list