[Checkins] SVN: zc.dict/trunk/ two bug fixes and an improvement to ``update``s behavior. want to update ordered dict before I make a release.

Gary Poster gary at zope.com
Tue Mar 4 20:28:51 EST 2008


Log message for revision 84469:
  two bug fixes and an improvement to ``update``s behavior.  want to update ordered dict before I make a release.

Changed:
  _U  zc.dict/trunk/
  U   zc.dict/trunk/README.txt
  D   zc.dict/trunk/bootstrap.py
  U   zc.dict/trunk/setup.py
  U   zc.dict/trunk/src/zc/dict/dict.py
  U   zc.dict/trunk/src/zc/dict/dict.txt
  U   zc.dict/trunk/src/zc/dict/ordered.txt

-=-

Property changes on: zc.dict/trunk
___________________________________________________________________
Name: svn:externals
   + bootstrap svn://svn.zope.org/repos/main/zc.buildout/trunk/bootstrap


Modified: zc.dict/trunk/README.txt
===================================================================
--- zc.dict/trunk/README.txt	2008-03-05 01:10:40 UTC (rev 84468)
+++ zc.dict/trunk/README.txt	2008-03-05 01:28:50 UTC (rev 84469)
@@ -2,5 +2,8 @@
 used as base classes.
 
 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.
+zc.dict.OrderedDict) is at least 3 persistent objects.  Keep this in
+mind if you intend to create lots and lots of these.
+
+To build, run ``python bootstrap/bootstrap.py`` and then ``bin/buildout``
+from this directory.  A clean, non-system Python is strongly recommended.

Deleted: zc.dict/trunk/bootstrap.py
===================================================================
--- zc.dict/trunk/bootstrap.py	2008-03-05 01:10:40 UTC (rev 84468)
+++ zc.dict/trunk/bootstrap.py	2008-03-05 01:28:50 UTC (rev 84469)
@@ -1,52 +0,0 @@
-##############################################################################
-#
-# Copyright (c) 2006 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.
-#
-##############################################################################
-"""Bootstrap a buildout-based project
-
-Simply run this script in a directory containing a buildout.cfg.
-The script accepts buildout command-line options, so you can
-use the -c option to specify an alternate configuration file.
-
-$Id$
-"""
-
-import os, shutil, sys, tempfile, urllib2
-
-tmpeggs = tempfile.mkdtemp()
-
-ez = {}
-exec urllib2.urlopen('http://peak.telecommunity.com/dist/ez_setup.py'
-                     ).read() in ez
-ez['use_setuptools'](to_dir=tmpeggs, download_delay=0)
-
-import pkg_resources
-
-cmd = 'from setuptools.command.easy_install import main; main()'
-if sys.platform == 'win32':
-    cmd = '"%s"' % cmd # work around spawn lamosity on windows
-
-ws = pkg_resources.working_set
-assert os.spawnle(
-    os.P_WAIT, sys.executable, sys.executable,
-    '-c', cmd, '-mqNxd', tmpeggs, 'zc.buildout',
-    dict(os.environ,
-         PYTHONPATH=
-         ws.find(pkg_resources.Requirement.parse('setuptools')).location
-         ),
-    ) == 0
-
-ws.add_entry(tmpeggs)
-ws.require('zc.buildout')
-import zc.buildout.buildout
-zc.buildout.buildout.main(sys.argv[1:] + ['bootstrap'])
-shutil.rmtree(tmpeggs)

