[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