Modified: zc.dict/trunk/setup.py
===================================================================
--- zc.dict/trunk/setup.py	2008-03-05 01:10:40 UTC (rev 84468)
+++ zc.dict/trunk/setup.py	2008-03-05 01:28:50 UTC (rev 84469)
@@ -5,7 +5,7 @@
                     open("src/zc/dict/ordered.txt").read())
 setup(
     name="zc.dict",
-    version="1.1b1",
+    version="1.1",
     license="ZPL 2.1",
     author="Zope Corporation",
     author_email="zope3-dev at zope.org",

Modified: zc.dict/trunk/src/zc/dict/dict.py
===================================================================
--- zc.dict/trunk/src/zc/dict/dict.py	2008-03-05 01:10:40 UTC (rev 84468)
+++ zc.dict/trunk/src/zc/dict/dict.py	2008-03-05 01:28:50 UTC (rev 84469)
@@ -45,10 +45,44 @@
         del self._data[key]
         self._len.change(-1)
 
-    def update(self, other):
-        for k, v in other.iteritems():
+    def update(self, *args, **kwargs):
+        if args:
+            if len(args) > 1:
+                raise TypeError(
+                    'update expected at most 1 arguments, got %d' %
+                    (len(args),))
+            if getattr(args[0], 'keys', None):
+                for k in args[0].keys():
+                    self[k] = args[0][k]
+            else:
+                for k, v in args[0]:
+                    self[k] = v
+        for k, v in kwargs.items():
             self[k] = v
 
+    def setdefault(self, key, failobj=None):
+        # we can't use BTree's setdefault because then we don't know to
+        # increment _len
+        try:
+            res = self._data[key]
+        except KeyError:
+            res = failobj
+            self._data[key] = res
+            self._len.change(1)
+        return res
+
+    def pop(self, key, *args):
+        try:
+            res = self._data.pop(key)
+        except KeyError:
+            if args:
+                res = args[0]
+            else:
+                raise
+        else:
+            self._len.change(-1)
+        return res
+
     def clear(self):
         self._data.clear()
         self._len.set(0)
@@ -85,8 +119,6 @@
     def itervalues(self): return self._data.itervalues()
     def has_key(self, key): return bool(self._data.has_key(key))
     def get(self, key, failobj=None): return self._data.get(key, failobj)
-    def setdefault(self, key, failobj=None): self._data.setdefault(key, failobj)
-    def pop(self, key, *args): return self._data.pop(key, *args)
     def __contains__(self, key): return self._data.__contains__(key)
 
     def popitem(self):

Modified: zc.dict/trunk/src/zc/dict/dict.txt
===================================================================
--- zc.dict/trunk/src/zc/dict/dict.txt	2008-03-05 01:10:40 UTC (rev 84468)
+++ zc.dict/trunk/src/zc/dict/dict.txt	2008-03-05 01:28:50 UTC (rev 84469)
@@ -8,119 +8,174 @@
 efficiency of BTrees and is safe to use as a base class.  Also, it
 implements the full Python dict interface.
 
-   >>> from zc.dict import Dict
-   >>> d = Dict()
-   >>> d
-   <zc.dict.dict.Dict object at ...>
+    >>> from zc.dict import Dict
+    >>> d = Dict()
+    >>> d
+    <zc.dict.dict.Dict object at ...>
+ 
+    >>> d['foo'] = 'bar'
+    >>> len(d)
+    1
+ 
+    >>> d['bar'] = 'baz'
+    >>> len(d)
+    2
 
-   >>> d['foo'] = 'bar'
-   >>> len(d)
-   1
+Note that an important difference between the Python dict and this Dict is
+that the Python dict uses hashes, and this uses BTree comparisons.
+Practically, this means that your keys should be of homogenous types.
+We use strings in these examples.
 
-   >>> d['bar'] = 'baz'
-   >>> len(d)
-   2
+Length is maintained separately, because len on a BTree is inefficient,
+as it has to wake up all buckets in the tree from the database.
 
-Length is maintained separately, because len on a BTree is
-inefficient, as it has to walk the whole tree.
+    >>> d._len
+    <BTrees.Length.Length object at ...>
+    >>> d._len()
+    2
 
-   >>> d._len
-   <BTrees.Length.Length object at ...>
-   >>> d._len()
-   2
-
 In order to keep updates efficient for small changes, we unroll them
 as a series of setitems.
 
-   >>> d.update({'bar': 'moo', 'ding': 'dong', 'beep': 'beep'})
-   >>> len(d)
-   4
+    >>> d.update({'bar': 'moo', 'ding': 'dong', 'beep': 'beep'})
+    >>> len(d)
+    4
 
-keys and values, and items return normal Python lists:
+The Dict supports the full ``update`` interface.
 
-   >>> d.keys()
-   ['bar', 'beep', 'ding', 'foo']
+    >>> d.update([['sha', 'zam'], ['ka', 'pow']])
+    >>> len(d)
+    6
+    >>> d['ka']
+    'pow'
+    >>> d.update(left='hook', right='jab')
+    >>> len(d)
+    8
+    >>> d['left']
+    'hook'
 
-   >>> d.values()
-   ['moo', 'beep', 'dong', 'bar']
+``pop`` needs to update the length.
 
-   >>> d.items()
-   [('bar', 'moo'), ('beep', 'beep'), ('ding', 'dong'), ('foo', 'bar')]
+    >>> d.pop('sha')
+    'zam'
+    >>> d.pop('ka')
+    'pow'
+    >>> d.pop('left')
+    'hook'
+    >>> d.pop('right')
+    'jab'
+    >>> len(d)
+    4
 
-However, efficient BTree iterators are available via the iter methods:
+...except when it doesn't.
 
-   >>> iter(d)
-   <OO-iterator object at ...>
-   >>> d.iterkeys()
-   <OO-iterator object at ...>
+    >>> d.pop('nonexistent')
+    Traceback (most recent call last):
+    ...
+    KeyError: 'nonexistent'
+    >>> d.pop('nonexistent', 42)
+    42
+    >>> len(d)
+    4
 
-   >>> d.iteritems()
-   <OO-iterator object at ...>
+``setdefault`` also sometimes needs to update the length.
 
-   >>> d.itervalues()
-   <OO-iterator object at ...>
+    >>> len(d)
+    4
+    >>> d.setdefault('newly created', 'value')
+    'value'
+    >>> d['newly created']
+    'value'
+    >>> len(d)
+    5
 
-The rest of the dict methods are delegated to the underlying BTree:
+    >>> d.setdefault('newly created', 'other')
+    'value'
+    >>> d['newly created']
+    'value'
+    >>> len(d)
+    5
 
-   >>> d.has_key('bar')
-   True
-   >>> 'BAR' in d
-   False
+    >>> del d['newly created'] # set things back to the way they were...
 
-   >>> d.pop('bar')
-   'moo'
+``keys``, ``values`` and ``items`` return normal Python lists.  Because of
+the underlying BTree, these are always in sort order of the keys.
 
-   >>> d.get('nonexistent', 'default')
-   'default'
+    >>> d.keys()
+    ['bar', 'beep', 'ding', 'foo']
+ 
+    >>> d.values()
+    ['moo', 'beep', 'dong', 'bar']
+ 
+    >>> d.items()
+    [('bar', 'moo'), ('beep', 'beep'), ('ding', 'dong'), ('foo', 'bar')]
 
-   >>> d.setdefault('newly created', 'value')
-   >>> d['newly created']
-   'value'
-   >>> d.setdefault('newly created', 'other')
-   >>> d['newly created']
-   'value'
+However, efficient BTree iterators are available via the iter methods:
 
+    >>> iter(d)
+    <OO-iterator object at ...>
+    >>> d.iterkeys()
+    <OO-iterator object at ...>
+ 
+    >>> d.iteritems()
+    <OO-iterator object at ...>
+ 
+    >>> d.itervalues()
+    <OO-iterator object at ...>
+
 popitem removes from the dict and returns a key-value pair:
 
-   >>> len(d)
-   4
+    >>> len(d)
+    4
+ 
+    >>> d.popitem()
+    ('bar', 'moo')
+ 
+    >>> len(d)
+    3
 
-   >>> d.popitem()
-   ('beep', 'beep')
-
-   >>> len(d)
-   3
-
 The copy method creates a copy of a Dict:
 
-   >>> c = d.copy()
-   >>> c.items() == d.items()
-   True
+    >>> c = d.copy()
+    >>> c.items() == d.items()
+    True
 
-However we don't support comparison because of cowardice:
+However we don't support comparison, except for identity, because of
+cowardice:
 
-   >>> c == d
-   False
-   >>> Dict() == {}
-   False
+    >>> c == d
+    False
+    >>> Dict() == {}
+    False
+    >>> d == d
+    True
 
 clear removes all the keys from the dict:
 
-   >>> d.clear()
-   >>> d.keys()
-   []
-   >>> len(d)
-   0
+    >>> d.clear()
+    >>> d.keys()
+    []
+    >>> len(d)
+    0
 
+The rest of the dict methods are delegated to the underlying BTree:
 
+    >>> c.has_key('beep')
+    True
+    >>> 'BEEP' in c
+    False
+    >>> c.get('nonexistent', 'default')
+    'default'
+
+
 Regression tests
 ----------------
 
 When setting an item that's already in the dict, the length is not
 increased:
 
-   >>> d.clear()
-   >>> d['foo'] = 'bar'
-   >>> d['foo'] = 'baz'
-   >>> len(d)
-   1
+    >>> d.clear()
+    >>> d['foo'] = 'bar'
+    >>> d['foo'] = 'baz'
+    >>> len(d)
+    1

Modified: zc.dict/trunk/src/zc/dict/ordered.txt
===================================================================
--- zc.dict/trunk/src/zc/dict/ordered.txt	2008-03-05 01:10:40 UTC (rev 84468)
+++ zc.dict/trunk/src/zc/dict/ordered.txt	2008-03-05 01:28:50 UTC (rev 84469)
@@ -5,6 +5,12 @@
 additional feature that it remembers the order in which items were added.
 It also provides the API to reorder the items.
 
+Importantly, the OrderedDict currently uses a PersistentList to store
+the order, which does not have good behavior for large sets, because the
+entire collection of keys must be pickled every time any key, or
+ordering, changes.  A BList would be a preferred data structure, but
+that has not yet been released.
+
    >>> from zc.dict import OrderedDict
    >>> d = OrderedDict()
    >>> d



More information about the Checkins mailing list